Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(stdlib): Implement roAppInfo #643

Merged
merged 11 commits into from
Apr 30, 2021
Merged

Conversation

vbuchii
Copy link
Contributor

@vbuchii vbuchii commented Apr 12, 2021

fixes #537

@vbuchii vbuchii marked this pull request as draft April 12, 2021 10:42
@vbuchii vbuchii marked this pull request as ready for review April 13, 2021 13:44
@vbuchii vbuchii changed the title 537: implement RoAppInfo Issue #537: implement RoAppInfo Apr 13, 2021
Copy link
Collaborator

@lkipke lkipke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good so far, a few comments

src/brsTypes/components/RoAppInfo.ts Outdated Show resolved Hide resolved
src/brsTypes/components/RoAppInfo.ts Outdated Show resolved Hide resolved
test/e2e/resources/components/roAppInfo.brs Show resolved Hide resolved
@lkipke lkipke added e2e Affects this project's end-to-end test cases (the BrightScript sample files executed during testing) enhancement Any addition to this project's existing capabilities stdlib Affects the standard library included with this BrightScript implementation labels Apr 14, 2021
@vbuchii vbuchii requested a review from lkipke April 17, 2021 19:28
@@ -40,4 +42,20 @@ export const Process = new RoAssociativeArray([
},
}),
},
{
name: new BrsString("setManifest"),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like having extensions to customize testing, but are we just creating this function to enable e2e testing? I'm not sure there's another use-case for needing to dynamically change the manifest location (but I could also be wrong!).

For writing an e2e test, we can change the root property when executing a file. For example, the function tr looks for a file called en_US/translations.ts in the root directory. So when we're testing tr, we change root to be the necessary directory:

await execute([resourceFile("components", "localization", "source", "main.brs")], {
...outputStreams,
root: "test/e2e/resources/components/localization",
});

Then when we call tr from Brightscript, it finds the correct file:

sub main()
_brs_.process.setLocale("en_US")
print tr("Hello") ' => Bonjour
print tr("hello") ' => hello
print tr("Fare thee well") ' => Au revoir
obj = parseJson(tr("Not a straightforward string"))
print obj.hello[0] ' => "world"
print obj.foo ' => 123
end sub

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with Levi, let's use above suggestion if this was only set to support E2E testing

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @lkipke, @alimnios72
Thank you for your feedback. I did try to use a similar approach but was unable to reach the needed result. Maybe it because of using the internal cwd() function. Then I found in the codebase set locale function and decided to use that approach.

I added changes to avoid using the additional function, please review 😊

Copy link
Collaborator

@alimnios72 alimnios72 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left a few comments below but overall this looks pretty good!

src/brsTypes/components/RoAppInfo.ts Show resolved Hide resolved
@@ -40,4 +42,20 @@ export const Process = new RoAssociativeArray([
},
}),
},
{
name: new BrsString("setManifest"),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with Levi, let's use above suggestion if this was only set to support E2E testing

impl: (interpreter: Interpreter) => {
let title = RoAppInfo._manifest.get("title");

return title !== undefined ? new BrsString(title.toString()) : new BrsString("");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here and in below function you could use title != null .... which will check for null and undefined, otherwise if the value was null if will fail that check

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done, thanks

src/brsTypes/components/RoAppInfo.ts Show resolved Hide resolved
Copy link
Owner

@sjbarag sjbarag left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're definitely getting closer here! I'd like to avoid re-parsing the manifest file if possible, but my bigger concern is around the use of process.cwd() in a static property of RoAppInfo — that won't work for our end-to-end tests (which you worked around by manually assigning to a private field), and will subtly break other use-cases as they arise.

Do you happen to know which manifest file is used when createObject("roAppInfo") is called from a ComponentLibrary? I imagine that will complicate things here a bit 😃

src/brsTypes/components/RoAppInfo.ts Show resolved Hide resolved
manifest = preprocessor.getManifestSync(
process.cwd() + "/test/e2e/resources/conditional-compilation"
);
RoAppInfo.manifest = manifest;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Watch out! Since this value is never reset, any test that requires an accurate RoAppInfo.manifest after this will fail in a very unexpected way. There's likely a way to solve this problem without explicitly reading an arbitrary manifest as part of this test (more details in a separate comment).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

export class RoAppInfo extends BrsComponent implements BrsValue {
readonly kind = ValueKind.Object;

private static manifest = PP.getManifestSync(process.cwd());
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Passing process.cwd() will introduce some very subtle bugs when the root directory for brs isn't process.cwd() — it often isn't in the end-to-end tests in this project!

Since we parse the manifest as basically the first step of this project (before brightscript files are even loaded!) I'm curious if we could re-use the parsed manifest, possibly by storing it as a property on the Interpreter instance that gets created early-on?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @sjbarag
I've introduced the manifest as property on the Interpreter instance as you suggested. So, we no longer re-parse manifest and don't use process.cwd().

@vbuchii
Copy link
Contributor Author

vbuchii commented Apr 21, 2021

We're definitely getting closer here! I'd like to avoid re-parsing the manifest file if possible, but my bigger concern is around the use of process.cwd() in a static property of RoAppInfo — that won't work for our end-to-end tests (which you worked around by manually assigning to a private field), and will subtly break other use-cases as they arise.

Do you happen to know which manifest file is used when createObject("roAppInfo") is called from a ComponentLibrary? I imagine that will complicate things here a bit 😃

I was unable to find any related info about that in the Roku SDK. So, I've tested on a sample and seen that it is used the manifest file from root of the project. In other words, regardless of where the object is created, the main manifest is used.

@vbuchii vbuchii requested a review from sjbarag April 21, 2021 17:49
Copy link
Owner

@sjbarag sjbarag left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work, @vbuchii ! Thanks for the improvements 😃

@@ -94,6 +97,14 @@ export class Interpreter implements Expr.Visitor<BrsType>, Stmt.Visitor<BrsType>
return this._environment;
}

get manifest() {
return this._manifest != null ? this._manifest : new Map<string, ManifestValue>();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooooh returning an empty map is a great idea!

@sjbarag sjbarag changed the title Issue #537: implement RoAppInfo feat(stdlib): Implement roAppInfo Apr 30, 2021
@sjbarag sjbarag merged commit 4d24b7c into sjbarag:main Apr 30, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
e2e Affects this project's end-to-end test cases (the BrightScript sample files executed during testing) enhancement Any addition to this project's existing capabilities stdlib Affects the standard library included with this BrightScript implementation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

roAppInfo is not implemented.
4 participants