From a5126d117625b29b68ad18751105fa65963fffa1 Mon Sep 17 00:00:00 2001 From: Beka Westberg Date: Wed, 13 Mar 2024 16:23:11 +0000 Subject: [PATCH] fix!: have disposing be true from start of dispose (#7891) --- core/block.ts | 8 +++----- core/block_svg.ts | 4 ++-- core/connection.ts | 9 ++++++--- core/xml.ts | 6 +++--- tests/mocha/block_test.js | 22 +++++++++++++++++----- 5 files changed, 31 insertions(+), 18 deletions(-) diff --git a/core/block.ts b/core/block.ts index ea7b63a7a..394459e92 100644 --- a/core/block.ts +++ b/core/block.ts @@ -189,7 +189,7 @@ export class Block implements IASTNodeLocation, IDeletable { /** * Is the current block currently in the process of being disposed? */ - private disposing = false; + protected disposing = false; /** * Has this block been fully initialized? E.g. all fields initailized. @@ -319,7 +319,7 @@ export class Block implements IASTNodeLocation, IDeletable { * children of this block. */ dispose(healStack: boolean) { - if (this.isDeadOrDying()) return; + this.disposing = true; // Dispose of this change listener before unplugging. // Technically not necessary due to the event firing delay. @@ -342,15 +342,13 @@ export class Block implements IASTNodeLocation, IDeletable { * E.g. does not fire events, unplug the block, etc. */ protected disposeInternal() { - if (this.isDeadOrDying()) return; - + this.disposing = true; if (this.onchangeWrapper_) { this.workspace.removeChangeListener(this.onchangeWrapper_); } this.workspace.removeTypedBlock(this); this.workspace.removeBlockById(this.id); - this.disposing = true; if (typeof this.destroy === 'function') this.destroy(); diff --git a/core/block_svg.ts b/core/block_svg.ts index 87a8cc6c5..f276d1e8e 100644 --- a/core/block_svg.ts +++ b/core/block_svg.ts @@ -776,7 +776,7 @@ export class BlockSvg * @param animate If true, show a disposal animation and sound. */ override dispose(healStack?: boolean, animate?: boolean) { - if (this.isDeadOrDying()) return; + this.disposing = true; Tooltip.dispose(); ContextMenu.hide(); @@ -795,7 +795,7 @@ export class BlockSvg * E.g. does trigger UI effects, remove nodes, etc. */ override disposeInternal() { - if (this.isDeadOrDying()) return; + this.disposing = true; super.disposeInternal(); if (common.getSelected() === this) { diff --git a/core/connection.ts b/core/connection.ts index 56ba4c3a5..56bf4c3e7 100644 --- a/core/connection.ts +++ b/core/connection.ts @@ -153,8 +153,10 @@ export class Connection implements IASTNodeLocationWithBlock { dispose() { // isConnected returns true for shadows and non-shadows. if (this.isConnected()) { - // Destroy the attached shadow block & its children (if it exists). - this.setShadowStateInternal(); + if (this.isSuperior()) { + // Destroy the attached shadow block & its children (if it exists). + this.setShadowStateInternal(); + } const targetBlock = this.targetBlock(); if (targetBlock && !targetBlock.isDeadOrDying()) { @@ -600,6 +602,8 @@ export class Connection implements IASTNodeLocationWithBlock { this.shadowDom = shadowDom; this.shadowState = shadowState; + if (this.getSourceBlock().isDeadOrDying()) return; + const target = this.targetBlock(); if (!target) { this.respawnShadow_(); @@ -608,7 +612,6 @@ export class Connection implements IASTNodeLocationWithBlock { } } else if (target.isShadow()) { target.dispose(false); - if (this.getSourceBlock().isDeadOrDying()) return; this.respawnShadow_(); if (this.targetBlock() && this.targetBlock()!.isShadow()) { this.serializeShadow(this.targetBlock()); diff --git a/core/xml.ts b/core/xml.ts index ee72f526b..0f2c4f143 100644 --- a/core/xml.ts +++ b/core/xml.ts @@ -250,13 +250,13 @@ export function blockToDom( if (!block.isEnabled()) { element.setAttribute('disabled', 'true'); } - if (!block.isDeletable() && !block.isShadow()) { + if (!block.isOwnDeletable()) { element.setAttribute('deletable', 'false'); } - if (!block.isMovable() && !block.isShadow()) { + if (!block.isOwnMovable()) { element.setAttribute('movable', 'false'); } - if (!block.isEditable()) { + if (!block.isOwnEditable()) { element.setAttribute('editable', 'false'); } diff --git a/tests/mocha/block_test.js b/tests/mocha/block_test.js index f5b2e6a82..c57ccbb15 100644 --- a/tests/mocha/block_test.js +++ b/tests/mocha/block_test.js @@ -67,9 +67,9 @@ suite('Blocks', function () { function createTestBlocks(workspace, isRow) { const blockType = isRow ? 'row_block' : 'stack_block'; - const blockA = workspace.newBlock(blockType); - const blockB = workspace.newBlock(blockType); - const blockC = workspace.newBlock(blockType); + const blockA = workspace.newBlock(blockType, 'a'); + const blockB = workspace.newBlock(blockType, 'b'); + const blockC = workspace.newBlock(blockType, 'c'); if (isRow) { blockA.inputList[0].connection.connect(blockB.outputConnection); @@ -386,8 +386,14 @@ suite('Blocks', function () { test('Child is shadow', function () { const blocks = this.blocks; - blocks.C.setShadow(true); + blocks.C.dispose(); + blocks.B.inputList[0].connection.setShadowState({ + 'type': 'row_block', + 'id': 'c', + }); + blocks.B.dispose(true); + // Even though we're asking to heal, it will appear as if it has not // healed because shadows always get destroyed. assertDisposedNoheal(blocks); @@ -423,8 +429,14 @@ suite('Blocks', function () { test('Child is shadow', function () { const blocks = this.blocks; - blocks.C.setShadow(true); + blocks.C.dispose(); + blocks.B.nextConnection.setShadowState({ + 'type': 'stack_block', + 'id': 'c', + }); + blocks.B.dispose(true); + // Even though we're asking to heal, it will appear as if it has not // healed because shadows always get destroyed. assertDisposedNoheal(blocks);