diff --git a/core/flyout_base.ts b/core/flyout_base.ts index 492d3341762..358c5532c9e 100644 --- a/core/flyout_base.ts +++ b/core/flyout_base.ts @@ -135,6 +135,12 @@ export abstract class Flyout */ private reflowWrapper: ((e: AbstractEvent) => void) | null = null; + /** + * If true, prevents the reflow wrapper from running. Used to prevent infinite + * recursion. + */ + private inhibitReflowWrapper = false; + /** * List of flyout elements. */ @@ -647,6 +653,7 @@ export abstract class Flyout // accommodates e.g. resizing a non-autoclosing flyout in response to the // user typing long strings into fields on the blocks in the flyout. this.reflowWrapper = (event) => { + if (this.inhibitReflowWrapper) return; if ( event.type === EventType.BLOCK_CHANGE || event.type === EventType.BLOCK_FIELD_INTERMEDIATE_CHANGE @@ -844,13 +851,9 @@ export abstract class Flyout * Reflow flyout contents. */ reflow() { - if (this.reflowWrapper) { - this.workspace_.removeChangeListener(this.reflowWrapper); - } + this.inhibitReflowWrapper = true; this.reflowInternal_(); - if (this.reflowWrapper) { - this.workspace_.addChangeListener(this.reflowWrapper); - } + this.inhibitReflowWrapper = false; } /** diff --git a/tests/mocha/flyout_test.js b/tests/mocha/flyout_test.js index 998279a0874..e2812b25ba3 100644 --- a/tests/mocha/flyout_test.js +++ b/tests/mocha/flyout_test.js @@ -43,6 +43,26 @@ suite('Flyout', function () { sharedTestTeardown.call(this); }); + suite('workspace change listeners', function () { + test('are triggered when a child block changes', function () { + let listenerTriggered = false; + const listener = (e) => { + if (e.type === Blockly.Events.BLOCK_CHANGE) { + listenerTriggered = true; + } + }; + this.workspace.getFlyout().getWorkspace().addChangeListener(listener); + const boolBlock = this.workspace + .getFlyout() + .getWorkspace() + .getBlocksByType('logic_compare')[0]; + boolBlock.getField('OP').setValue('LTE'); + this.clock.tick(1000); + assert.isTrue(listenerTriggered); + this.workspace.getFlyout().getWorkspace().removeChangeListener(listener); + }); + }); + suite('position', function () { suite('vertical flyout', function () { suite('simple flyout', function () {