In this update

  1. Overview
  2. We need your help
  3. Editor
  4. New Roku File System Panel
  5. New Roku App Overlays Panel
  6. Improvements to document symbols
  7. Fix random disconnects in vscode panels
  8. Better stability during sideload
  9. Add some enhanced launch settings to support more diverse projects
  10. Fix crash when trying to copy numeric values to the clipboard
  11. Fix conditional compile syntax highlighting
  12. Debugging
  13. Optional Chainging Operator errors in debug console
  14. BrighterScript
  15. Allow negative patterns in diagnostic filters
  16. Prevent unused variable warnings on ternary and null coalescence expressions
  17. Add plugin hook for documentSymbol and workspaceSybmol
  18. Support when tokens have null ranges
  19. Community Tools
  20. bslint
  21. Fix safe colors
  22. brs
  23. Implemented roString methods startsWith() and endsWith()
  24. Align Arithmetic Operator Modulo behavior to match Roku
  25. Fixed path handling for Windows
  26. Implemented component roList
  27. Community Libraries
  28. brighterscript-formatter
  29. Add insertSpaceAfterConditionalCompileSymbol, fix conditional compile formatting
  30. Preview features
  31. bslint
  32. BrighterScript
  33. Removes CommentStatement and all comment tokens from Lexer output
  34. Adds type to const hovers and adds hover for for-each loop vars
  35. Improved variable shadowing logic
  36. AALiteral function m type is now AssociativeArray
  37. Treat class constructor functions as function types
  38. Better variable handling for unknown types
  39. Improves empty throw message
  40. Move scope.validate() into BscPlugin
  41. Better AA built-in property overrides
  42. Fixes bitwise operator typing
  43. Increase max param count to 63
  44. Faster validation for local variables
  45. Scope validation performance boost
  46. For Contributors
  47. BrighterScript null safety improvements
  48. Thank you

Overview

Welcome to the March 2024 edition of “What’s New in RokuCommunity.” Please consider subscribing to stay up to date with what’s happening in RokuCommunity.

We need your help

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:

Editor

New Roku File System Panel

This month we added a new panel called “Roku File System”. This panel will be avaiable anytime the app is running with RDB enabled, and will show all the files in your app as they exist on-device.

roku-file-system

New Roku App Overlays Panel

Another new panel we’ve added is called “Roku App Overlays”. This panel enables you to register images that will be overlayed onto your running application. This is incredibly useful when trying to build out UI elements against an existing mockup image. This panel will be active anytime the app is running with RTA enabled. Here’s a quick demo showing how it works. You can show and hide the image, change its transparency, rename the image, add multiple images, etc.

Improvements to document symbols

We’ve improved the document symbols included within vscode. Several symbol types were missing, such as constants, enums, and certain classes.

We also removed the leading namespace values from relevat symbols since they’re shown in grey next to the symbols anyway. This improves searchability for these symbols as vscode would get confused when typing the symbols without leading namespaces in some situations.

Before: image

After: image

Fix random disconnects in vscode panels

We’ve been having issues with some of the panels from the BrightScript Language vscode extension randomly disconnecting from the Roku device during debug sessions. We’ve fixed several bugs causing this issue. There’s not much to show here, but hopefully you will see more stability when using these features in the future.

Better stability during sideload

The Roku Device View panel in vscode works by capturing screenshots as fast as the device can generate them. We noticed this was causing issues when sideloading new app builds to the device, as we must be putting too much stress on the device during that time which causes the device to time out. To mitigate this, we now pause the device view screenshot capturing during the sideloading process. This has significantly reduced the failure rate during the sideloading process. Once the device successfully sideloads the app, we resume the screenshot behavior, so you shouldn’t notice any difference in experience.

image

Add some enhanced launch settings to support more diverse projects

As of vscode v2.46.0, you can now further customize your launch process. Many developers have custom build processes such as makefile or shell scripts. Historically, the vscode extension hasn’t supported this process because the extension needs to be in control over the entire process. However, we felt it was important for dev teams to be able to use as much of their existing build process as possible.

We’ve added the ability to register a custom packageTask that will bulid the .zip instead of having vscode build it. VSCode still needs to be the one moving files into the staging directory, but if you have a custom zipping process, this will now allow you to leverage that feature. Here’s an example launch.json with these new features:

{
    //this is a vscode "task" which should be registered in ./vscode/tasks.json
    "packageTask": "name-of-task-that-zips-your-app",
     //where should vscode put the files that are ready to be staged?
    "stagingDir": "./dist",
     //where did you put your zip?
    "packagePath": "./out/custom.zip"
}

We’ve also added a few missing launch.json settings such as stagingDir (not sure how that one went undocumented for so long…).

Fix crash when trying to copy numeric values to the clipboard

If you’ve ever used the “Roku Devices” panel, you may have noticed that you couldn’t copy numeric values to the clipboard. That has now been fixed as of vscode extension v2.46.1!

Before: image

After: image

Fix conditional compile syntax highlighting

We’ve fixed some issues with syntax highlighting for conditional compile items with spaces between # and the next keyword (we didn’t even know BrightScript supported spaces there!).

Before: image

After: image

Debugging

Optional Chainging Operator errors in debug console

We fixed a bug when evaluating optional chaining expressions in the vscode REPL or watch panel that would crash instead of properly evaluating the expression. Here are some examples of expressions that should now properly evaluate:

print m.top.gridState?.leftEdgeTime
print m.top.gridState?["leftEdgeTime"]
print m.top.gridState?.["leftEdgeTime"]

BrighterScript

Allow negative patterns in diagnostic filters

If you haven’t been using diagnosticFilters in brighterscript yet, you should definitely take a look at the docs. These filters support ignoring a list of diagnostics for a specific file or groups of files. Developers commonly use these to ignore errors in vendor libraries that they don’t have direct control over modifying (or don’t want to modify).

This month we added support for negated patterns in the src patters, which is makes the feature even more powerful. You can now do things like this:

"diagnosticFilters": [
    { "src": "vendor/**/*" }, //ignore all errors from vendor libraries
    { "src": "!*/**/*", "codes": [1000] } //except DO show this particular code everywhere
]

What’s great about this is you can even stack multiple patterns together to curate a very specific list of diagnostics, by combining negative and positive patterns, codes, etc.

Prevent unused variable warnings on ternary and null coalescence expressions

We’ve had a longstanding bug that when using enums in a ternary expression, the transpiled could would incorrectly inject those enum values into the bslib_ternary() call. This wouldn’t cause runtime errors since they were never referenced, but it did produce unused variable errors on-device.

Here’s an example of the issue. This ternary operation:

buttonBaseWidth = (nodeId = "closedCaptions") ? ClosedCaptionsButtonSize.Width : ThumbButtonSize.Width

Would transpile to:

buttonBaseWidth = (function(__bsCondition, ClosedCaptionsButtonSize, ThumbButtonSize)
    if __bsCondition then
        return 38
    else
        return 40
    end if
end function)((nodeId = "closedCaptions"), ClosedCaptionsButtonSize, ThumbButtonSize)

Notice the ClosedCaptionsButtonSize being passed as a variable? That causes an unused variable device warning in the console when the app is sideloaded.

BrighterScript v0.65.26 includes a fix for this issue, and now the names of these enums are omitted from the transpiled output (which is fine since the enums were injected into the inner function body already anyway.

buttonBaseWidth = (function(__bsCondition)
    if __bsCondition then
        return 38
    else
        return 40
    end if
end function)((nodeId = "closedCaptions"))

You can check out the pull request for how we solved this, or the original issue if you’re curious what the

Add plugin hook for documentSymbol and workspaceSybmol

Starting in BrighterScript v0.65.27, plugin authors can contribute their own document and workspace symbols by using thes enew plugin hooks:

  • beforeProvideDocumentSymbols

  • provideDocumentSymbols

  • afterProvideDocumentSymbols

  • beforeProvideWorkspaceSymbols

  • provideWorkspaceSymbols

  • afterProvideWorkspaceSymbols

We’ve moved the brighterscript logic into the internal brighterscript plugin, so plugin authors can review DocumentSymbolProcessor and WorkspaceSymbolProcessor for examples of how to contribute these symbols. It’s also worth looking at how we’ve implemented our AST walking to discover symbols, which can be found in this PR.

Support when tokens have null ranges

Many brighterscript plugins use Parser.parse() to generate AST used to replace existing code. This causes the generated sourcemaps to be very incorrect. To mitigate this, we added support for generating AST without any range information at all.

Now most expressions and statements can transpile to proper code without needing location information. There was a lot of internal brighterscript typescript code that didn’t like when AST nodes had null ranges and there may be some edge cases, but we believe we’ve fixed most of those issues.

Here’s how you can leverage this new functionality:

const tokens = Parser.parse('print hello', { trackLocations: false });

The tokens array will have all the same tokens, but none of them will have location information, making them much safer to inject into AST without messing with sourcemaps.

Community Tools

bslint

Fix safe colors

We’ve updated the broadcast safe color for white to now be #EBEBEB instead of #DBDBDB. In the future, we’d love to make this list configurable, so if you have any interest in contributing to this, let us know.

brs

The brs project is a BrightScript interpreter that runs off-device, and is implemented in javascript.

Implemented roString methods startsWith() and endsWith()

We’ve added runtime support for the startsWith() and endsWith() methods on the roString object. Here’s the new methods in action in the brs repl:

image

Align Arithmetic Operator Modulo behavior to match Roku

We discovered that the MOD operator in BrightScript always truncates the result value, even for float and double values. We’ve aligned the brs runtime to match this behavior.

Before: image

After: image

Fixed path handling for Windows

We fixed several Windows-specific crashes where brs was not correctly handling Windows path separators. We’ve fixed these bugs which should now allow brs to run more consistently in Windows environments.

Implemented component roList

We’ve added support for roList, and both File and String now use it.

Community Libraries

brighterscript-formatter

Add insertSpaceAfterConditionalCompileSymbol, fix conditional compile formatting

RokuCommunity’s brightscript and brighterscript formatter has gotten a a new formatting option called insertSpaceAfterConditionalCompileSymbol. This option manages spacing between the # and the following keyword. When true, the formatter will add a single space character, and when false it will remove all whitespace between them.

format-cond-compile

We’ve also fixed indentation issues with conditional compile tokens that have spaces after the # (like # if, # else if, etc…).

Preview features

bslint

As we create new v1 alpha releases of brighterscript, we’re also keeping the v1 belint alphas in sync. So for example, if you install brighterscript v1.0.0-alpha.28, you should also install bslint v1.0.0-alpha.28. There are breaking changes happening between each alpha release of brighterscript v1, which means bslint also needs to target that same bsc version.

BrighterScript

We’ve got another great month full of improvements to the brighterscript v1 alpha releases. Here are some of the highlights:

Removes CommentStatement and all comment tokens from Lexer output

Comments in BrighterScript AST have always felt like a hack. Many parsers from other languages (such as TypeScript, eslint, the roslyn compiler, etc…) store comments as trivia rather than actual nodes in the abstract syntax tree. As of brighterscript v1.0.0-alpha.28, we have now done the same. Here are the changes:

  • we’ve removed CommentStatement and CommentExpression. Comments now reside SOLELY in a new AstNode and token property called leadingTrivia.
  • TranspileState.transpileToken() will automatically transpile comments (if they exist) ahead of the token
  • To still indent comments before a “block closing token” (eg. }, end sub, etc), use TranspileState.transpileEndBlockToken()
  • Modified getSignatureHelp, getDocumentation, etc. to use leading trivia only

This is probably one of the impactful breaking changes in the BrighterScript v1 releases. We’ll have more information in the coming months, but you can always look through the brighterscript source code for how leading/trailing trivia is handled.

Adds type to const hovers and adds hover for for-each loop vars

We’ve added const types and for-each loop vars to the hover in VSCode.

image

image

image

Improved variable shadowing logic

Variable shadowing in brighterscript has always been a bit challenging. Previously, you couldn’t have a local variable share the same name as a global function. The same issue was present for classes, namespaces, interfaces, enums, consts, etc. This forced developers to find alternative local variable or parameter names, which could be quite frustrating.

Starting in brighterscript v1.0.0-alpha.28, we’ve improved this situation significantly. You can now declare a local variable that has the same name as a parent item, and the parent item is “shadowed”/hidden, meaning your local variable wins. You can read the docs to learn more about how all of this new logic works.

here’s some example code:

function alpha()
    print "global alpha()"
end function

function test()
    alpha() ' prints "global alpha()"
end function

namespace beta

    function alpha()
        print "beta.alpha()"
    end function

    function test()
        alpha() ' prints "beta.alpha()"
    end function

    namespace charlie

        function alpha()
            print "beta.charlie.alpha()"
        end function

        function test()
            alpha() ' prints "beta.charlie.alpha()"
        end function

    end namespace

end namespace

AALiteral function m type is now AssociativeArray

We fixed a bug where the m variable inside an anonymous function inside a class method was incorrectly thinking it was the m from the class itself. Here’s a screenshot of the error:

image

As of brighterscript v1.0.0-alpha.28, that m will now just be a plain AssociativeArray

Treat class constructor functions as function types

Starting in v1.0.0-alpha.28, when a Class constructor function is used outside of new it is now treated as a function type, allowing code completion and validation based on that.

Better variable handling for unknown types

We’ve fixed a bug when a parameter has an unresolved type that causing the variable to be marked as “unknown”.

Here’s the issue: bad-interface

And now we show better errors, like this: image

We’ve made the following fixes to mitigate the issue:

  • Any variable declared via assignment or as function param will not cause the “Cannot find …” Diagnostic
  • Adds validation for invalid type in the typeExpression in an assignment statement

Improves empty throw message

The BrighterScript transpiler tries its best to produce valid brightscript code, even if sometimes the original code was not valid. One such example is the throw statement. If you forget to include an error message, brighterscript would auto-include a generic "An error has occurred" message. However, that message didn’t align with the default message found on device. So we’ve aligned with that, and that message is now "User-specified exception". We recommend always writing your own messages so you can more clearly understand them throughout your code, but at least now the messages are aligned with what the device will produce.

Example. This:

sub main()
    try
        throw 'bs:disable-line
    catch e
    end try
end sub

Will now transpile to this:

sub main()
    try
        throw "User-specified exception"
    catch e
    end try
end sub

Move scope.validate() into BscPlugin

For contributors to BrighterScript, we’ve moved all of the logic from scope.validate() into the BscPlugin class, further aligning our internal plugin system with the exact same rules and restrictions that third party plugins follow. There’s not much to show here, you can check out the brighterscript#1105 to see the changes we made.

Better AA built-in property overrides

AssociativeArray types now follow the same pattern as Class types, where the built in members are from a different symbol provider, so if they are overriden, the overriden type info is used.

Here’s a screenshot of the original issue:

image

Fixes bitwise operator typing

We fixed a bug with bitwise and and or operators showing incorrect types in the type system.

Prior to v1.0.0-alpha.28, here’s what the type system would see: image image

And now we correctly show: image

Increase max param count to 63

Historically the BrightScript runtime would only support functions having a maximum of 32 parameters. However, sometime around Roku OS 11.5, they increased this limit to 64. We’ve updated this limit in brighterscript as well, so you can now utilize all of those extra function parameters.

Before: image

After: image

Faster validation for local variables

We’ve added significant validation performance improvements starting in v1.0.0-alpha.29. The first fix added some caching for local variable validations, checking only un-changed AstSegments for function shadowing if those segments make an assignment to a symbol that changed.

Before:

validate@local   ---------- 51.368 ops/sec
validate@0.65.26 --------- 101.435 ops/sec

After:

validate@local   --------- 286.331 ops/sec
validate@0.65.26 --------- 102.877 ops/sec

Scope validation performance boost

We’ve improved overall validation times for most scope validations. Here are some of the changes we made:

  • Refactored namespace linking to make better use of file-level caching
  • Adds significant changes to how validation is performed:
    • Whole scopes are culled from validation if there are not changes that effect that immediate scope
    • Better file culling for name shadowing checks based on changed symbols

Overall, this should cut initial validation time down to about 40%, and should make validation changes in editor much faster…

BEFORE:

% npm run validate

> jellyfin-roku@2.0.5 validate
> npx bsc --copy-to-staging=false --create-package=false

[10:21:34:1920 PM]  Using config file: "/roku/jellyfin-roku_2/bsconfig.json"
[10:21:34:1940 PM]  Loading 0 plugins for cwd "/roku/jellyfin-roku_2"
[10:21:34:2060 PM]  load files
[10:21:34:8270 PM]  load files finished. (620.515ms)
[10:21:34:8270 PM]  Validating project
[10:21:44:6830 PM]  Validating project finished. (9s855.268ms)

AFTER (this is log-level “info”):

% npm run validate

> jellyfin-roku@2.0.5 validate
> npx bsc --copy-to-staging=false --create-package=false --log-level=info

[11:44:09:6900 AM]  Using config file: "/roku/jellyfin-roku_2/bsconfig.json"
[11:44:09:6920 AM]  Loading 0 plugins for cwd "/roku/jellyfin-roku_2"
[11:44:09:7010 AM]  load files
[11:44:10:2920 AM]  load files finished. (590.650ms)
[11:44:10:2920 AM]  Validating project
[11:44:10:6730 AM]    Build component types
[11:44:10:7000 AM]    Build component types finished. (27.114ms)
[11:44:10:7010 AM]    Validate all scopes
[11:44:14:3260 AM]    Validate all scopes finished. (3s624.666ms)
[11:44:14:3260 AM]    Validation Metrics: filesValidated=305, fileValidationTime=276.499ms, fileInfoGenerationTime=103.664ms,
    programValidationTime=0.308ms, scopesValidated=139, totalLinkTime=600.8ms,
    totalScopeValidationTime=2s944.775ms, componentValidationTime=0.567ms
[11:44:14:3290 AM]  Validating project finished. (4s37.58ms)
[11:44:14:3300 AM]  Program.getDiagnostics()
[11:44:14:3380 AM]    diagnostic counts: total=54, after filter=50
[11:44:14:3380 AM]  Program.getDiagnostics() finished. (8.233ms)
[11:44:14:3400 AM]  Program.getDiagnostics()
[11:44:14:3430 AM]    diagnostic counts: total=54, after filter=50
[11:44:14:3430 AM]  Program.getDiagnostics() finished. (3.603ms)

For Contributors

BrighterScript null safety improvements

We’ve null safety issues in Statement and Expression. There isn’t much else to say here other than when we eventually address all of the null safety issues in the brighterscript codebase, we’ll be enabling it by default. This should help us catch a whole category of additional bugs at development time. You can review brighterscript#1033 for more information.

Thank you

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:

Contributions to roku-deploy:

Contributions to roku-debug:

Contributions to brighterscript-formatter:

Contributions to bslint:

Contributions to ropm:

Contributions to brs:

Home What's new Slack channel Newsletter Edit this website on Github

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 favorite by @arturocuya, powered by Astro