Wrap extension menu function to provide context

When the extension system calls a function to retrieve extension menu
items, it now provides the ID of the current editing target. There's
also now a little bit of error-checking on the results.
This commit is contained in:
Christopher Willis-Ford 2018-03-12 14:06:14 -08:00
parent 2932f232c4
commit 1049e90a8f

View file

@ -264,13 +264,36 @@ class ExtensionManager {
// we can use it later when converting the menu for Scratch Blocks.
if (typeof menus[item] === 'string') {
const serviceObject = dispatch.services[serviceName];
// TODO: Fix this to use dispatch.call when extensions are running in workers.
menus[item] = serviceObject[menus[item]].bind(serviceObject);
const menuName = menus[item];
menus[item] = this._getExtensionMenuItems.bind(this, serviceObject, menuName);
}
}
return menus;
}
/**
* Fetch the items for a particular extension menu, providing the target ID for context.
* @param {object} extensionObject - the extension object providing the menu.
* @param {string} menuName - the name of the menu function to call.
* @returns {Array} menu items ready for scratch-blocks.
* @private
*/
_getExtensionMenuItems (extensionObject, menuName) {
// Fetch the items appropriate for the target currently being edited. This assumes that menus only
// collect items when opened by the user while editing a particular target.
const editingTarget = this.runtime.getEditingTarget();
const editingTargetID = editingTarget ? editingTarget.id : null;
// TODO: Fix this to use dispatch.call when extensions are running in workers.
const menuFunc = extensionObject[menuName];
const menuItems = menuFunc.call(extensionObject, editingTargetID);
if (!menuItems || menuItems.length < 1) {
throw new Error(`Extension menu returned no items: ${menuName}`);
}
return menuItems;
}
/**
* Apply defaults for optional block fields.
* @param {string} serviceName - the name of the service hosting this extension block