From a15c069ac678258233e8683cfee6f7efd6bbe343 Mon Sep 17 00:00:00 2001 From: Muffin Date: Fri, 26 Jan 2024 20:39:05 -0600 Subject: [PATCH 1/6] Improve promise-like extension block test notably, fail on compiler errors, and run the test block several times --- .../tw-block-returning-promise-like.sb3 | Bin 2309 -> 2331 bytes .../tw_block_returning_promise_like.js | 8 ++++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/test/fixtures/tw-block-returning-promise-like.sb3 b/test/fixtures/tw-block-returning-promise-like.sb3 index d7c232ca21ab440b01d3d9cf9b8df4702dfa886b..4ef6f8076e6624ab2299ff625e9dae6c530fe199 100644 GIT binary patch delta 1100 zcmV-S1he~v5}Oi#P)h>@3IG5A2mo0WJ6NXgy1upp006KI000aC003}uZ)#;@bS`Rh zZ*H|#dvDt|5dSI#2O|mKd6FzAj{n)xJca^ETh!UGAqcV)dA3j3Mq=TQ~E70xwX|CF&K-1o%`KoreTffP*t_GH~?4&d0O`)}s3$i02{-dtoes zUN;qkAZ|U(Zf5}K(o1wN3ePJ^)%V zf9B3z>S2z^C+DEXvm&2rmZr;gEx{v5Z7svOkq*OuM>%eoF9!Zk=UfY~%c1ocP+9W) z#&e`rmC;OyEbx0q5F=GSs}znTrea0g2?%|=hUs*Ej&n>`8zdk$Y|=O7Zf+;2Mk$PW zD)|(}gITDV^^tgk-LfI>D6!rBHlyf=-H_yQ14gR#)ZSQFtWB5J)-Ln9%k1KGI6V6O zl!@3f-hh6;QY)>Le9vYfBw*;cP9;EmOP z*v*$#+2L=)|Egb?i+rVa$PG9?>AbJDJI9|cE{;B){J15bup0Kt_RgC^dD8S$?^Q|C z(|wYaC(2iF8`N|wIxALC7Ps#jpx+#q)tJm)`(TO9KQ70000809h0}ScuLL0h0g#0LlQ9;seJ6 zSrj|7tORib4p|gCSf=l~zP1AZ0I&>`D+nwDSrj{yS_m5f;FER;GXq%^JCm#k8v?Zi Sle+{alkW%+1}6vr0001zL@3IG5A2moW8HCUB#2!Nmi0077f000aC003}uZ)#;@bS`Rh zZ*H|#dvD`54F4(z4MAHV%WTJK)BLmb`WOyqcf+L{HWWoiOG=`PEg6!MHtX`;NBWUE zeVyB3fD({2MgI7bbk984sq~JGuI`y~V-HiwM&2%Dmubj*FKkDkcv-yv^!@Iqs-+SL@s}Hpj+G9<&8(gouELDzN-6NS;1A@Z?pBg@|Xl}Ah z>iP>`Sc}}TaehI70#YdG5_JVL0X`SjNLxhdWtJN@+DCG!gfy2Hw95gL!B=cFsKr&1ZnOwNrUTV6WCAhpBD zZ-_&)y2>V!1%6@@WR%VqwZVy!si-d0L5|Z`3Y${oGOl@P4$AJcKGkq-}NS;tmI|fhs0W# zPRkRlN_mZ9>{ldZkftBN5(Y+SGNY9@w!*W2X?^0ihk-Re|Mum)Xo78xQIYo%_m z;q-^Eums1g%6*roSb|OzT;iV7dJpoQgO8oyh=_XOiT+7X3{ty$&nh&Rm40ELxAW3c zqSGhEoh|q~o#?ow0qVkri8t&l&z*8_XV4b#)@mK*ORJpt_u+pvuFF+knH_Trp3i!J zA8T>%`18fZ(Jv?e-4hk8fxY&<^R85$wB0p$RTJ&>pH$_E@d|E>p6*0v#R|&irl|q^ z{c267oIF=^N#emowcav=`89Y+!z#CbPxb90YYmh!) z6na)p@l7S|u9ml*M@RYY9u { + t.fail('Compile error'); + }); + vm.loadProject(fixture).then(() => { let ended = 0; vm.runtime.on('SAY', (target, type, text) => { From ec1f7dea0cc85d57a3d6273c3a9110d07d06070a Mon Sep 17 00:00:00 2001 From: GarboMuffin Date: Sun, 28 Jan 2024 16:30:48 -0600 Subject: [PATCH 2/6] Add vm.exports.i_will_not_ask_for_help_when_these_break() (#181) --- src/compiler/compile.js | 2 +- src/compiler/irgen.js | 5 ++++- src/engine/thread.js | 3 +++ src/virtual-machine.js | 12 +++++++++++- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/compiler/compile.js b/src/compiler/compile.js index fb43164504..b5edb81352 100644 --- a/src/compiler/compile.js +++ b/src/compiler/compile.js @@ -1,4 +1,4 @@ -const IRGenerator = require('./irgen'); +const {IRGenerator} = require('./irgen'); const JSGenerator = require('./jsgen'); const compile = thread => { diff --git a/src/compiler/irgen.js b/src/compiler/irgen.js index 40f007a75d..c3679fb41a 100644 --- a/src/compiler/irgen.js +++ b/src/compiler/irgen.js @@ -1693,4 +1693,7 @@ class IRGenerator { } } -module.exports = IRGenerator; +module.exports = { + ScriptTreeGenerator, + IRGenerator +}; diff --git a/src/engine/thread.js b/src/engine/thread.js index a4e55504f9..c8cf6cb1c1 100644 --- a/src/engine/thread.js +++ b/src/engine/thread.js @@ -514,4 +514,7 @@ class Thread { } } +// for extensions +Thread._StackFrame = _StackFrame; + module.exports = Thread; diff --git a/src/virtual-machine.js b/src/virtual-machine.js index fd218be46b..e1a1fcdea9 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -220,7 +220,17 @@ class VirtualMachine extends EventEmitter { this.exports = { Sprite, RenderedTarget, - JSZip + JSZip, + + i_will_not_ask_for_help_when_these_break: () => { + console.warn('You are using unsupported APIs. WHEN your code breaks, do not expect help.'); + return ({ + JSGenerator: require('./compiler/jsgen.js'), + IRGenerator: require('./compiler/irgen.js').IRGenerator, + ScriptTreeGenerator: require('./compiler/irgen.js').ScriptTreeGenerator, + Thread: require('./engine/thread.js') + }); + } }; } From 58dbb212215a1d8aeaddd4debe428d7f2383e80f Mon Sep 17 00:00:00 2001 From: CST1229 <68464103+CST1229@users.noreply.github.com> Date: Mon, 29 Jan 2024 19:31:55 +0100 Subject: [PATCH 3/6] "Stage selected: less pen blocks" label on the stage The motion category already does this, so this is for parity --- src/extensions/scratch3_pen/index.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/extensions/scratch3_pen/index.js b/src/extensions/scratch3_pen/index.js index 16c09dfb61..b1b8eace4a 100644 --- a/src/extensions/scratch3_pen/index.js +++ b/src/extensions/scratch3_pen/index.js @@ -298,6 +298,16 @@ class Scratch3PenBlocks { }), blockIconURI: blockIconURI, blocks: [ + // tw: additional message when on the stage for clarity + { + blockType: BlockType.LABEL, + text: formatMessage({ + id: 'tw.pen.stageSelected', + default: 'Stage selected: less pen blocks', + description: 'Label that appears in the Pen category when the stage is selected' + }), + filter: [TargetType.STAGE] + }, { opcode: 'clear', blockType: BlockType.COMMAND, From 96225163c11220af50d51b72cad0bb382ac1c9f7 Mon Sep 17 00:00:00 2001 From: Muffin Date: Fri, 2 Feb 2024 21:25:58 -0600 Subject: [PATCH 4/6] Fix tests in Node 21 and later --- test/unit/tw_sandboxed_extensions.js | 3 +++ test/unit/tw_translate.js | 9 ++++++--- test/unit/tw_unsandboxed_extensions.js | 3 +++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/test/unit/tw_sandboxed_extensions.js b/test/unit/tw_sandboxed_extensions.js index a763c8b616..ec0fb4b562 100644 --- a/test/unit/tw_sandboxed_extensions.js +++ b/test/unit/tw_sandboxed_extensions.js @@ -9,6 +9,9 @@ global.fetch = (url, options = {}) => ( Promise.resolve(`[Response ${url instanceof Request ? url.url : url} options=${JSON.stringify(options)}]`) ); +// Remove navigator object from Node 21 and later +delete global.navigator; + // Need to trick the extension API to think it's running in a worker // It will not actually use this object ever. global.self = {}; diff --git a/test/unit/tw_translate.js b/test/unit/tw_translate.js index 8ac5dc7053..3e9c9ccf2c 100644 --- a/test/unit/tw_translate.js +++ b/test/unit/tw_translate.js @@ -6,9 +6,12 @@ global.fetch = () => Promise.reject(new Error('Simulated network error')); const Scratch3TranslateBlocks = require('../../src/extensions/scratch3_translate/index'); -global.navigator = { - language: 'en' -}; +// Node 21 and later defines a navigator object, but we want to override that for the test +Object.defineProperty(global, 'navigator', { + value: { + language: 'en-US' + } +}); // Translate tries to access AbortController from window, but does not require it to exist. global.window = {}; diff --git a/test/unit/tw_unsandboxed_extensions.js b/test/unit/tw_unsandboxed_extensions.js index a4bfdeec4b..48cf89c12e 100644 --- a/test/unit/tw_unsandboxed_extensions.js +++ b/test/unit/tw_unsandboxed_extensions.js @@ -52,6 +52,9 @@ global.window = { open: (url, target, features) => `[Window ${url} target=${target || ''} features=${features || ''}]` }; +// Remove navigator object from Node 21 and later +delete global.navigator; + tap.beforeEach(() => { scriptCallbacks.clear(); global.location = { From 845c374f7224a76dc6669594c4f3bbe09817bc0b Mon Sep 17 00:00:00 2001 From: tpsnt Date: Sat, 10 Feb 2024 15:40:36 +0800 Subject: [PATCH 5/6] Fix WeDo2.send sends empty message (#192) * Fix WeDo2.send sends empty message WeDo2.send invokes Base64Util.uint8ArrayToBase64(message). However message.arrayLength === undefined. This causes Base64Util.uint8ArrayToBase64 always returning empty string ''. * Move the fix to base64-util instead --------- Co-authored-by: Muffin --- src/util/base64-util.js | 5 ++++- test/unit/util_base64.js | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/util/base64-util.js b/src/util/base64-util.js index 1325291707..19165c980b 100644 --- a/src/util/base64-util.js +++ b/src/util/base64-util.js @@ -20,10 +20,13 @@ class Base64Util { /** * Convert a Uint8Array to a base64 encoded string. - * @param {Uint8Array} array - the array to convert. + * @param {Uint8Array|Array} array - the array to convert. * @return {string} - the base64 encoded string. */ static uint8ArrayToBase64 (array) { + if (Array.isArray(array)) { + array = new Uint8Array(array); + } let binary = ''; const len = array.byteLength; for (let i = 0; i < len; i++) { diff --git a/test/unit/util_base64.js b/test/unit/util_base64.js index c18c353333..b62a228d8b 100644 --- a/test/unit/util_base64.js +++ b/test/unit/util_base64.js @@ -3,6 +3,7 @@ const Base64Util = require('../../src/util/base64-util'); test('uint8ArrayToBase64', t => { t.equal(Base64Util.uint8ArrayToBase64(new Uint8Array([0, 50, 80, 200])), 'ADJQyA=='); + t.equal(Base64Util.uint8ArrayToBase64([0, 50, 80, 200]), 'ADJQyA=='); t.end(); }); @@ -29,7 +30,9 @@ test('round trips', t => { ]; for (const uint8array of data) { const uint8ToBase64 = Base64Util.uint8ArrayToBase64(uint8array); + const arrayToBase64 = Base64Util.uint8ArrayToBase64(Array.from(uint8array)); const bufferToBase64 = Base64Util.arrayBufferToBase64(uint8array.buffer); + t.equal(uint8ToBase64, arrayToBase64); t.equal(uint8ToBase64, bufferToBase64); const decoded = Base64Util.base64ToUint8Array(uint8ToBase64); t.same(uint8array, decoded); From 9657efb1d4d672cb3782649fc72d885c4f241942 Mon Sep 17 00:00:00 2001 From: Muffin Date: Sat, 10 Feb 2024 01:42:16 -0600 Subject: [PATCH 6/6] Shorten Base64Util test cases 1000000 items is very slow; the tests take about 4 seconds on my machine. --- test/unit/util_base64.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/util_base64.js b/test/unit/util_base64.js index b62a228d8b..f43aa14859 100644 --- a/test/unit/util_base64.js +++ b/test/unit/util_base64.js @@ -26,7 +26,7 @@ test('round trips', t => { new Uint8Array(0), new Uint8Array([10, 90, 0, 255, 255, 255, 10, 2]), new Uint8Array(10000), - new Uint8Array(1000000) + new Uint8Array(100000) ]; for (const uint8array of data) { const uint8ToBase64 = Base64Util.uint8ArrayToBase64(uint8array);