Skip to content

Commit

Permalink
fix: do not create extra shadow blocks when mirroring events (#7427)
Browse files Browse the repository at this point in the history
  • Loading branch information
maribethb authored Aug 23, 2023
1 parent d6d1074 commit b9a7a0c
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 0 deletions.
21 changes: 21 additions & 0 deletions core/events/events_block_create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ export class BlockCreate extends BlockBase {
'the constructor, or call fromJson',
);
}
if (allShadowBlocks(workspace, this.ids)) return;
if (forward) {
blocks.append(this.json, workspace);
} else {
Expand All @@ -154,6 +155,26 @@ export class BlockCreate extends BlockBase {
}
}
}
/**
* Returns true if all blocks in the list are shadow blocks. If so, that means
* the top-level block being created is a shadow block. This only happens when a
* block that was covering up a shadow block is removed. We don't need to create
* an additional block in that case because the original block still has its
* shadow block.
*
* @param workspace Workspace to check for blocks
* @param ids A list of block ids that were created in this event
* @returns True if all block ids in the list are shadow blocks
*/
const allShadowBlocks = function (
workspace: Workspace,
ids: string[],
): boolean {
const shadows = ids
.map((id) => workspace.getBlockById(id))
.filter((block) => block && block.isShadow());
return shadows.length === ids.length;
};

export interface BlockCreateJson extends BlockBaseJson {
xml: string;
Expand Down
36 changes: 36 additions & 0 deletions tests/mocha/event_block_create_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,42 @@ suite('Block Create Event', function () {
chai.assert.equal(event.xml.tagName, 'shadow');
});

test('Does not create extra shadow blocks', function () {
const shadowId = 'shadow_block';
const blockJson = {
'type': 'math_arithmetic',
'id': 'parent_with_shadow',
'fields': {'OP': 'ADD'},
'inputs': {
'A': {
'shadow': {
'type': 'math_number',
'id': shadowId,
'fields': {'NUM': 1},
},
},
},
};

// If there is a shadow block on the workspace and then we get
// a block create event with the same ID as the shadow block,
// this represents a block that had been covering a shadow block
// being removed.
Blockly.serialization.blocks.append(blockJson, this.workspace);
const shadowBlock = this.workspace.getBlockById(shadowId);
const blocksBefore = this.workspace.getAllBlocks();

const event = new Blockly.Events.BlockCreate(shadowBlock);
event.run(true);

const blocksAfter = this.workspace.getAllBlocks();
chai.assert.deepEqual(
blocksAfter,
blocksBefore,
'No new blocks should be created from an event that only creates shadow blocks',
);
});

suite('Serialization', function () {
test('events round-trip through JSON', function () {
const block = this.workspace.newBlock('row_block', 'block_id');
Expand Down

0 comments on commit b9a7a0c

Please sign in to comment.