diff --git a/src/engine/blocks.js b/src/engine/blocks.js index e22122ed..db0d5a5b 100644 --- a/src/engine/blocks.js +++ b/src/engine/blocks.js @@ -735,6 +735,12 @@ class Blocks { if (this._blocks[e.newParent].inputs.hasOwnProperty(e.newInput)) { oldShadow = this._blocks[e.newParent].inputs[e.newInput].shadow; } + + // If the block being attached is itself a shadow, make sure to set + // both block and shadow to that blocks ID. This happens when adding + // inputs to a custom procedure. + if (this._blocks[e.id].shadow) oldShadow = e.id; + this._blocks[e.newParent].inputs[e.newInput] = { name: e.newInput, block: e.id, diff --git a/test/unit/engine_blocks.js b/test/unit/engine_blocks.js index c25d5b42..8ab483e2 100644 --- a/test/unit/engine_blocks.js +++ b/test/unit/engine_blocks.js @@ -358,6 +358,43 @@ test('move no obscure shadow', t => { t.end(); }); +test('move - attaching new shadow', t => { + const b = new Blocks(new Runtime()); + // Block/shadow are null to mimic state right after a procedure_call block + // is mutated by adding an input. The "move" will attach the new shadow. + b.createBlock({ + id: 'foo', + opcode: 'TEST_BLOCK', + next: null, + fields: {}, + inputs: { + fooInput: { + name: 'fooInput', + block: null, + shadow: null + } + }, + topLevel: true + }); + b.createBlock({ + id: 'bar', + opcode: 'TEST_BLOCK', + shadow: true, + next: null, + fields: {}, + inputs: {}, + topLevel: true + }); + b.moveBlock({ + id: 'bar', + newInput: 'fooInput', + newParent: 'foo' + }); + t.equal(b._blocks.foo.inputs.fooInput.block, 'bar'); + t.equal(b._blocks.foo.inputs.fooInput.shadow, 'bar'); + t.end(); +}); + test('change', t => { const b = new Blocks(new Runtime()); b.createBlock({