From d02af853bbc57e20a13b410857dd75a35277485a Mon Sep 17 00:00:00 2001 From: Anya Tokar Date: Wed, 24 Nov 2021 14:22:37 -0500 Subject: [PATCH 01/12] add shallow clone method and tests --- src/brsTypes/components/RoSGNode.ts | 37 ++++++++++ test/brsTypes/components/RoSGNode.test.js | 89 ++++++++++++++++++++++- 2 files changed, 125 insertions(+), 1 deletion(-) diff --git a/src/brsTypes/components/RoSGNode.ts b/src/brsTypes/components/RoSGNode.ts index f4833ea8..26aa9d30 100644 --- a/src/brsTypes/components/RoSGNode.ts +++ b/src/brsTypes/components/RoSGNode.ts @@ -372,6 +372,7 @@ export class RoSGNode extends BrsComponent implements BrsValue, BrsIterable { this.callfunc, this.issubtype, this.parentsubtype, + this.clone, ], ifSGNodeBoundingRect: [this.boundingRect], }); @@ -1695,6 +1696,41 @@ export class RoSGNode extends BrsComponent implements BrsValue, BrsIterable { }, }); + private clone = new Callable("clone", { + signature: { + args: [new StdlibArgument("isDeepCopy", ValueKind.Boolean)], + returns: ValueKind.Object, + }, + impl: (interpreter: Interpreter, isDeepCopy: BrsBoolean) => { + let copy = createNodeByType(interpreter, new BrsString(this.nodeSubtype)); + + let originalFields = this.getFields(); + let newFields = new RoAssociativeArray([]); + + let addReplace = newFields.getMethod("addreplace"); + + for (let [key, value] of originalFields) { + if (addReplace) { + addReplace.call( + interpreter, + new BrsString(key), + getBrsValueFromFieldType(value.getType(), value.toString()) + ); + } + } + + if (!(copy instanceof BrsInvalid)) { + let update = copy.getMethod("update"); + + if (update) { + update.call(interpreter, newFields, BrsBoolean.True); + } + } + + return copy; + }, + }); + /* Returns the subtype of this node as specified when it was created */ private subtype = new Callable("subtype", { signature: { @@ -1893,6 +1929,7 @@ function addChildren( let setField = newChild.getMethod("setfield"); if (setField) { let nodeFields = newChild.getFields(); + for (let [key, value] of Object.entries(child.fields)) { let field = nodeFields.get(key.toLowerCase()); if (field) { diff --git a/test/brsTypes/components/RoSGNode.test.js b/test/brsTypes/components/RoSGNode.test.js index 24523f7d..c060a2c9 100644 --- a/test/brsTypes/components/RoSGNode.test.js +++ b/test/brsTypes/components/RoSGNode.test.js @@ -929,6 +929,7 @@ describe("RoSGNode", () => { ]); let addFields = node.getMethod("addfields"); + let update = node.getMethod("update"); let getField = node.getMethod("getfield"); expect(update).toBeTruthy(); @@ -2501,7 +2502,6 @@ describe("RoSGNode", () => { it("returns the parent subtype", () => { let markupNode = new MarkupGrid(); let parentsubtype = markupNode.getMethod("parentsubtype"); - let result = parentsubtype.call(interpreter, new BrsString("MarkUpGrid")); expect(result.value).toBe("ArrayGrid"); }); @@ -2514,6 +2514,93 @@ describe("RoSGNode", () => { expect(result).toBe(BrsInvalid.Instance); }); }); + + describe("clone", () => { + let interpreter, originalNode; + + beforeEach(() => { + interpreter = new Interpreter(); + originalNode = new MarkupGrid([ + { name: new BrsString("field1"), value: new BrsString("a string") }, + { name: new BrsString("field2"), value: new Int32(-19999) }, + { name: new BrsString("field3"), value: BrsBoolean.False }, + { name: new BrsString("<33"), value: new BrsString("") }, + ]); + + child1 = new RoSGNode([ + { name: new BrsString("child"), value: new BrsString("1") }, + ]); + child2 = new RoSGNode([ + { name: new BrsString("child"), value: new BrsString("2") }, + ]); + child3 = new RoSGNode([ + { name: new BrsString("child"), value: new BrsString("3") }, + ]); + grandchild1 = new RoSGNode([ + { name: new BrsString("grandChild"), value: new BrsString("4") }, + ]); + grandchild2 = new RoSGNode([ + { name: new BrsString("grandChild"), value: new BrsString("5") }, + ]); + + let appendGrandchildren = child1.getMethod("appendchildren"); + appendGrandchildren.call(interpreter, new RoArray([grandchild1, grandchild2])); + + let appendChildren = originalNode.getMethod("appendchildren"); + appendChildren.call(interpreter, new RoArray([child1, child2, child3])); + }); + + it("return type is same as of subject", () => { + let cloneMethod = originalNode.getMethod("clone"); + let copyNode = cloneMethod.call(interpreter, new BrsBoolean(true)); + + expect(copyNode).toBeInstanceOf(RoSGNode); + expect(copyNode).toBeInstanceOf(MarkupGrid); + }); + + it("copies field values", () => { + let cloneMethod = originalNode.getMethod("clone"); + let copyNode = cloneMethod.call(interpreter, new BrsBoolean(true)); + + expect(copyNode.get(new BrsString("field1"))).toEqual( + new BrsString("a string") + ); + expect(copyNode.get(new BrsString("field2"))).toEqual(new Int32(-19999)); + expect(copyNode.get(new BrsString("field3"))).toEqual(BrsBoolean.False); + expect(copyNode.get(new BrsString("<33"))).toEqual(new BrsString("")); + + let isSameNode = originalNode.getMethod("isSameNode"); + expect(isSameNode.call(interpreter, copyNode)).toEqual(BrsBoolean.False); + }); + + it("shallow copy doesn't copy children", () => { + let cloneMethod = originalNode.getMethod("clone"); + let copyNode = cloneMethod.call(interpreter, new BrsBoolean(false)); + + let getChildCount = copyNode.getMethod("getchildcount"); + let childCount = getChildCount.call(interpreter); + + expect(childCount).toEqual(new Int32(0)); + }); + + xit("deep copy copies children and grandchildren", () => { + let cloneMethod = originalNode.getMethod("clone"); + let copyNode = cloneMethod.call(interpreter, new BrsBoolean(true)); + + let getChildCount = copyNode.getMethod("getchildcount"); + let childCount = getChildCount.call(interpreter); + + expect(childCount).toEqual(new Int32(3)); + + getChild = copyNode.getMethod("getchild"); + let child1copy = getChild.call(interpreter, new Int32(1)); + + let getGrandchildCount = child1copy.getMethod("getchildcount"); + let grandchildCount = getGrandchildCount.call(interpreter); + + expect(grandchildCount).toEqual(new Int32(2)); + }); + }); }); }); From 4ba9b38c3141849c6fd8808f378b0e2a64767bdd Mon Sep 17 00:00:00 2001 From: Anya Tokar Date: Wed, 24 Nov 2021 17:12:00 -0500 Subject: [PATCH 02/12] tiny: add/remove spaces --- src/brsTypes/components/RoSGNode.ts | 1 - test/brsTypes/components/RoSGNode.test.js | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/brsTypes/components/RoSGNode.ts b/src/brsTypes/components/RoSGNode.ts index 26aa9d30..4b555e5a 100644 --- a/src/brsTypes/components/RoSGNode.ts +++ b/src/brsTypes/components/RoSGNode.ts @@ -1929,7 +1929,6 @@ function addChildren( let setField = newChild.getMethod("setfield"); if (setField) { let nodeFields = newChild.getFields(); - for (let [key, value] of Object.entries(child.fields)) { let field = nodeFields.get(key.toLowerCase()); if (field) { diff --git a/test/brsTypes/components/RoSGNode.test.js b/test/brsTypes/components/RoSGNode.test.js index c060a2c9..f9eba69b 100644 --- a/test/brsTypes/components/RoSGNode.test.js +++ b/test/brsTypes/components/RoSGNode.test.js @@ -929,7 +929,6 @@ describe("RoSGNode", () => { ]); let addFields = node.getMethod("addfields"); - let update = node.getMethod("update"); let getField = node.getMethod("getfield"); expect(update).toBeTruthy(); @@ -2502,6 +2501,7 @@ describe("RoSGNode", () => { it("returns the parent subtype", () => { let markupNode = new MarkupGrid(); let parentsubtype = markupNode.getMethod("parentsubtype"); + let result = parentsubtype.call(interpreter, new BrsString("MarkUpGrid")); expect(result.value).toBe("ArrayGrid"); }); From ed5facb77a5437030634cd1a3124e909330c310f Mon Sep 17 00:00:00 2001 From: Anya Tokar Date: Tue, 30 Nov 2021 14:27:11 -0500 Subject: [PATCH 03/12] add recursive deep clone for fields and children --- src/brsTypes/components/RoSGNode.ts | 51 +++++++++++++++++++---- test/brsTypes/components/RoSGNode.test.js | 30 +++++++++---- 2 files changed, 66 insertions(+), 15 deletions(-) diff --git a/src/brsTypes/components/RoSGNode.ts b/src/brsTypes/components/RoSGNode.ts index 4b555e5a..e3006ddf 100644 --- a/src/brsTypes/components/RoSGNode.ts +++ b/src/brsTypes/components/RoSGNode.ts @@ -373,6 +373,7 @@ export class RoSGNode extends BrsComponent implements BrsValue, BrsIterable { this.issubtype, this.parentsubtype, this.clone, + this.clonehelper, ], ifSGNodeBoundingRect: [this.boundingRect], }); @@ -1696,18 +1697,21 @@ export class RoSGNode extends BrsComponent implements BrsValue, BrsIterable { }, }); - private clone = new Callable("clone", { + private clonehelper = new Callable("clonehelper", { signature: { - args: [new StdlibArgument("isDeepCopy", ValueKind.Boolean)], + args: [ + new StdlibArgument("toBeCloned", ValueKind.Object), + new StdlibArgument("isDeepCopy", ValueKind.Boolean), + ], returns: ValueKind.Object, }, - impl: (interpreter: Interpreter, isDeepCopy: BrsBoolean) => { - let copy = createNodeByType(interpreter, new BrsString(this.nodeSubtype)); + impl: (interpreter: Interpreter, toBeCloned: RoSGNode, isDeepCopy: BrsBoolean) => { + let copy = createNodeByType(interpreter, new BrsString(toBeCloned.nodeSubtype)); - let originalFields = this.getFields(); - let newFields = new RoAssociativeArray([]); + let originalFields = toBeCloned.getFields(); + let copiedFields = new RoAssociativeArray([]); - let addReplace = newFields.getMethod("addreplace"); + let addReplace = copiedFields.getMethod("addreplace"); for (let [key, value] of originalFields) { if (addReplace) { @@ -1723,7 +1727,20 @@ export class RoSGNode extends BrsComponent implements BrsValue, BrsIterable { let update = copy.getMethod("update"); if (update) { - update.call(interpreter, newFields, BrsBoolean.True); + update.call(interpreter, copiedFields, BrsBoolean.True); + } + + if (isDeepCopy.toBoolean()) { + let appendChild = copy.getMethod("appendchild"); + + for (let child of toBeCloned.children) { + let clone = child.getMethod("cloneHelper"); + + if (clone && appendChild) { + let childCopy = clone.call(interpreter, child, BrsBoolean.True); + appendChild.call(interpreter, childCopy); + } + } } } @@ -1731,6 +1748,24 @@ export class RoSGNode extends BrsComponent implements BrsValue, BrsIterable { }, }); + private clone = new Callable("clone", { + signature: { + args: [new StdlibArgument("isDeepCopy", ValueKind.Boolean)], + returns: ValueKind.Object, + }, + impl: (interpreter: Interpreter, isDeepCopy: BrsBoolean) => { + let cloneHelper = this.getMethod("clonehelper"); + + if (cloneHelper) { + let copy = cloneHelper.call(interpreter, this, isDeepCopy); + + return copy; + } + + return BrsInvalid.Instance; + }, + }); + /* Returns the subtype of this node as specified when it was created */ private subtype = new Callable("subtype", { signature: { diff --git a/test/brsTypes/components/RoSGNode.test.js b/test/brsTypes/components/RoSGNode.test.js index f9eba69b..d8e62e27 100644 --- a/test/brsTypes/components/RoSGNode.test.js +++ b/test/brsTypes/components/RoSGNode.test.js @@ -2528,19 +2528,22 @@ describe("RoSGNode", () => { ]); child1 = new RoSGNode([ - { name: new BrsString("child"), value: new BrsString("1") }, + { name: new BrsString("child1name"), value: new BrsString("1") }, ]); child2 = new RoSGNode([ - { name: new BrsString("child"), value: new BrsString("2") }, + { name: new BrsString("child2name"), value: new Int32(2) }, ]); child3 = new RoSGNode([ - { name: new BrsString("child"), value: new BrsString("3") }, + { name: new BrsString("child3name"), value: BrsBoolean.False }, ]); grandchild1 = new RoSGNode([ - { name: new BrsString("grandChild"), value: new BrsString("4") }, + { name: new BrsString("grandchild1name"), value: new Int32(1.2) }, ]); grandchild2 = new RoSGNode([ - { name: new BrsString("grandChild"), value: new BrsString("5") }, + { + name: new BrsString("grandchild2name"), + value: new BrsString("second grandchild"), + }, ]); let appendGrandchildren = child1.getMethod("appendchildren"); @@ -2583,7 +2586,7 @@ describe("RoSGNode", () => { expect(childCount).toEqual(new Int32(0)); }); - xit("deep copy copies children and grandchildren", () => { + it("deep copy copies children and grandchildren", () => { let cloneMethod = originalNode.getMethod("clone"); let copyNode = cloneMethod.call(interpreter, new BrsBoolean(true)); @@ -2593,12 +2596,25 @@ describe("RoSGNode", () => { expect(childCount).toEqual(new Int32(3)); getChild = copyNode.getMethod("getchild"); - let child1copy = getChild.call(interpreter, new Int32(1)); + let child1copy = getChild.call(interpreter, new Int32(0)); + + expect(child1copy.get(new BrsString("child1name"))).toEqual(new BrsString("1")); let getGrandchildCount = child1copy.getMethod("getchildcount"); let grandchildCount = getGrandchildCount.call(interpreter); expect(grandchildCount).toEqual(new Int32(2)); + + getChild = child1copy.getMethod("getchild"); + let grandchild1copy = getChild.call(interpreter, new Int32(0)); + let grandchild2copy = getChild.call(interpreter, new Int32(1)); + + expect(grandchild1copy.get(new BrsString("grandchild1name"))).toEqual( + new Int32(1.2) + ); + expect(grandchild2copy.get(new BrsString("grandchild2name"))).toEqual( + new BrsString("second grandchild") + ); }); }); }); From 3df221c0235569ecc14a54ffcda8d9c02fb1716d Mon Sep 17 00:00:00 2001 From: Anya Tokar Date: Tue, 30 Nov 2021 17:23:59 -0500 Subject: [PATCH 04/12] refactor cloneHelper to not be Callable --- src/brsTypes/components/RoSGNode.ts | 117 +++++++++++----------- test/brsTypes/components/RoSGNode.test.js | 2 +- 2 files changed, 60 insertions(+), 59 deletions(-) diff --git a/src/brsTypes/components/RoSGNode.ts b/src/brsTypes/components/RoSGNode.ts index e3006ddf..af7fcee3 100644 --- a/src/brsTypes/components/RoSGNode.ts +++ b/src/brsTypes/components/RoSGNode.ts @@ -373,7 +373,6 @@ export class RoSGNode extends BrsComponent implements BrsValue, BrsIterable { this.issubtype, this.parentsubtype, this.clone, - this.clonehelper, ], ifSGNodeBoundingRect: [this.boundingRect], }); @@ -1697,72 +1696,22 @@ export class RoSGNode extends BrsComponent implements BrsValue, BrsIterable { }, }); - private clonehelper = new Callable("clonehelper", { - signature: { - args: [ - new StdlibArgument("toBeCloned", ValueKind.Object), - new StdlibArgument("isDeepCopy", ValueKind.Boolean), - ], - returns: ValueKind.Object, - }, - impl: (interpreter: Interpreter, toBeCloned: RoSGNode, isDeepCopy: BrsBoolean) => { - let copy = createNodeByType(interpreter, new BrsString(toBeCloned.nodeSubtype)); - - let originalFields = toBeCloned.getFields(); - let copiedFields = new RoAssociativeArray([]); - - let addReplace = copiedFields.getMethod("addreplace"); - - for (let [key, value] of originalFields) { - if (addReplace) { - addReplace.call( - interpreter, - new BrsString(key), - getBrsValueFromFieldType(value.getType(), value.toString()) - ); - } - } - - if (!(copy instanceof BrsInvalid)) { - let update = copy.getMethod("update"); - - if (update) { - update.call(interpreter, copiedFields, BrsBoolean.True); - } - - if (isDeepCopy.toBoolean()) { - let appendChild = copy.getMethod("appendchild"); - - for (let child of toBeCloned.children) { - let clone = child.getMethod("cloneHelper"); - - if (clone && appendChild) { - let childCopy = clone.call(interpreter, child, BrsBoolean.True); - appendChild.call(interpreter, childCopy); - } - } - } - } - - return copy; - }, - }); - private clone = new Callable("clone", { signature: { args: [new StdlibArgument("isDeepCopy", ValueKind.Boolean)], returns: ValueKind.Object, }, impl: (interpreter: Interpreter, isDeepCopy: BrsBoolean) => { - let cloneHelper = this.getMethod("clonehelper"); + return cloneNode(interpreter, this, isDeepCopy.toBoolean()); + // let cloneHelper = this.getMethod("clonehelper"); - if (cloneHelper) { - let copy = cloneHelper.call(interpreter, this, isDeepCopy); + // if (cloneHelper) { + // let copy = cloneHelper.call(interpreter, this, isDeepCopy); - return copy; - } + // return copy; + // } - return BrsInvalid.Instance; + // return BrsInvalid.Instance; }, }); @@ -1985,3 +1934,55 @@ function addChildren( } }); } + +function cloneNode( + interpreter: Interpreter, + toBeCloned: RoSGNode, + isDeepCopy: Boolean +): RoSGNode | BrsInvalid { + let copy = createNodeByType(interpreter, new BrsString(toBeCloned.nodeSubtype)); + + let originalFields = toBeCloned.getFields(); + let copiedFields = new RoAssociativeArray([]); + let addReplace = copiedFields.getMethod("addreplace"); + + // Copy the fields. + for (let [key, value] of originalFields) { + if (addReplace) { + addReplace.call( + interpreter, + new BrsString(key), + getBrsValueFromFieldType(value.getType(), value.toString()) + ); + } + } + + if (!(copy instanceof BrsInvalid)) { + let update = copy.getMethod("update"); + + if (update) { + update.call(interpreter, copiedFields, BrsBoolean.True); + } + + // A deep clone also copies children. + if (isDeepCopy) { + let appendChild = copy.getMethod("appendchild"); + let getChildren = toBeCloned.getMethod("getchildren"); + + if (getChildren && appendChild) { + let children = getChildren.call(interpreter, new Int32(-1), new Int32(0)); + + if (children instanceof RoArray) { + for (let child of children.getElements()) { + if (child instanceof RoSGNode) { + let childCopy = cloneNode(interpreter, child, isDeepCopy); + appendChild.call(interpreter, childCopy); + } + } + } + } + } + } + + return copy; +} diff --git a/test/brsTypes/components/RoSGNode.test.js b/test/brsTypes/components/RoSGNode.test.js index d8e62e27..b877bd58 100644 --- a/test/brsTypes/components/RoSGNode.test.js +++ b/test/brsTypes/components/RoSGNode.test.js @@ -2586,7 +2586,7 @@ describe("RoSGNode", () => { expect(childCount).toEqual(new Int32(0)); }); - it("deep copy copies children and grandchildren", () => { + it("deep clone copies children and grandchildren", () => { let cloneMethod = originalNode.getMethod("clone"); let copyNode = cloneMethod.call(interpreter, new BrsBoolean(true)); From f9f7f463129114155fa0e4ebed48eaa72fd373b6 Mon Sep 17 00:00:00 2001 From: Anya Tokar Date: Tue, 30 Nov 2021 17:38:50 -0500 Subject: [PATCH 05/12] test: add e2e testing --- test/e2e/RoSGNode.test.js | 2 ++ test/e2e/resources/components/roSGNode/roSGNode.brs | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/test/e2e/RoSGNode.test.js b/test/e2e/RoSGNode.test.js index bdc35420..8b5223a2 100644 --- a/test/e2e/RoSGNode.test.js +++ b/test/e2e/RoSGNode.test.js @@ -209,6 +209,8 @@ describe("components/roSGNode", () => { "invalid", "33", "37", + "updatedId", + "newValue", "0", "0", "0", diff --git a/test/e2e/resources/components/roSGNode/roSGNode.brs b/test/e2e/resources/components/roSGNode/roSGNode.brs index f490522b..c25988fa 100644 --- a/test/e2e/resources/components/roSGNode/roSGNode.brs +++ b/test/e2e/resources/components/roSGNode/roSGNode.brs @@ -214,6 +214,16 @@ sub init() node.ClipStart = 37 ?node.ClipStart + ' it clones nodes + node = createObject("roSGNode", "ContentNode") + node.update({ + id: "updatedId", + newField: "newValue" + }, true) + clonedNode = node.clone(true) + print clonedNode.id + print clonedNode.newField + ' ifSGNodeBoundingRect rect = node.boundingRect() print rect.x ' => 0 From 480f6b378e740888cf87dccd419339e6bd39ed37 Mon Sep 17 00:00:00 2001 From: Anya Tokar Date: Tue, 30 Nov 2021 17:45:16 -0500 Subject: [PATCH 06/12] tiny: remove copied out code --- src/brsTypes/components/RoSGNode.ts | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/brsTypes/components/RoSGNode.ts b/src/brsTypes/components/RoSGNode.ts index af7fcee3..89ef5002 100644 --- a/src/brsTypes/components/RoSGNode.ts +++ b/src/brsTypes/components/RoSGNode.ts @@ -1703,15 +1703,6 @@ export class RoSGNode extends BrsComponent implements BrsValue, BrsIterable { }, impl: (interpreter: Interpreter, isDeepCopy: BrsBoolean) => { return cloneNode(interpreter, this, isDeepCopy.toBoolean()); - // let cloneHelper = this.getMethod("clonehelper"); - - // if (cloneHelper) { - // let copy = cloneHelper.call(interpreter, this, isDeepCopy); - - // return copy; - // } - - // return BrsInvalid.Instance; }, }); From 1d64c937b116ade812feba8e65b3084fd1eb9224 Mon Sep 17 00:00:00 2001 From: Anya Tokar Date: Wed, 1 Dec 2021 10:45:35 -0500 Subject: [PATCH 07/12] smaller CR changes --- src/brsTypes/components/RoSGNode.ts | 30 ++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/brsTypes/components/RoSGNode.ts b/src/brsTypes/components/RoSGNode.ts index 89ef5002..45436603 100644 --- a/src/brsTypes/components/RoSGNode.ts +++ b/src/brsTypes/components/RoSGNode.ts @@ -1323,7 +1323,7 @@ export class RoSGNode extends BrsComponent implements BrsValue, BrsIterable { let childNodesElements = child_nodes.getElements(); if (childNodesElements.length !== 0) { childNodesElements.forEach((childNode) => { - if (childNode instanceof RoSGNode) { + { // Remove if it exists to reappend this.removeChildByReference(childNode); this.appendChildToParent(childNode); @@ -1933,22 +1933,22 @@ function cloneNode( ): RoSGNode | BrsInvalid { let copy = createNodeByType(interpreter, new BrsString(toBeCloned.nodeSubtype)); - let originalFields = toBeCloned.getFields(); - let copiedFields = new RoAssociativeArray([]); - let addReplace = copiedFields.getMethod("addreplace"); - - // Copy the fields. - for (let [key, value] of originalFields) { - if (addReplace) { - addReplace.call( - interpreter, - new BrsString(key), - getBrsValueFromFieldType(value.getType(), value.toString()) - ); + if (copy instanceof RoSGNode) { + let originalFields = toBeCloned.getFields(); + let copiedFields = new RoAssociativeArray([]); + let addReplace = copiedFields.getMethod("addreplace"); + + // Copy the fields. + for (let [key, value] of originalFields) { + if (addReplace) { + addReplace.call( + interpreter, + new BrsString(key), + getBrsValueFromFieldType(value.getType(), value.toString()) + ); + } } - } - if (!(copy instanceof BrsInvalid)) { let update = copy.getMethod("update"); if (update) { From f14ada13712fdbeee9342a29e20bedb20df05e62 Mon Sep 17 00:00:00 2001 From: Anya Tokar Date: Thu, 2 Dec 2021 10:14:09 -0500 Subject: [PATCH 08/12] fix: undo an accidental edit in addchildren method --- src/brsTypes/components/RoSGNode.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/brsTypes/components/RoSGNode.ts b/src/brsTypes/components/RoSGNode.ts index 45436603..cdd2335b 100644 --- a/src/brsTypes/components/RoSGNode.ts +++ b/src/brsTypes/components/RoSGNode.ts @@ -1323,7 +1323,7 @@ export class RoSGNode extends BrsComponent implements BrsValue, BrsIterable { let childNodesElements = child_nodes.getElements(); if (childNodesElements.length !== 0) { childNodesElements.forEach((childNode) => { - { + if (childNode instanceof RoSGNode) { // Remove if it exists to reappend this.removeChildByReference(childNode); this.appendChildToParent(childNode); From 7ba20220f7981460b30181283356c5a98fcfe2cb Mon Sep 17 00:00:00 2001 From: Anya Tokar Date: Thu, 2 Dec 2021 17:44:20 -0500 Subject: [PATCH 09/12] expose .children method per CR suggestion --- src/brsTypes/components/RoSGNode.ts | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/brsTypes/components/RoSGNode.ts b/src/brsTypes/components/RoSGNode.ts index cdd2335b..a58ece13 100644 --- a/src/brsTypes/components/RoSGNode.ts +++ b/src/brsTypes/components/RoSGNode.ts @@ -296,7 +296,7 @@ function isSubtypeCheck(currentNodeType: string, checkType: string): boolean { export class RoSGNode extends BrsComponent implements BrsValue, BrsIterable { readonly kind = ValueKind.Object; private fields = new Map(); - private children: RoSGNode[] = []; + public children: RoSGNode[] = []; private parent: RoSGNode | BrsInvalid = BrsInvalid.Instance; readonly defaultFields: FieldModel[] = [ @@ -1958,17 +1958,14 @@ function cloneNode( // A deep clone also copies children. if (isDeepCopy) { let appendChild = copy.getMethod("appendchild"); - let getChildren = toBeCloned.getMethod("getchildren"); - if (getChildren && appendChild) { - let children = getChildren.call(interpreter, new Int32(-1), new Int32(0)); + if (appendChild) { + let children = toBeCloned.children; - if (children instanceof RoArray) { - for (let child of children.getElements()) { - if (child instanceof RoSGNode) { - let childCopy = cloneNode(interpreter, child, isDeepCopy); - appendChild.call(interpreter, childCopy); - } + for (let child of children) { + if (child instanceof RoSGNode) { + let childCopy = cloneNode(interpreter, child, isDeepCopy); + appendChild.call(interpreter, childCopy); } } } From 0505973a011453e41bca4bc538ad1364b73413fc Mon Sep 17 00:00:00 2001 From: Anya Tokar Date: Thu, 2 Dec 2021 17:59:12 -0500 Subject: [PATCH 10/12] add clone method description from brightscript docs --- src/brsTypes/components/RoSGNode.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/brsTypes/components/RoSGNode.ts b/src/brsTypes/components/RoSGNode.ts index a58ece13..f6051da6 100644 --- a/src/brsTypes/components/RoSGNode.ts +++ b/src/brsTypes/components/RoSGNode.ts @@ -1696,6 +1696,7 @@ export class RoSGNode extends BrsComponent implements BrsValue, BrsIterable { }, }); + /* Returns a copy of the entire node tree or just a shallow copy. */ private clone = new Callable("clone", { signature: { args: [new StdlibArgument("isDeepCopy", ValueKind.Boolean)], From 6a6a5de8facc572228623236ab5fab6b557ba44b Mon Sep 17 00:00:00 2001 From: Anya Tokar Date: Thu, 6 Jan 2022 11:32:17 -0500 Subject: [PATCH 11/12] Revert "expose .children method per CR suggestion" This reverts commit 7ba20220f7981460b30181283356c5a98fcfe2cb. --- src/brsTypes/components/RoSGNode.ts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/brsTypes/components/RoSGNode.ts b/src/brsTypes/components/RoSGNode.ts index f6051da6..7da63ff7 100644 --- a/src/brsTypes/components/RoSGNode.ts +++ b/src/brsTypes/components/RoSGNode.ts @@ -296,7 +296,7 @@ function isSubtypeCheck(currentNodeType: string, checkType: string): boolean { export class RoSGNode extends BrsComponent implements BrsValue, BrsIterable { readonly kind = ValueKind.Object; private fields = new Map(); - public children: RoSGNode[] = []; + private children: RoSGNode[] = []; private parent: RoSGNode | BrsInvalid = BrsInvalid.Instance; readonly defaultFields: FieldModel[] = [ @@ -1959,14 +1959,17 @@ function cloneNode( // A deep clone also copies children. if (isDeepCopy) { let appendChild = copy.getMethod("appendchild"); + let getChildren = toBeCloned.getMethod("getchildren"); - if (appendChild) { - let children = toBeCloned.children; + if (getChildren && appendChild) { + let children = getChildren.call(interpreter, new Int32(-1), new Int32(0)); - for (let child of children) { - if (child instanceof RoSGNode) { - let childCopy = cloneNode(interpreter, child, isDeepCopy); - appendChild.call(interpreter, childCopy); + if (children instanceof RoArray) { + for (let child of children.getElements()) { + if (child instanceof RoSGNode) { + let childCopy = cloneNode(interpreter, child, isDeepCopy); + appendChild.call(interpreter, childCopy); + } } } } From f434df70fcd4cd2fa5271193a6b5c51d09bb77cc Mon Sep 17 00:00:00 2001 From: Anya Tokar Date: Thu, 6 Jan 2022 12:49:04 -0500 Subject: [PATCH 12/12] Restart CI/CD