In this update
Welcome to the January 2024 edition of “What’s New in RokuCommunity.” Please consider subscribing to stay up to date with what’s happening in RokuCommunity.
The RokuCommunity projects are maintained by a relatively small group of developers (mostly volunteers), and we have a growing list of unresolved issues. We need your help! There are many different ways you can contribute. Whether it’s addressing bugs, improving documentation, introducing new features, or simply helping us manage our expanding list of GitHub issues, your involvement would be greatly appreciated. We are more than happy to guide you in finding the most suitable contribution method that aligns with your interests. To learn more about how you can contribute, feel free to reach out to us on Slack, or explore the existing GitHub issues:
In this section, we highlight a specific issue where we could benefit from the community’s assistance in finding a solution. These problems are generally straightforward to address, and serve as an excellent opportunity to become acquainted with the various RokuCommunity codebases.
This month, we’d like to highlight bslint#41. Many linters support enforcing that all files have a trailing newline, which ensures consistency across your project. @rokucommunity/bslint does not currently have a rule for this, which is something we’d love to see added. Here’s how the error looks in a typescript project using eslint:
If you’re interested in working on this feature, please comment on the github issue or reach out to us on Slack
We fixed a few bugs in the “Device View” panel related to downloading a screenshot. Previously, without continuous screenshot capture enabled, the first screenshot would not download automatically, requiring a manual ‘refresh’ to initiate the download. Now it requests an initial screenshot which mitigates the issue.
We’ve improved the way certain errors are presented in vscode by showing them in a modal dialog box. Previously many of these errors were shown in a little toast popup at the bottom right of vscode which can easily be missed. Users were regularly frustrated when vscode would fail to launch a debug session, so hopefully this will help draw more visibility to certain types of errors. The most common error is a bad password.
Here’s a screenshot of the new popup:
stagingDir properly in DebugConfigurationProviderWe’ve deprecated the stagingFolderPath launch.json option in favor of the more standard stagingDir property. Both will still work for a while, but we recommend you move to stagingDir so you don’t see those pesky “deprecated” messages in your launch.json. stagingDir wins, and if not set, check for stagingFolderPath.
Along with that, we also fixed a bug with debug sessions and launch.json files related to stagingDir and stagingFolderPath when stagingDir is also present in a root-level bsconfig.json. Now it should properly load the stagingDir and (deprecated) stagingFolderPath properly when specified by launch.json.
We’ve improved how the brightscript and BrighterScript formatter handles spaces between objects. It should now properly remove whitespace between anything separated by a dot. Here are some examples:
We added better error detection for specific debug session failures, especially when uploading the ZIP file fails. You should now see a nice popup with a better error message.
There’s a new launch.json setting called controlPort which is used to interact with the debug protocol.
Most developers won’t need to change this, but if you’re debugging through port forwarding, using an emulator, or some other nonstandard means, this should enable you to properly configure your launch settings.
We added support for running roku-debug in Debug Adapter Protocol (DAP) mode for use in IDEs.
roku-debug is the library that powers the debug session within vscode. However, with this setting, you can now use roku-debug to power debug sessions in other IDEs (like eclipse, vim/neovim, emacs, etc.). This should work with any editor that supports the debug adapter protocol.
You can activate this mode like this:
npx roku-debug --dapYou’ll typically need to configure your IDE to execute the command mentioned above. If you’ve integrated this functionality into an IDE, please let us know so we can update our documentation to show how to configure it! Here’s an example of how to configure DAP mode in Neovim.
We’ve added a new BrighterScript config property called pruneEmptyCodeFiles which defaults to false. When set to true, brightscript files that are considered empty won’t be published during transpilation. It also adds a canBePruned property to the Brs and XML files.
Currently Brs files are considered empty if they don’t contain a FunctionStatement, MethodStatement, or a ClassStatement. (let us know if we missed one)
This will also remove imports of empty scripts. If a brightscript file that an xml files references has their canBePruned field return false, the associated import will be removed too.
On a large internal project, this resulted in significant compile-time speedups.
ultra 4800x (OS 12.5):
7250ms4965msstick4k 3800x (OS 12.5):
5789ms4342msexpress 3960x (OS 11.5):
8232ms6111ms.program to the builder BEFORE emitting afterProgramCreate eventFor BrighterScript plugin authors, we fixed a small bug where where the ProgramBuilder doesn’t have a reference to .program when the afterProgramCreate event fires. We solved this by assigning .program before emitting the event.
libpkg: prefixWe fixed a bug in where component libraries that use libpkg:/ scheme for script imports would fail to find files.
You can now use libpkg:/ in xml script imports as well as BrighterScript import statements.
These both work now!
BrighterScript has added some safeguards around manifest loading to improve the way plugins can interact with it. There’s a hidden _manifest file on the Program class in BrighterScript. Some plugins use/abuse this to modify manifest values (to apply some preprocessing or sanitization).
However, there have historically been some strange timing issues around this process. To mitigate those issues, BrighterScript will now avoid replacing the manifest on startup if a plugin has already overwritten it.
If you weren’t aware, we’re working on a major revision of BrighterScript that includes type tracking, much better type safety, and many other improvements.
Some of the new features are things like:
To simplify testing BrighterScript v1 and facilitate switching back to v0, we backported the above syntaxes into the v0 releases. This means you can write newer syntax and commit that code without needing to undo it.
Now keep in mind, these new syntax features provide NO additional validation in the v0 release line.
In transpiled code:
dynamicdynamicobject (just like Classes/interfaces)Even if you’re not using/testing the v1 alphas, it might be worth using some of this new syntax just to more cleanly document your code. You can view all of the supported syntax in this unit test, but here are some examples:
We’ve added a new BrighterScript plugin hook for go to definition. Plugins can define beforeProvideDefinition, provideDefinition, or afterProvideDefinition to add more entries into the results of that operation.
We converted the internal BrighterScript go to definition to leverage these same plugin hooks. You can check that out in BscPlugin.ts, but here’s a sample:
We’ve fixed parsing and transpile issues with multi-index IndexedGetExpression and IndexedSetStatement.
We’ve made a few improvements to the brs emulator:
You can check out the @rokucommunity/brs#39 for more information.
The original method for identifying the context (m object) for Callables relied on re-evaluating the source during a dot-chained call, that had performance issues, and caused the side effect of issue #9. That solution did not solved the performance issue fully.
In the new solution, we save a reference for the context for each callable, eliminating the need of re-evaluation, and fixed all side effects.
The end result is that there should no longer be a performance issue for calling dot chained calls.
GetInterface() and FindMemberFunction() now properly boxing parametersBoth of the methods GetInterface() and FindMemberFunction() were not properly boxing parameters to behave like a Roku device. These have been fixed as of @rokucommunity/brs v0.45.4
We’re transitioning BrighterScript towards a v1.0.0 release!
As we’ve been working on the BrighterScript v0.66 alphas, we noticed that there were more and more breaking changes that we wanted to implement. It became clear that we were actually implementing a full major version change.
BrighterScript was introduced as an experiment, that slowly grew into a product that is relied on by many production applications on a daily basis. At this point, we owe it to the community to signal that we have confidence in the project. We can think of no better way to do that than to move to a v1 release.
We’re hopeful that the v1 release will be ready by this summer, but we can’t guarantee a release date at this time (we’re very busy here at RokuCommunity). You can track our progress in the v1.0.0 milestone.
At the time of this publication, the latest BrighterScript v1 alpha is v1.0.0-alpha.27. You can try out the latest version of BrighterScript v1 alphas by running:
npm install brighterscript@nextHere are some enhancements that we’ve added to the brighterscript v1 alphas this month:
The BrightScript runtime doesn’t like when parentheses are used exclusively to wrap a variable. For example, this will cause a run-time error:
sub addSomeProperty(obj)
      (obj).append({key: "value"})
end subThis was causing issues when transpiling a typecast expression like this::
sub addSomeProperty(obj)
      (obj as roAssociativeArray).append({key: "value"})
end subSo to mitigate that, we’ve fixed the transpiler to so that if an expression that is grouped is a typecast, it does not include the parentheses.
We’ve added diagnostics for setting unknown fields of classes
private or protected class members externallyWe’ve added diagnostics for accessing private or protected class members when you shouldn’t have access to them.
Private members are available in the class that defined them. Protected members are available in the class that defined them, and all sub classes.
true, false, invalid to completion resultsWe’ve added true, false, and invalid to completion items when appropriate.
We now ensure that function parameters are included in completion results, even if you’re at the end of the function block. private and protected class members only are included in completion results when they are accessible
Parser.referencesWe’ve completely removed the Parser.references collection from BrighterScript. Historically, this was used to improve performance for plugins. However, the AST walking logic is significantly faster now, and we have much better patterns and AST detection mechanisms, so we have decided to eliminate Parser.references.
We’ve removed it because it causes confusion for plugins when trying to figure out how to properly make AST edits. Often an AST edit wouldn’t update the Parser.references collection and thus making future plugin modifications complicated or out of sync.
If you’re using this in your plugin, please consider switching to an AST walk function to find these items.
File interface to BscFileWhen the file API first landed, we had been using the interface name File. However, there’s already a global interface with that name in TypeScript, which caused lots of confusion when writing plugins. To mitigate this, we have renamed our interface BscFile. TypeScript will correctly prompt for imports when using this interface, and it no longer collides with the global interface.
We fixed a bug where a const and a function are not allowed to have the same name across different namespaces. This is now supported (as expected).
XML fields with type="color" can now accept strings or integers.
We updated BrighterScript’s internal understanding of <interface> function and field entries as defined here: https://developer.roku.com/docs/references/scenegraph/xml-elements/interface.md#attributes
We also fixed a bug with the way type="array" was handled, so that should no longer be causing diagnostics when used correctly.
findChildren function on AstNodeWe’ve added a new method on AstNode called .findChildren() to support finding all nodes of a specific type (like namespaces, classes, consts, etc). The matcher is just a function, so the evaluation can work for anything.
We’ve made some large changes to the structure of the BrighterScript readme:
List of changes:
bsconfig.json example, copied from the brighterscript-template projectignoreErrorCodes flag in “bs ignore” documentationWe’ve started the process of converting the entire BrighterScript codebase to be null safe (by enabling the strictNullChecks tsconfig.json setting). This month we’ve made some great progress. There’s not much user-facing to discuss, but feel free to look through #996 and #1000.
We’ve overhauled the create-vsix github action to improve inter-project linking when building custom vsix. It should be much better at building vsix that depend on changes that span multiple projects all having the same branch name.
For contributors, here’s what you need to know:
create-vsix tag to a PRvscode-brightscript-language, roku-deploy, BrighterScript, etc…) all have the same branch nameGitHub Actions will auto-generate a new vsix every time you push code to the PR, and a bot will comment with instructions on how to install that vsix.
You can see an example on this PR, but here’s a screenshot:
install-local and watch-all scriptsThe install-local script was only creating links between sibling projects into vscode-brightscript-language. However, some of the other projects depend on each other as well, so they should all be inter-linked.
So we updated the watch-all script to run the projects in order as well so we ensure the dependent projects are built before spinning up the next watcher. This does have the downside of showing all package.json and package-lock.json files as modified, but you can just undo the changes and run npm install local again when you need to get changes.
Last but certainly not least, a big Thank You to the following people who contributed this month:
Contributions to vscode-brightscript-language:
Contributions to brighterscript:
File interface to BscFile (PR #1013)Parser.references (PR #1021)findChildren function on AstNode (PR #1010).program to the builder BEFORE emitting afterProgramCreate event (PR #1011)Contributions to roku-debug:
Contributions to brighterscript-formatter:
Contributions to bslint:
create-package github action support (ebea19b)Contributions to brs:
Legal notice
The views and opinions expressed in this website and all of its pages are those from within our open source community and do not represent the views or positions of Roku, Inc. or any entities they represent.
Designed with by @arturocuya, powered by Astro