Repository: sjbarag/brs
Pull request #422 (2020-05-20 20:01:43)

Add shorthand types
# Change Summary
There are several shorthand primitive types [in the Roku docs](https://developer.roku.com/docs/references/scenegraph/xml-elements/interface.md). This adds an alias for those types so they get resolved correctly.


Patch:
diff --git a/src/brsTypes/BrsType.ts b/src/brsTypes/BrsType.ts
index c7ff1b3..67c0e08 100644
--- a/src/brsTypes/BrsType.ts
+++ b/src/brsTypes/BrsType.ts
@@ -109,12 +109,14 @@ export function getBrsValueFromFieldType(type: string, value?: string): BrsType
     let returnValue: BrsType;
 
     switch (type.toLowerCase()) {
+        case "bool":
         case "boolean":
             returnValue = value ? BrsBoolean.from(value === "true") : BrsBoolean.False;
             break;
         case "node":
             returnValue = BrsInvalid.Instance;
             break;
+        case "int":
         case "integer":
             returnValue = value ? new Int32(Number.parseInt(value)) : new Int32(0);
             break;
@@ -130,6 +132,7 @@ export function getBrsValueFromFieldType(type: string, value?: string): BrsType
             returnValue = BrsInvalid.Instance;
             break;
         case "uri":
+        case "str":
         case "string":
             returnValue = value ? new BrsString(value) : new BrsString("");
             break;
diff --git a/src/brsTypes/components/ArrayGrid.ts b/src/brsTypes/components/ArrayGrid.ts
new file mode 100644
index 0000000..04c5eed
--- /dev/null
+++ b/src/brsTypes/components/ArrayGrid.ts
@@ -0,0 +1,58 @@
+import { FieldModel } from "./RoSGNode";
+import { AAMember } from "./RoAssociativeArray";
+import { Group } from "./Group";
+
+export class ArrayGrid extends Group {
+    readonly defaultFields: FieldModel[] = [
+        { name: "content", type: "node" },
+        { name: "itemSize", type: "array", value: "[0,0]" },
+        { name: "itemSpacing", type: "array", value: "[0,0]" },
+        { name: "numRows", type: "integer", value: "0" },
+        { name: "numColumns", type: "integer", value: "0" },
+        { name: "focusRow", type: "integer", value: "0" },
+        { name: "focusColumn", type: "integer", value: "0" },
+        { name: "horizFocusAnimationStyle", type: "string", value: "floatingFocus" },
+        { name: "vertFocusAnimationStyle", type: "string", value: "floatingFocus" },
+        { name: "drawFocusFeedbackOnTop", type: "boolean", value: "false" },
+        { name: "drawFocusFeedback", type: "boolean", value: "true" },
+        { name: "fadeFocusFeedbackWhenAutoScrolling", type: "boolean", value: "false" },
+        { name: "currFocusFeedbackOpacity", type: "float", value: "read-only" },
+        { name: "focusBitmapUri", type: "string", value: "" },
+        { name: "focusFootprintBitmapUri", type: "string", value: "" },
+        { name: "focusBitmapBlendColor", type: "string", value: "0xFFFFFFFF" },
+        { name: "focusFootprintBlendColor", type: "string", value: "0xFFFFFFFF" },
+        { name: "wrapDividerBitmapUri", type: "string", value: "" },
+        { name: "wrapDividerWidth", type: "float", value: "0" },
+        { name: "wrapDividerHeight", type: "float", value: "36" },
+        { name: "fixedLayout", type: "boolean", value: "false" },
+        { name: "numRenderPasses", type: "integer", value: "1" },
+        { name: "rowHeights", type: "array", value: "[]" },
+        { name: "columnWidths", type: "array", value: "[]" },
+        { name: "rowSpacings", type: "array", value: "[]" },
+        { name: "columnSpacings", type: "array", value: "[]" },
+        { name: "sectionDividerBitmapUri", type: "string", value: "" },
+        { name: "sectionDividerFont", type: "node" },
+        { name: "sectionDividerTextColor", type: "string" },
+        { name: "sectionDividerSpacing", type: "float", value: "0.0" },
+        { name: "sectionDividerWidth", type: "float", value: "0.0" },
+        { name: "sectionDividerHeight", type: "float", value: "0.0" },
+        { name: "sectionDividerMinWidth", type: "float", value: "0.0" },
+        { name: "sectionDividerLeftOffset", type: "float", value: "0.0" },
+        { name: "itemClippingRect", type: "array", value: "[ 0.0, 0.0, 0.0, 0.0 ]" },
+        { name: "itemSelected", type: "integer", value: "0" },
+        { name: "itemFocused", type: "integer", value: "0" },
+        { name: "itemUnfocused", type: "integer", value: "0" },
+        { name: "jumpToItem", type: "integer", value: "0" },
+        { name: "animateToItem", type: "integer", value: "0" },
+        { name: "currFocusRow", type: "float", value: "0.0" },
+        { name: "currFocusColumn", type: "float", value: "0.0" },
+        { name: "currFocusSection", type: "float", value: "0.0" },
+    ];
+
+    constructor(initializedFields: AAMember[] = [], readonly name: string = "ArrayGrid") {
+        super([], name);
+
+        this.registerDefaultFields(this.defaultFields);
+        this.registerInitializedFields(initializedFields);
+    }
+}
diff --git a/src/brsTypes/components/ComponentFactory.ts b/src/brsTypes/components/ComponentFactory.ts
index 309c6ea..092514b 100644
--- a/src/brsTypes/components/ComponentFactory.ts
+++ b/src/brsTypes/components/ComponentFactory.ts
@@ -1,4 +1,4 @@
-import { RoSGNode, Group, LayoutGroup, Rectangle, Label, Font, Poster } from "..";
+import { RoSGNode, Group, LayoutGroup, Rectangle, Label, Font, Poster, ArrayGrid } from "..";
 
 export enum BrsComponentName {
     Node = "Node",
@@ -8,6 +8,7 @@ export enum BrsComponentName {
     Label = "Label",
     Font = "Font",
     Poster = "Poster",
+    ArrayGrid = "ArrayGrid",
 }
 
 // TODO: update with more components as they're implemented.
@@ -32,6 +33,8 @@ export class ComponentFactory {
                 return new Font([], name);
             case BrsComponentName.Poster:
                 return new Poster([], name);
+            case BrsComponentName.ArrayGrid:
+                return new ArrayGrid([], name);
             default:
                 return;
         }
diff --git a/src/brsTypes/index.ts b/src/brsTypes/index.ts
index 4f7fe63..3afd138 100644
--- a/src/brsTypes/index.ts
+++ b/src/brsTypes/index.ts
@@ -48,6 +48,7 @@ export * from "./components/Rectangle";
 export * from "./components/Label";
 export * from "./components/Font";
 export * from "./components/Poster";
+export * from "./components/ArrayGrid";
 
 /**
  * Determines whether or not the given value is a number.
diff --git a/src/parser/ComponentScopeResolver.ts b/src/parser/ComponentScopeResolver.ts
index ae1c488..bcf707c 100644
--- a/src/parser/ComponentScopeResolver.ts
+++ b/src/parser/ComponentScopeResolver.ts
@@ -72,9 +72,10 @@ export class ComponentScopeResolver {
             let previousComponent = currentComponent;
             currentComponent = this.componentMap.get(currentComponent.extends);
             if (!currentComponent) {
-                return Promise.reject({
-                    message: `Cannot find extended component ${previousComponent.extends} defined on ${previousComponent.name}`,
-                });
+                console.error(
+                    `Cannot find extended component ${previousComponent.extends} defined on ${previousComponent.name}`
+                );
+                return Promise.resolve();
             }
             yield this.parserLexerFn(currentComponent.scripts.map(c => c.uri));
         }


Test patch:
diff --git a/test/brsTypes/components/ArrayGrid.test.js b/test/brsTypes/components/ArrayGrid.test.js
new file mode 100644
index 0000000..62208f8
--- /dev/null
+++ b/test/brsTypes/components/ArrayGrid.test.js
@@ -0,0 +1,77 @@
+const brs = require("brs");
+const { ArrayGrid } = brs.types;
+
+describe("ArrayGrid", () => {
+    describe("stringification", () => {
+        it("inits a new ArrayGrid component", () => {
+            let group = new ArrayGrid();
+
+            expect(group.toString()).toEqual(
+                `<Component: roSGNode:ArrayGrid> =
+{
+    change: <UNINITIALIZED>
+    focusable: false
+    focusedchild: invalid
+    id: 
+    visible: true
+    opacity: 1
+    translation: invalid
+    rotation: 0
+    scale: invalid
+    scalerotatecenter: invalid
+    childrenderorder: renderLast
+    inheritparenttransform: true
+    inheritparentopacity: true
+    clippingrect: invalid
+    renderpass: 0
+    muteaudioguide: false
+    enablerendertracking: false
+    rendertracking: disabled
+    content: invalid
+    itemsize: invalid
+    itemspacing: invalid
+    numrows: 0
+    numcolumns: 0
+    focusrow: 0
+    focuscolumn: 0
+    horizfocusanimationstyle: floatingFocus
+    vertfocusanimationstyle: floatingFocus
+    drawfocusfeedbackontop: false
+    drawfocusfeedback: true
+    fadefocusfeedbackwhenautoscrolling: false
+    currfocusfeedbackopacity: NaN
+    focusbitmapuri: 
+    focusfootprintbitmapuri: 
+    focusbitmapblendcolor: 0xFFFFFFFF
+    focusfootprintblendcolor: 0xFFFFFFFF
+    wrapdividerbitmapuri: 
+    wrapdividerwidth: 0
+    wrapdividerheight: 36
+    fixedlayout: false
+    numrenderpasses: 1
+    rowheights: invalid
+    columnwidths: invalid
+    rowspacings: invalid
+    columnspacings: invalid
+    sectiondividerbitmapuri: 
+    sectiondividerfont: invalid
+    sectiondividertextcolor: 
+    sectiondividerspacing: 0
+    sectiondividerwidth: 0
+    sectiondividerheight: 0
+    sectiondividerminwidth: 0
+    sectiondividerleftoffset: 0
+    itemclippingrect: invalid
+    itemselected: 0
+    itemfocused: 0
+    itemunfocused: 0
+    jumptoitem: 0
+    animatetoitem: 0
+    currfocusrow: 0
+    currfocuscolumn: 0
+    currfocussection: 0
+}`
+            );
+        });
+    });
+});
diff --git a/test/e2e/BrsComponents.test.js b/test/e2e/BrsComponents.test.js
index edf7f09..cd4e639 100644
--- a/test/e2e/BrsComponents.test.js
+++ b/test/e2e/BrsComponents.test.js
@@ -506,4 +506,24 @@ describe("end to end brightscript functions", () => {
             "10.4",
         ]);
     });
+
+    test("components/ArrayGrid.brs", async () => {
+        outputStreams.root = __dirname + "/resources";
+        await execute([resourceFile("components", "ArrayGrid.brs")], outputStreams);
+
+        expect(allArgs(outputStreams.stdout.write).filter(arg => arg !== "\n")).toEqual([
+            "arraygrid node type:",
+            "Node",
+            "arraygrid node subtype:",
+            "ArrayGrid",
+            "arraygrid node focusRow:",
+            "0",
+            "arraygrid node jumpToItem:",
+            "0",
+            "arraygrid as child wrapDividerWidth",
+            "1.23",
+            "arraygrid as child numRows",
+            "5",
+        ]);
+    });
 });
diff --git a/test/e2e/resources/components/ArrayGrid.brs b/test/e2e/resources/components/ArrayGrid.brs
new file mode 100644
index 0000000..e51981e
--- /dev/null
+++ b/test/e2e/resources/components/ArrayGrid.brs
@@ -0,0 +1,12 @@
+sub Main()
+    arraygrid = createObject("roSGNode", "ArrayGrid")
+    print "arraygrid node type:" type(arraygrid)
+    print "arraygrid node subtype:" arraygrid.subtype()
+    print "arraygrid node focusRow:" arraygrid.focusRow
+    print "arraygrid node jumpToItem:" arraygrid.jumpToItem
+
+    parent = createObject("roSGNode", "ComponentsAsChildren")
+    arraygridAsChild = parent.findNode("arraygrid")
+    print "arraygrid as child wrapDividerWidth" arraygridAsChild.wrapDividerWidth
+    print "arraygrid as child numRows" arraygridAsChild.numRows
+end sub
diff --git a/test/e2e/resources/components/ComponentsAsChildren.xml b/test/e2e/resources/components/ComponentsAsChildren.xml
index ae84abd..2db40d7 100644
--- a/test/e2e/resources/components/ComponentsAsChildren.xml
+++ b/test/e2e/resources/components/ComponentsAsChildren.xml
@@ -20,6 +20,9 @@
             <LayoutGroup id="layoutGroup"
                 layoutDirection="horiz"
                 horizAlignment="right" />
+            <ArrayGrid id="arraygrid" 
+                wrapDividerWidth="1.23"
+                numRows="5" />
         </Group>
     </children>
 </component>