diff --git a/src/blocks/scratch3_procedures.js b/src/blocks/scratch3_procedures.js index c648d9603..b91630f12 100644 --- a/src/blocks/scratch3_procedures.js +++ b/src/blocks/scratch3_procedures.js @@ -27,11 +27,20 @@ class Scratch3ProcedureBlocks { if (!util.stackFrame.executed) { const procedureCode = args.mutation.proccode; const paramNames = util.getProcedureParamNames(procedureCode); + + // If null, procedure could not be found, which can happen if custom + // block is dragged between sprites without the definition. + // Match Scratch 2.0 behavior and noop. + if (paramNames === null) { + return; + } + for (let i = 0; i < paramNames.length; i++) { if (args.hasOwnProperty(`input${i}`)) { util.pushParam(paramNames[i], args[`input${i}`]); } } + util.stackFrame.executed = true; util.startProcedure(procedureCode); } diff --git a/test/unit/blocks_procedures.js b/test/unit/blocks_procedures.js new file mode 100644 index 000000000..4ecdb41d8 --- /dev/null +++ b/test/unit/blocks_procedures.js @@ -0,0 +1,28 @@ +const test = require('tap').test; +const Procedures = require('../../src/blocks/scratch3_procedures'); + +const blocks = new Procedures(null); + +test('getPrimitives', t => { + t.type(blocks.getPrimitives(), 'object'); + t.end(); +}); + +// Originally inspired by https://github.com/LLK/scratch-gui/issues/809 +test('calling a custom block with no definition does not throw', t => { + const args = { + mutation: { + proccode: 'undefined proc' + } + }; + const util = { + getProcedureParamNames: () => null, + stackFrame: { + executed: false + } + }; + t.doesNotThrow(() => { + blocks.callNoReturn(args, util); + }); + t.end(); +});