From 2312c12abd039ac80036fce851dbe035f12b8c00 Mon Sep 17 00:00:00 2001 From: LordCat Date: Mon, 1 Dec 2025 20:58:13 -0500 Subject: [PATCH 1/4] "requiredExtensions" extension API --- src/engine/runtime.js | 18 +++++++++++++- src/extension-support/extension-manager.js | 29 ++++++++++++++++++++-- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/src/engine/runtime.js b/src/engine/runtime.js index 7daa4c4e40..f88d3a3154 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -1061,7 +1061,23 @@ class Runtime extends EventEmitter { * @param {ExtensionMetadata} extensionInfo - information about the extension (id, blocks, etc.) * @private */ - _registerExtensionPrimitives (extensionInfo) { + async _registerExtensionPrimitives (extensionInfo) { + + // If the extension requires other extensions, load them first. + if (Array.isArray(extensionInfo.requiredExtensions)) { + for (const extensionId of extensionInfo.requiredExtensions) { + if ( + this.extensionManager.isCoreExtension(extensionId) || + this.extensionManager.isBuiltinExtension(extensionId) || + await this.extensionManager.securityManager.canLoadExtensionFromProject(extensionId) + ) { + this.extensionManager.loadExtensionURL(extensionId); + } else { + console.warn(`Failed to load required extension: ${extensionId} for extension: ${extensionInfo.id}`); + } + } + } + const categoryInfo = { id: extensionInfo.id, name: maybeFormatMessage(extensionInfo.name), diff --git a/src/extension-support/extension-manager.js b/src/extension-support/extension-manager.js index edcea24ecf..72a81fb417 100644 --- a/src/extension-support/extension-manager.js +++ b/src/extension-support/extension-manager.js @@ -29,6 +29,20 @@ const defaultBuiltinExtensions = { tw: () => require('../extensions/tw') }; +const coreExtensions = [ + 'motion', + 'looks', + 'sound', + 'events', + 'control', + 'sensing', + 'operators', + 'variables', + 'JSON', + 'myBlocks', + 'Comments' +]; + /** * @typedef {object} ArgumentInfo - Information about an extension block argument * @property {ArgumentType} type - the type of value this argument can take @@ -126,6 +140,7 @@ class ExtensionManager { this.asyncExtensionsLoadedCallbacks = []; this.builtinExtensions = Object.assign({}, defaultBuiltinExtensions); + this.coreExtensions = coreExtensions; dispatch.setService('extensions', createExtensionService(this)).catch(e => { log.error(`ExtensionManager was unable to register extension service: ${JSON.stringify(e)}`); @@ -153,6 +168,16 @@ class ExtensionManager { return Object.prototype.hasOwnProperty.call(this.builtinExtensions, extensionId); } + /** + * Determine whether an extension with a given ID is registered as a core extension in the VM, such as motion. + * Note that custom extensions or extensions that don't load on startup will return false here. + * @param {string} extensionId + * @returns {boolean} + */ + isCoreExtension (extensionId) { + return this.coreExtensions.includes(extensionId); + } + /** * Synchronously load an internal extension (core or non-core) by ID. This call will * fail if the provided id is not does not match an internal extension. @@ -207,8 +232,8 @@ class ExtensionManager { return; } - if (this.isExtensionURLLoaded(extensionURL)) { - // Extension is already loaded. + if (this.isExtensionURLLoaded(extensionURL) || this.isCoreExtension(extensionURL)) { + // Extension is already loaded or is a core extension. return; } From 1095f7d32da519c274cfb2e8f289b22c20d410b8 Mon Sep 17 00:00:00 2001 From: LordCat Date: Mon, 1 Dec 2025 21:06:55 -0500 Subject: [PATCH 2/4] It's linting time --- src/engine/runtime.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/engine/runtime.js b/src/engine/runtime.js index f88d3a3154..016d3d6510 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -1061,7 +1061,7 @@ class Runtime extends EventEmitter { * @param {ExtensionMetadata} extensionInfo - information about the extension (id, blocks, etc.) * @private */ - async _registerExtensionPrimitives (extensionInfo) { + async _registerExtensionPrimitives (extensionInfo) { // If the extension requires other extensions, load them first. if (Array.isArray(extensionInfo.requiredExtensions)) { @@ -1073,7 +1073,9 @@ class Runtime extends EventEmitter { ) { this.extensionManager.loadExtensionURL(extensionId); } else { - console.warn(`Failed to load required extension: ${extensionId} for extension: ${extensionInfo.id}`); + console.warn( + `Failed to load required extension: ${extensionId} for extension: ${extensionInfo.id}` + ); } } } From c9e016853d0acbfd01b7ae6c9c351ea1e032ff2d Mon Sep 17 00:00:00 2001 From: LordCat Date: Mon, 1 Dec 2025 21:18:57 -0500 Subject: [PATCH 3/4] Fix coreExtensions list --- src/extension-support/extension-manager.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/extension-support/extension-manager.js b/src/extension-support/extension-manager.js index 72a81fb417..bed46ac341 100644 --- a/src/extension-support/extension-manager.js +++ b/src/extension-support/extension-manager.js @@ -38,9 +38,9 @@ const coreExtensions = [ 'sensing', 'operators', 'variables', - 'JSON', - 'myBlocks', - 'Comments' + 'json', + 'procedures', + 'comments' ]; /** From 63a2271fe7a858ace78818f8912203bd317cf049 Mon Sep 17 00:00:00 2001 From: LordCat Date: Mon, 1 Dec 2025 21:21:54 -0500 Subject: [PATCH 4/4] change "variables" to "data --- src/extension-support/extension-manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extension-support/extension-manager.js b/src/extension-support/extension-manager.js index bed46ac341..fba1d3a434 100644 --- a/src/extension-support/extension-manager.js +++ b/src/extension-support/extension-manager.js @@ -37,7 +37,7 @@ const coreExtensions = [ 'control', 'sensing', 'operators', - 'variables', + 'data', 'json', 'procedures', 'comments'