mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2025-07-11 13:34:00 -04:00
Replace extension delimeter with '_'
This commit is contained in:
parent
47a2d76a14
commit
f86cad3305
5 changed files with 74 additions and 39 deletions
src
|
@ -471,7 +471,7 @@ class Runtime extends EventEmitter {
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_makeExtensionMenuId (menuName, extensionId) {
|
_makeExtensionMenuId (menuName, extensionId) {
|
||||||
return `${extensionId}.menu.${escapeHtml(menuName)}`;
|
return `${extensionId}_menu_${escapeHtml(menuName)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -625,7 +625,7 @@ class Runtime extends EventEmitter {
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_convertForScratchBlocks (blockInfo, categoryInfo) {
|
_convertForScratchBlocks (blockInfo, categoryInfo) {
|
||||||
const extendedOpcode = `${categoryInfo.id}.${blockInfo.opcode}`;
|
const extendedOpcode = `${categoryInfo.id}_${blockInfo.opcode}`;
|
||||||
|
|
||||||
const blockJSON = {
|
const blockJSON = {
|
||||||
type: extendedOpcode,
|
type: extendedOpcode,
|
||||||
|
|
|
@ -188,7 +188,7 @@ class ExtensionManager {
|
||||||
_registerInternalExtension (extensionObject) {
|
_registerInternalExtension (extensionObject) {
|
||||||
const extensionInfo = extensionObject.getInfo();
|
const extensionInfo = extensionObject.getInfo();
|
||||||
const fakeWorkerId = this.nextExtensionWorker++;
|
const fakeWorkerId = this.nextExtensionWorker++;
|
||||||
const serviceName = `extension.${fakeWorkerId}.${extensionInfo.id}`;
|
const serviceName = `extension_${fakeWorkerId}_${extensionInfo.id}`;
|
||||||
return dispatch.setService(serviceName, extensionObject)
|
return dispatch.setService(serviceName, extensionObject)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
dispatch.call('extensions', 'registerExtensionService', serviceName);
|
dispatch.call('extensions', 'registerExtensionService', serviceName);
|
||||||
|
@ -229,7 +229,9 @@ class ExtensionManager {
|
||||||
*/
|
*/
|
||||||
_prepareExtensionInfo (serviceName, extensionInfo) {
|
_prepareExtensionInfo (serviceName, extensionInfo) {
|
||||||
extensionInfo = Object.assign({}, extensionInfo);
|
extensionInfo = Object.assign({}, extensionInfo);
|
||||||
extensionInfo.id = this._sanitizeID(extensionInfo.id);
|
if (!/^[a-z0-9]+$/i.test(extensionInfo.id)) {
|
||||||
|
throw new Error('Invalid extension id');
|
||||||
|
}
|
||||||
extensionInfo.name = extensionInfo.name || extensionInfo.id;
|
extensionInfo.name = extensionInfo.name || extensionInfo.id;
|
||||||
extensionInfo.blocks = extensionInfo.blocks || [];
|
extensionInfo.blocks = extensionInfo.blocks || [];
|
||||||
extensionInfo.targetTypes = extensionInfo.targetTypes || [];
|
extensionInfo.targetTypes = extensionInfo.targetTypes || [];
|
||||||
|
|
|
@ -19,6 +19,21 @@ const {loadCostume} = require('../import/load-costume.js');
|
||||||
const {loadSound} = require('../import/load-sound.js');
|
const {loadSound} = require('../import/load-sound.js');
|
||||||
const {deserializeCostume, deserializeSound} = require('./deserialize-assets.js');
|
const {deserializeCostume, deserializeSound} = require('./deserialize-assets.js');
|
||||||
|
|
||||||
|
// Constants used during deserialization of an SB3 file
|
||||||
|
const CORE_EXTENSIONS = [
|
||||||
|
'argument',
|
||||||
|
'control',
|
||||||
|
'data',
|
||||||
|
'event',
|
||||||
|
'looks',
|
||||||
|
'math',
|
||||||
|
'motion',
|
||||||
|
'operator',
|
||||||
|
'procedures',
|
||||||
|
'sensing',
|
||||||
|
'sound'
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a Scratch 2.0 procedure string (e.g., "my_procedure %s %b %n")
|
* Convert a Scratch 2.0 procedure string (e.g., "my_procedure %s %b %n")
|
||||||
* into an argument map. This allows us to provide the expected inputs
|
* into an argument map. This allows us to provide the expected inputs
|
||||||
|
@ -501,12 +516,14 @@ const parseBlock = function (sb2block, addBroadcastMsg, getVariableId, extension
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const oldOpcode = sb2block[0];
|
const oldOpcode = sb2block[0];
|
||||||
|
|
||||||
// If the block is from an extension, record it.
|
// If the block is from an extension, record it.
|
||||||
const dotIndex = blockMetadata.opcode.indexOf('.');
|
const index = blockMetadata.opcode.indexOf('_');
|
||||||
if (dotIndex >= 0) {
|
const prefix = blockMetadata.opcode.substring(0, index);
|
||||||
const extension = blockMetadata.opcode.substring(0, dotIndex);
|
if (CORE_EXTENSIONS.indexOf(prefix) === -1) {
|
||||||
extensions.extensionIDs.add(extension);
|
extensions.extensionIDs.add(prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Block skeleton.
|
// Block skeleton.
|
||||||
const activeBlock = {
|
const activeBlock = {
|
||||||
id: uid(), // Generate a new block unique ID.
|
id: uid(), // Generate a new block unique ID.
|
||||||
|
|
|
@ -420,11 +420,11 @@ const specMap = {
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
'playDrum': {
|
'playDrum': {
|
||||||
opcode: 'music.playDrumForBeats',
|
opcode: 'music_playDrumForBeats',
|
||||||
argMap: [
|
argMap: [
|
||||||
{
|
{
|
||||||
type: 'input',
|
type: 'input',
|
||||||
inputOp: 'music.menu.DRUM',
|
inputOp: 'music_menu_DRUM',
|
||||||
inputName: 'DRUM'
|
inputName: 'DRUM'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -435,7 +435,7 @@ const specMap = {
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
'rest:elapsed:from:': {
|
'rest:elapsed:from:': {
|
||||||
opcode: 'music.restForBeats',
|
opcode: 'music_restForBeats',
|
||||||
argMap: [
|
argMap: [
|
||||||
{
|
{
|
||||||
type: 'input',
|
type: 'input',
|
||||||
|
@ -445,7 +445,7 @@ const specMap = {
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
'noteOn:duration:elapsed:from:': {
|
'noteOn:duration:elapsed:from:': {
|
||||||
opcode: 'music.playNoteForBeats',
|
opcode: 'music_playNoteForBeats',
|
||||||
argMap: [
|
argMap: [
|
||||||
{
|
{
|
||||||
type: 'input',
|
type: 'input',
|
||||||
|
@ -460,11 +460,11 @@ const specMap = {
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
'instrument:': {
|
'instrument:': {
|
||||||
opcode: 'music.setInstrument',
|
opcode: 'music_setInstrument',
|
||||||
argMap: [
|
argMap: [
|
||||||
{
|
{
|
||||||
type: 'input',
|
type: 'input',
|
||||||
inputOp: 'music.menu.INSTRUMENT',
|
inputOp: 'music_menu_INSTRUMENT',
|
||||||
inputName: 'INSTRUMENT'
|
inputName: 'INSTRUMENT'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -495,7 +495,7 @@ const specMap = {
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
'changeTempoBy:': {
|
'changeTempoBy:': {
|
||||||
opcode: 'music.changeTempo',
|
opcode: 'music_changeTempo',
|
||||||
argMap: [
|
argMap: [
|
||||||
{
|
{
|
||||||
type: 'input',
|
type: 'input',
|
||||||
|
@ -505,7 +505,7 @@ const specMap = {
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
'setTempoTo:': {
|
'setTempoTo:': {
|
||||||
opcode: 'music.setTempo',
|
opcode: 'music_setTempo',
|
||||||
argMap: [
|
argMap: [
|
||||||
{
|
{
|
||||||
type: 'input',
|
type: 'input',
|
||||||
|
@ -515,32 +515,32 @@ const specMap = {
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
'tempo': {
|
'tempo': {
|
||||||
opcode: 'music.getTempo',
|
opcode: 'music_getTempo',
|
||||||
argMap: [
|
argMap: [
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
'clearPenTrails': {
|
'clearPenTrails': {
|
||||||
opcode: 'pen.clear',
|
opcode: 'pen_clear',
|
||||||
argMap: [
|
argMap: [
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
'stampCostume': {
|
'stampCostume': {
|
||||||
opcode: 'pen.stamp',
|
opcode: 'pen_stamp',
|
||||||
argMap: [
|
argMap: [
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
'putPenDown': {
|
'putPenDown': {
|
||||||
opcode: 'pen.penDown',
|
opcode: 'pen_penDown',
|
||||||
argMap: [
|
argMap: [
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
'putPenUp': {
|
'putPenUp': {
|
||||||
opcode: 'pen.penUp',
|
opcode: 'pen_penUp',
|
||||||
argMap: [
|
argMap: [
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
'penColor:': {
|
'penColor:': {
|
||||||
opcode: 'pen.setPenColorToColor',
|
opcode: 'pen_setPenColorToColor',
|
||||||
argMap: [
|
argMap: [
|
||||||
{
|
{
|
||||||
type: 'input',
|
type: 'input',
|
||||||
|
@ -550,7 +550,7 @@ const specMap = {
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
'changePenHueBy:': {
|
'changePenHueBy:': {
|
||||||
opcode: 'pen.changePenHueBy',
|
opcode: 'pen_changePenHueBy',
|
||||||
argMap: [
|
argMap: [
|
||||||
{
|
{
|
||||||
type: 'input',
|
type: 'input',
|
||||||
|
@ -560,7 +560,7 @@ const specMap = {
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
'setPenHueTo:': {
|
'setPenHueTo:': {
|
||||||
opcode: 'pen.setPenHueToNumber',
|
opcode: 'pen_setPenHueToNumber',
|
||||||
argMap: [
|
argMap: [
|
||||||
{
|
{
|
||||||
type: 'input',
|
type: 'input',
|
||||||
|
@ -570,7 +570,7 @@ const specMap = {
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
'changePenShadeBy:': {
|
'changePenShadeBy:': {
|
||||||
opcode: 'pen.changePenShadeBy',
|
opcode: 'pen_changePenShadeBy',
|
||||||
argMap: [
|
argMap: [
|
||||||
{
|
{
|
||||||
type: 'input',
|
type: 'input',
|
||||||
|
@ -580,7 +580,7 @@ const specMap = {
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
'setPenShadeTo:': {
|
'setPenShadeTo:': {
|
||||||
opcode: 'pen.setPenShadeToNumber',
|
opcode: 'pen_setPenShadeToNumber',
|
||||||
argMap: [
|
argMap: [
|
||||||
{
|
{
|
||||||
type: 'input',
|
type: 'input',
|
||||||
|
@ -590,7 +590,7 @@ const specMap = {
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
'changePenSizeBy:': {
|
'changePenSizeBy:': {
|
||||||
opcode: 'pen.changePenSizeBy',
|
opcode: 'pen_changePenSizeBy',
|
||||||
argMap: [
|
argMap: [
|
||||||
{
|
{
|
||||||
type: 'input',
|
type: 'input',
|
||||||
|
@ -600,7 +600,7 @@ const specMap = {
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
'penSize:': {
|
'penSize:': {
|
||||||
opcode: 'pen.setPenSizeTo',
|
opcode: 'pen_setPenSizeTo',
|
||||||
argMap: [
|
argMap: [
|
||||||
{
|
{
|
||||||
type: 'input',
|
type: 'input',
|
||||||
|
@ -610,16 +610,16 @@ const specMap = {
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
'senseVideoMotion': {
|
'senseVideoMotion': {
|
||||||
opcode: 'videoSensing.videoOn',
|
opcode: 'videoSensing_videoOn',
|
||||||
argMap: [
|
argMap: [
|
||||||
{
|
{
|
||||||
type: 'input',
|
type: 'input',
|
||||||
inputOp: 'videoSensing.menu.ATTRIBUTE',
|
inputOp: 'videoSensing_menu_ATTRIBUTE',
|
||||||
inputName: 'ATTRIBUTE'
|
inputName: 'ATTRIBUTE'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'input',
|
type: 'input',
|
||||||
inputOp: 'videoSensing.menu.SUBJECT',
|
inputOp: 'videoSensing_menu_SUBJECT',
|
||||||
inputName: 'SUBJECT'
|
inputName: 'SUBJECT'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -655,7 +655,7 @@ const specMap = {
|
||||||
'whenSensorGreaterThan': ([, sensor]) => {
|
'whenSensorGreaterThan': ([, sensor]) => {
|
||||||
if (sensor === 'video motion') {
|
if (sensor === 'video motion') {
|
||||||
return {
|
return {
|
||||||
opcode: 'videoSensing.whenMotionGreaterThan',
|
opcode: 'videoSensing_whenMotionGreaterThan',
|
||||||
argMap: [
|
argMap: [
|
||||||
// skip the first arg, since we converted to a video specific sensing block
|
// skip the first arg, since we converted to a video specific sensing block
|
||||||
{},
|
{},
|
||||||
|
@ -980,17 +980,17 @@ const specMap = {
|
||||||
// ]
|
// ]
|
||||||
// },
|
// },
|
||||||
'setVideoState': {
|
'setVideoState': {
|
||||||
opcode: 'videoSensing.videoToggle',
|
opcode: 'videoSensing_videoToggle',
|
||||||
argMap: [
|
argMap: [
|
||||||
{
|
{
|
||||||
type: 'input',
|
type: 'input',
|
||||||
inputOp: 'videoSensing.menu.VIDEO_STATE',
|
inputOp: 'videoSensing_menu.VIDEO_STATE',
|
||||||
inputName: 'VIDEO_STATE'
|
inputName: 'VIDEO_STATE'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
'setVideoTransparency': {
|
'setVideoTransparency': {
|
||||||
opcode: 'videoSensing.setVideoTransparency',
|
opcode: 'videoSensing_setVideoTransparency',
|
||||||
argMap: [
|
argMap: [
|
||||||
{
|
{
|
||||||
type: 'input',
|
type: 'input',
|
||||||
|
|
|
@ -33,6 +33,21 @@ const INPUT_BLOCK_NO_SHADOW = 2; // no shadow
|
||||||
const INPUT_DIFF_BLOCK_SHADOW = 3; // obscured shadow
|
const INPUT_DIFF_BLOCK_SHADOW = 3; // obscured shadow
|
||||||
// There shouldn't be a case where block is null, but shadow is present...
|
// There shouldn't be a case where block is null, but shadow is present...
|
||||||
|
|
||||||
|
// Constants used during deserialization of an SB3 file
|
||||||
|
const CORE_EXTENSIONS = [
|
||||||
|
'argument',
|
||||||
|
'control',
|
||||||
|
'data',
|
||||||
|
'event',
|
||||||
|
'looks',
|
||||||
|
'math',
|
||||||
|
'motion',
|
||||||
|
'operator',
|
||||||
|
'procedures',
|
||||||
|
'sensing',
|
||||||
|
'sound'
|
||||||
|
];
|
||||||
|
|
||||||
// Constants referring to 'primitive' blocks that are usually shadows,
|
// Constants referring to 'primitive' blocks that are usually shadows,
|
||||||
// or in the case of variables and lists, appear quite often in projects
|
// or in the case of variables and lists, appear quite often in projects
|
||||||
// math_number
|
// math_number
|
||||||
|
@ -700,10 +715,11 @@ const parseScratchObject = function (object, runtime, extensions, zip) {
|
||||||
const blockJSON = object.blocks[blockId];
|
const blockJSON = object.blocks[blockId];
|
||||||
blocks.createBlock(blockJSON);
|
blocks.createBlock(blockJSON);
|
||||||
|
|
||||||
const dotIndex = blockJSON.opcode.indexOf('.');
|
// If the block is from an extension, record it.
|
||||||
if (dotIndex >= 0) {
|
const index = blockJSON.opcode.indexOf('_');
|
||||||
const extensionId = blockJSON.opcode.substring(0, dotIndex);
|
const prefix = blockJSON.opcode.substring(0, index);
|
||||||
extensions.extensionIDs.add(extensionId);
|
if (CORE_EXTENSIONS.indexOf(prefix) === -1) {
|
||||||
|
extensions.extensionIDs.add(prefix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue