diff --git a/src/blocks/scratch3_event.js b/src/blocks/scratch3_event.js index a486bda09..37a254467 100644 --- a/src/blocks/scratch3_event.js +++ b/src/blocks/scratch3_event.js @@ -109,7 +109,17 @@ class Scratch3EventBlocks { const instance = this; const waiting = util.stackFrame.startedThreads.some(thread => instance.runtime.isActiveThread(thread)); if (waiting) { - util.yield(); + // If all threads are waiting for the next tick or later yield + // for a tick as well. Otherwise yield until the next loop of + // the threads. + if ( + util.stackFrame.startedThreads + .every(thread => instance.runtime.isWaitingThread(thread)) + ) { + util.yieldTick(); + } else { + util.yield(); + } } } } diff --git a/src/blocks/scratch3_looks.js b/src/blocks/scratch3_looks.js index d66e1ce95..14e7a5b53 100644 --- a/src/blocks/scratch3_looks.js +++ b/src/blocks/scratch3_looks.js @@ -416,7 +416,17 @@ class Scratch3LooksBlocks { const instance = this; const waiting = util.stackFrame.startedThreads.some(thread => instance.runtime.isActiveThread(thread)); if (waiting) { - util.yield(); + // If all threads are waiting for the next tick or later yield + // for a tick as well. Otherwise yield until the next loop of + // the threads. + if ( + util.stackFrame.startedThreads + .every(thread => instance.runtime.isWaitingThread(thread)) + ) { + util.yieldTick(); + } else { + util.yield(); + } } } diff --git a/src/blocks/scratch3_sound.js b/src/blocks/scratch3_sound.js index 4c637e71a..a599b314c 100644 --- a/src/blocks/scratch3_sound.js +++ b/src/blocks/scratch3_sound.js @@ -231,9 +231,7 @@ class Scratch3SoundBlocks { util.target.audioPlayer.setEffect(effect, soundState.effects[effect]); // Yield until the next tick. - return new Promise(resolve => { - resolve(); - }); + return Promise.resolve(); } _syncEffectsForTarget (target) { @@ -284,9 +282,7 @@ class Scratch3SoundBlocks { util.target.audioPlayer.setVolume(util.target.volume); // Yield until the next tick. - return new Promise(resolve => { - resolve(); - }); + return Promise.resolve(); } getVolume (args, util) { diff --git a/src/engine/block-utility.js b/src/engine/block-utility.js index 2026c0f0d..b456d02fa 100644 --- a/src/engine/block-utility.js +++ b/src/engine/block-utility.js @@ -57,6 +57,13 @@ class BlockUtility { this.thread.status = Thread.STATUS_YIELD; } + /** + * Set the thread to yield until the next tick of the runtime. + */ + yieldTick () { + this.thread.status = Thread.STATUS_YIELD_TICK; + } + /** * Start a branch in the current block. * @param {number} branchNum Which branch to step to (i.e., 1, 2). diff --git a/src/engine/runtime.js b/src/engine/runtime.js index cf6d90a67..5edb79233 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -1017,6 +1017,19 @@ class Runtime extends EventEmitter { this.threads.indexOf(thread) > -1); } + /** + * Return whether a thread is waiting for more information or done. + * @param {?Thread} thread Thread object to check. + * @return {boolean} True if the thread is waiting + */ + isWaitingThread (thread) { + return ( + thread.status === Thread.STATUS_PROMISE_WAIT || + thread.status === Thread.STATUS_YIELD_TICK || + !this.isActiveThread(thread) + ); + } + /** * Toggle a script. * @param {!string} topBlockId ID of block that starts the script.