diff --git a/src/engine/runtime.js b/src/engine/runtime.js index 4fe871a65..36722a458 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -329,6 +329,24 @@ Runtime.prototype._removeThread = function (thread) { } }; +/** + * Restart a thread in place, maintaining its position in the list of threads. + * This is used by `startHats` to and is necessary to ensure 2.0-like execution order. + * Test project: https://scratch.mit.edu/projects/130183108/ + * @param {!Thread} thread Thread object to restart. + */ +Runtime.prototype._restartThread = function (thread) { + var newThread = new Thread(thread.topBlock); + newThread.target = thread.target; + newThread.pushStack(thread.topBlock); + var i = this.threads.indexOf(thread); + if (i > -1) { + this.threads[i] = newThread; + } else { + this.threads.push(thread); + } +}; + /** * Return whether a thread is currently active/running. * @param {?Thread} thread Thread object to check. @@ -422,7 +440,8 @@ Runtime.prototype.startHats = function (requestedHatOpcode, for (var i = 0; i < instance.threads.length; i++) { if (instance.threads[i].topBlock === topBlockId && instance.threads[i].target === target) { - instance._removeThread(instance.threads[i]); + instance._restartThread(instance.threads[i]); + return; } } } else { diff --git a/src/engine/sequencer.js b/src/engine/sequencer.js index c777949b7..8c732ca9c 100644 --- a/src/engine/sequencer.js +++ b/src/engine/sequencer.js @@ -45,11 +45,9 @@ Sequencer.prototype.stepThreads = function () { this.timer.timeElapsed() < WORK_TIME && (this.runtime.turboMode || !this.runtime.redrawRequested)) { numActiveThreads = 0; - // Inline copy of the threads, updated on each step. - var threadsCopy = this.runtime.threads.slice(); // Attempt to run each thread one time. - for (var i = 0; i < threadsCopy.length; i++) { - var activeThread = threadsCopy[i]; + for (var i = 0; i < this.runtime.threads.length; i++) { + var activeThread = this.runtime.threads[i]; if (activeThread.stack.length === 0 || activeThread.status === Thread.STATUS_DONE) { // Finished with this thread.