-
Notifications
You must be signed in to change notification settings - Fork 43
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
Conversation
There was a problem hiding this 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/extensions/Process.ts
Outdated
@@ -40,4 +42,20 @@ export const Process = new RoAssociativeArray([ | |||
}, | |||
}), | |||
}, | |||
{ | |||
name: new BrsString("setManifest"), |
There was a problem hiding this comment.
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:
brs/test/e2e/Localization.test.js
Lines 21 to 24 in 35d45df
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:
brs/test/e2e/resources/components/localization/source/main.brs
Lines 1 to 10 in 35d45df
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 |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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 😊
There was a problem hiding this 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/extensions/Process.ts
Outdated
@@ -40,4 +42,20 @@ export const Process = new RoAssociativeArray([ | |||
}, | |||
}), | |||
}, | |||
{ | |||
name: new BrsString("setManifest"), |
There was a problem hiding this comment.
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
src/brsTypes/components/RoAppInfo.ts
Outdated
impl: (interpreter: Interpreter) => { | ||
let title = RoAppInfo._manifest.get("title"); | ||
|
||
return title !== undefined ? new BrsString(title.toString()) : new BrsString(""); |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done, thanks
There was a problem hiding this 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 😃
test/e2e/BrsComponents.test.js
Outdated
manifest = preprocessor.getManifestSync( | ||
process.cwd() + "/test/e2e/resources/conditional-compilation" | ||
); | ||
RoAppInfo.manifest = manifest; |
There was a problem hiding this comment.
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).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed
src/brsTypes/components/RoAppInfo.ts
Outdated
export class RoAppInfo extends BrsComponent implements BrsValue { | ||
readonly kind = ValueKind.Object; | ||
|
||
private static manifest = PP.getManifestSync(process.cwd()); |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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()
.
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. |
There was a problem hiding this 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>(); |
There was a problem hiding this comment.
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!
fixes #537