Overview

We had another solid month full of great improvements to the RokuCommunity tools, even though many of us were off for part of the month to celebrate the holidays. I think that goes to show just how dedicated some of our community contributors are, and we are so grateful for their help and support!

There are many updates in this version that we hope you’ll like, some of the key highlights include:

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 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:

Issue of the month

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 RokuCommunity codebases.

This month, we’d like to draw attention to vscode-brightscript-language#238. Rendezvous tracking is a very useful feature in the VSCode extension. However, we have very little documentation explaining how to use it, how to enable it, etc. We’re asking for the community’s help to create a documentation page for this so that more developers can utilize the feature. The docs are written in markdown on the vscode-brightscript-language repo, and published to https://rokucommunity.github.io/vscode-brightscript-language/

image

If you’re interested in working on this feature, please comment on the github issue or reach out to us on Slack

Editor

Add check for onChange function

We’ve added a new XML validation that warns about missing functions referenced by onChange XML handlers.

image

Fix spelling mistake in lsp message

We fixed a small spelling mistake in the “Can’t find language server” error message.

image

Add a few missing brightscript.debug settings

We noticed a few brightscript.debug settings were missing from the schema, meaning you would get warnings when trying to use them in user/workspace settings. We’ve added the missing items so now you should have better intellisense when editing the settings, and no more warnings.

Debugging

Support a configurable port for SceneGraphDebugCommandController

We have added the ability to override SceneGraph debug server port (normally 8080). This is mostly useful for port-forwarding or emulator/simulator situations, because Roku devices do not support overriding this port.

image

BrighterScript

Add optional modifier for interface and class members

We’ve finally added support for optional class and interface members. We don’t really do anything with them right now, but this is in preparation for the upcoming type tracking features, and it enables developers to better document their interfaces and classes.

You can read more about it in the class or interface docs, but here’s a quick sample:

class Video
    url as string
    length as float
    optional subtitleUrl as string
    optional rating as string
    optional genre as string
end class

Correct RANGE in template string when dealing with quotes in annotations

We fixed a bug where " characters in template strings would mistakenly increment the line number of future tokens, causing incorrect token positions for the remainder of the file. This didn’t cause problems with the transpiled code, but makes for a very poor debugging (sourcemap) and editing (diagnostic position) experience.

Before the fix: template-string-position-fix

After the fix: template-string-position-fix-fixed

Fix transpile for non-namespaced enums in namespaced functions

We fixed a critical transpile bug in brighterscript where non-namespaced enums used in namespaced function blocks would be left un-transpiled! This should be fixed now in brighterscript v0.65.13 or above

image

Fix multi-namespace class inheritance transpile bug

Fixes a bug with class inheritance where an ancestor 2+ levels higher would get the wrong super index, but only when that ancestor was a namespace-relative reference from a different namespace than the originating class.

Consider this code example

namespace alpha
    class One
    end class
end namespace

namespace beta
    class Two extends alpha.One
    end class

    class Three extends Two
    end class
end namespace

namespace charlie
    class Four extends beta.Three
    end class
end namespace

The inheritance chain for Four is: Four -> beta.Three -> Two -> alpha.One. The bug occurs when trying to find Two because it’s a namespace-relative lookup. BrighterScript was trying to find charlie.Two instead of beta.Two.

This resulted in the wrong super index, causing a stack overflow at runtime. We fixed it, so now this code should transpile correctly.

Prevent errors when using enums in a file that’s not included in any scopes

We’ve fixed a bug in the brighterscript transpiler that occurred when a file which uses enums is not found in any scope. We have a large unit test suite, but somehow the relevant unit test wasn’t testing enums and was suppressing errors. We fixed the error and this situation should no longer crash the transpiler.

Here’s the error:

Error when calling plugin BscPlugin.beforeFileTranspile: TypeError: Cannot read properties of undefined (reading 'getEnumMemberFileLink')
    at BrsFilePreTranspileProcessor.getEnumInfo (../node_modules/brighterscript/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js:38:32)
    <long stack trace here>

Load manifest from files array instead of root of project

The program is currently set to load the manifest file from the project’s root. This isn’t very flexible, and it causes some issues for projects which generate their manifests in a pre-compile step, (i.e., bs_const values not getting read and causing code blocks to be removed erroneously).

We’ve modified BrighterScript to find and load the manifest file first (rather than loading it on-demand like was previously implemented). This should mitigate most of the issues related to this.

Community Tools

brs

Replace npm package luxon with day.js for roDateTime and roTimespan

In the BRS emulator project we updated the internal NodeJS date library from luxon to day.js. This gives us more control of the specific formats Roku supports when parsing ISO dates, also this package is smaller than luxon. This allowed us to fix a few bugs related to printing dates so they more accurately align with actual Roku devices.

Fix optional chaining implementation side effect

We fixed the optional chaining implementation in the BRS emulator. There was a bug that affected the parsing of inline if with the ? (print) statement.

Code like this should now run correctly in the emulator:

function test_issue_30()
    testA = ["apple", 2, "banana", "orange", 5, "grape", "pear"]
    for fruit = 0 to testA.count()-1
        ' this was the line causing issues
        if type(testA[fruit]).inStr(0,"String") = -1 ? testA[fruit]
    next
end function

Implemented missing ifEnum methods in roArray and roAssociativeArray

We added several missing interface methods to the BRS emulator:

  • Methods from ifEnum: isNext(), next(), reset() (array and AA)
  • Methods from ifArrayGet/Set: getEntry(), setEntry() (array)

We also now properly sort AA items when printing the object (same behavior as Roku)

Add stub try/catch implementation

We’ve added partial support for try/catch. Implementing try/catch/throw takes a good bit of work in the interpreter, so it has been split into two parts. This initial implementation includes parsing try/catch/end try (without throw), and always executes only the try block to maintain backwards compatibility.

It’s a weird partial state, but the alternative is a massive pull request that can’t be reasonably reviewed or understood.

Here’s the feature working in action:

brs-try

Component XML path parsing was failing on edge case

We fixed a bug in the brs interpreter where, when parsing an empty list of additional directories, the code was finding invalid XML files under node_modules when the package was installed in posix OS (Mac, Linux).

Preview features

We’ve made more improvements to the BrighterScript v0.66 alphas, specific around type tracking and stability. Here are some of the highlights:

Fixed bug when extending roSGNodeNode

We fixed a crash when an interface extends the roSGNodeNode interface. You can now successfully create interfaces like this:

namespace myApp
    interface CommandManager extends roSGNodeNode
        commandName as string
    end interface
    function doesItWork(thing as myApp.CommandManager)
        ? thing.commandName
    end function
end namespace

Namespace validation fix

We fixed a bug that was incorrectly showing diagnostics when there was a class with the same partial name as a similar namespace.

namespace some.nameSpace
    function anything()
    end function
end namespace
namespace some
        'this was causing issues, but we fixed it!
        class name
        end class
end namespace

Fixes Class Constructor used as function transpilation and validation

The type system now correctly identifies that class constructors are also functions. So things like this will no longer show diagnostics:

sub callSomeFunc(someFunc as function)
    someFunc()
end sub
class MyKlass
end class
sub doStuff()
    'this is okay now!
    callSomeFunc(MyKlass)
end sub

Classes do not include AA members

When defining a class, you would expect the class to contain only the members you’ve explicitly defined. However, we found that all of the ifAssociativeArray fields were present, which were allowing classes to be treated like AAs by default. While classes are implemented as AAs under the hood, we felt that this was too permissive and counter to the goal of classes.

To mitigate this, we have removed all of the ifAssociativeArray methods from classes by default. If you want to treat your class like an “anything goes” AA, you can simply implement that interface. Like this:

class Person
    name as string
    sub setAge(age as number)
        m.age = age
        ' ~~~ this is not allowed anymore
    end sub
end class

class PersonAA implements ifAssociativeArray
    name as string
    sub setAge(age as number)
        'this is totally fine because we have extended ifAssociativeArray
        m.age = age
    end sub
end class

Use regex for faster manifest/typedef detection

Adds slightly faster performance to the logic updated in #942 when dealing with large file lists. This probably doesn’t make much difference in practice, but hey, free cycles are free cycles!

The javascript engine will compile and cache regex expressions, so we can use them inline. We also avoid calling `.toLowerCase() because it’s fairly expensive.

image

The end result is slightly faster initial brighterscript build times.

Remove post-transpiled symbols from .bs code completion

We fixed a bug that was incorrectly showing transpiled versions of symbols when editing brighterscript files.

Like this:

namespace Alpha
    sub beta()
        print "hello"
    end sub
    sub gamma()
        ' completions here should NOT have Alpha_beta or Alpha_gamma
    end sub
end namespace

Fix out-of-date transpile blocks in docs

Fixes a few docs “view transpiled code” blocks that were out of date from their sample code.

General purpose name collision diagnostic

We’ve added some great new diagnostics focused on detecting name collisions. Here are some examples:

image

image

image

Make roSGNode and roSGNodeNode the same

When we first introduced the native types (like Node, roSGNode, roSGNodeLabel, etc…), we thought it made sense for Node and roSGNode to be different, so we made interfaces called roSGNode and roSGNodeNode respectively. However, in practice we found that it was just more confusing than helpful. So starting in v0.66.0-alpha.11 roSGNode and roSGNodeNode have been merged into a single interface called roSGNode. In almost every situation, you can just use roSGNode. Let us know if you have some practical use case for needing to mark something as Node instead.

For Contributors

Use getDeviceInfo from roku-deploy

Last month we improved the rokuDeploy.getDeviceInfo() method to be more library friendly to our NodeJS projects. This month we removed our custom fetching of device-info in favor of the rokuDeploy.getDeviceInfo() function. This shouldn’t have any visual impacts, but just know that under the hood we’ve unified our device-info access so that bug fixes are more easily shared across all the RokuCommunity projects.

fix the create-package script

Last month we introduced the create-package github action support. However, we found a few bugs. So this month we added a few fixes:

  • builds proper urls to packages by excluding @ and _ symbols.
  • specify the --title so the release doesn’t accidentally use the current branch name.

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 brs:

  • @lvcabral (Marcelo Lv Cabral)
    • fix(components): Replacing package luxon by day.js on roDateTime and roTimespan #28 (PR #29)
    • fix(parser,lexer) Optional chaining implementation side effect #30 (PR #31)
    • feat(components): Implemented missing ifEnum methods in roArray and roAssociativeArray (PR #33)
    • feat(lex,parse): Add stub try/catch implementation (PR #34)
    • fix(lib): Component XML path parsing was failing on edge case (PR #37)
  • @TwitchBronBron (Bronley Plumb)
    • Adds create-package CI build for quicker iteration (PR #36)

Contributions to promises:

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