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 --dap
You’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):
7250ms
4965ms
stick4k 3800x (OS 12.5):
5789ms
4342ms
express 3960x (OS 11.5):
8232ms
6111ms
.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:
dynamic
dynamic
object
(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@next
Here 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 sub
This was causing issues when transpiling a typecast expression like this::
sub addSomeProperty(obj)
(obj as roAssociativeArray).append({key: "value"})
end sub
So 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.references
We’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 BscFile
When 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 @arturocuya, powered by Astro
by