From b23fb1e8bee79055cbf7f2fd00c9182b68ba4f43 Mon Sep 17 00:00:00 2001 From: Muffin Date: Wed, 16 Aug 2023 16:39:09 -0500 Subject: [PATCH 1/3] Refactor ScratchX compatibility layer --- src/extension-support/extension-worker.js | 3 +- .../tw-scratchx-compatibility-layer.js | 52 ++++++++++--------- .../tw-unsandboxed-extension-runner.js | 3 +- test/unit/tw_scratchx.js | 35 +++++++++++-- 4 files changed, 62 insertions(+), 31 deletions(-) diff --git a/src/extension-support/extension-worker.js b/src/extension-support/extension-worker.js index b0a9b89522..bdc5286a25 100644 --- a/src/extension-support/extension-worker.js +++ b/src/extension-support/extension-worker.js @@ -1,6 +1,7 @@ /* eslint-env worker */ const ScratchCommon = require('./tw-extension-api-common'); +const createScratchX = require('./tw-scratchx-compatibility-layer'); const dispatch = require('../dispatch/worker-dispatch'); const log = require('../util/log'); const {isWorker} = require('./tw-extension-worker-context'); @@ -95,4 +96,4 @@ global.Scratch.extensions = { register: extensionWorker.register.bind(extensionWorker) }; -global.ScratchExtensions = require('./tw-scratchx-compatibility-layer'); +global.ScratchExtensions = createScratchX(global.Scratch); diff --git a/src/extension-support/tw-scratchx-compatibility-layer.js b/src/extension-support/tw-scratchx-compatibility-layer.js index 227af2b52a..bceae527aa 100644 --- a/src/extension-support/tw-scratchx-compatibility-layer.js +++ b/src/extension-support/tw-scratchx-compatibility-layer.js @@ -1,8 +1,5 @@ // ScratchX API Documentation: https://github.com/LLK/scratchx/wiki/ -// Global Scratch API from extension-worker.js -/* globals Scratch */ - const ArgumentType = require('./argument-type'); const BlockType = require('./block-type'); @@ -191,31 +188,36 @@ const convert = (name, descriptor, functions) => { const extensionNameToExtension = new Map(); -const register = (name, descriptor, functions) => { - const scratch3Extension = convert(name, descriptor, functions); - extensionNameToExtension.set(name, scratch3Extension); - Scratch.extensions.register(scratch3Extension); -}; - /** - * @param {string} extensionName - * @returns {ScratchXStatus} + * @param {*} Scratch Scratch 3.0 extension API object + * @returns {*} ScratchX-compatible API object */ -const getStatus = extensionName => { - const extension = extensionNameToExtension.get(extensionName); - if (extension) { - return extension._getStatus(); - } - return { - status: 0, - msg: 'does not exist' +const createScratchX = Scratch => { + const register = (name, descriptor, functions) => { + const scratch3Extension = convert(name, descriptor, functions); + extensionNameToExtension.set(name, scratch3Extension); + Scratch.extensions.register(scratch3Extension); }; -}; -module.exports = { - register, - getStatus, + /** + * @param {string} extensionName + * @returns {ScratchXStatus} + */ + const getStatus = extensionName => { + const extension = extensionNameToExtension.get(extensionName); + if (extension) { + return extension._getStatus(); + } + return { + status: 0, + msg: 'does not exist' + }; + }; - // For tests - convert + return { + register, + getStatus + }; }; + +module.exports = createScratchX; diff --git a/src/extension-support/tw-unsandboxed-extension-runner.js b/src/extension-support/tw-unsandboxed-extension-runner.js index c249b8ced5..debeebab5c 100644 --- a/src/extension-support/tw-unsandboxed-extension-runner.js +++ b/src/extension-support/tw-unsandboxed-extension-runner.js @@ -1,4 +1,5 @@ const ScratchCommon = require('./tw-extension-api-common'); +const createScratchX = require('./tw-scratchx-compatibility-layer'); const AsyncLimiter = require('../util/async-limiter'); const createTranslate = require('./tw-l10n'); @@ -115,7 +116,7 @@ const setupUnsandboxedExtensionAPI = vm => new Promise(resolve => { Scratch.translate = createTranslate(vm); global.Scratch = Scratch; - global.ScratchExtensions = require('./tw-scratchx-compatibility-layer'); + global.ScratchExtensions = createScratchX(Scratch); }); /** diff --git a/test/unit/tw_scratchx.js b/test/unit/tw_scratchx.js index 90ecb1c307..bf2d8d9562 100644 --- a/test/unit/tw_scratchx.js +++ b/test/unit/tw_scratchx.js @@ -1,5 +1,5 @@ const ScratchXUtilities = require('../../src/extension-support/tw-scratchx-utilities'); -const ScratchExtensions = require('../../src/extension-support/tw-scratchx-compatibility-layer'); +const createScratchX = require('../../src/extension-support/tw-scratchx-compatibility-layer'); const {test} = require('tap'); test('argument index to id', t => { @@ -19,7 +19,34 @@ test('generate extension id', t => { t.end(); }); +const mockScratchExtensions = () => { + const mockScratch = {}; + return createScratchX(mockScratch); +}; + +const convert = (...args) => { + let registered = null; + const mockScratch = { + extensions: { + register: extensionObject => { + if (registered) { + // In tests we don't want this + throw new Error('register() called twice'); + } + registered = extensionObject; + } + } + }; + const ScratchExtensions = createScratchX(mockScratch); + ScratchExtensions.register(...args); + if (!registered) { + throw new Error('Did not register()'); + } + return registered; +}; + test('register', t => { + const ScratchExtensions = mockScratchExtensions(); t.type(ScratchExtensions.register, 'function'); t.end(); }); @@ -49,7 +76,7 @@ test('complex extension', async t => { const touching = sprite => sprite === 'Sprite9'; - const converted = ScratchExtensions.convert( + const converted = convert( 'My Extension', { blocks: [ @@ -215,7 +242,7 @@ test('complex extension', async t => { }); test('display name', t => { - const converted = ScratchExtensions.convert( + const converted = convert( 'Internal Name', { blocks: [], @@ -234,7 +261,7 @@ test('_getStatus', t => { status: 2, msg: 'Ready' }); - const converted = ScratchExtensions.convert( + const converted = convert( 'Name', { blocks: [] From 55cda8242cc69010113f55354f337dc1b4c7041e Mon Sep 17 00:00:00 2001 From: Muffin Date: Tue, 22 Aug 2023 10:00:36 -0500 Subject: [PATCH 2/3] Run unsandboxed extensions with fetch() and new AsyncFunction instead of