From 0c0c387f346f03ab83fffec597440a8c1648f2f7 Mon Sep 17 00:00:00 2001 From: the-can-of-soup <91906096+the-can-of-soup@users.noreply.github.com> Date: Thu, 29 Jan 2026 01:34:12 -0500 Subject: [PATCH 1/9] Add before and after tick events (1/2) --- src/engine/runtime.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/engine/runtime.js b/src/engine/runtime.js index 402ce043c6..95fd3dbe77 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -1165,6 +1165,22 @@ class Runtime extends EventEmitter { return 'THREAD_FINISHED' } + /** + * Event name for before the sequencer executes a tick. + * @const {string} + */ + static get BEFORE_TICK () { + return 'BEFORE_TICK' + } + + /** + * Event name for after the sequencer executes a tick. + * @const {string} + */ + static get AFTER_TICK () { + return 'AFTER_TICK' + } + /** * Event name for sprite renaming. * @const {string} From 0fd3e7d58cec909ec5760fe8259b10ec9cb5d14d Mon Sep 17 00:00:00 2001 From: the-can-of-soup <91906096+the-can-of-soup@users.noreply.github.com> Date: Thu, 29 Jan 2026 01:36:59 -0500 Subject: [PATCH 2/9] Add before and after tick events (2/2) --- src/engine/sequencer.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/engine/sequencer.js b/src/engine/sequencer.js index d4fa50d114..58a6d95b25 100644 --- a/src/engine/sequencer.js +++ b/src/engine/sequencer.js @@ -102,6 +102,7 @@ class Sequencer { let stoppedThread = false; // Attempt to run each thread one time. const threads = this.runtime.threads; + this.runtime.emit('BEFORE_TICK', threads); for (this.activeThreadIndex = 0; this.activeThreadIndex < threads.length; this.activeThreadIndex++) { const i = this.activeThreadIndex; const activeThread = this.activeThread = threads[i]; @@ -148,6 +149,7 @@ class Sequencer { stoppedThread = true; } } + this.runtime.emit('AFTER_TICK', threads); // We successfully ticked once. Prevents running STATUS_YIELD_TICK // threads on the next tick. ranFirstTick = true; From 315fa823e7a645b236881d867e6cc3c913d06c2a Mon Sep 17 00:00:00 2001 From: the-can-of-soup <91906096+the-can-of-soup@users.noreply.github.com> Date: Thu, 29 Jan 2026 02:13:42 -0500 Subject: [PATCH 3/9] Whoops forgot this in #173 --- src/engine/sequencer.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/engine/sequencer.js b/src/engine/sequencer.js index 58a6d95b25..98b04ae743 100644 --- a/src/engine/sequencer.js +++ b/src/engine/sequencer.js @@ -177,6 +177,7 @@ class Sequencer { } this.activeThread = null; + this.activeThreadIndex = null; return doneThreads; } From b511bb95eda30135f1f4920a68855605afb7ab5c Mon Sep 17 00:00:00 2001 From: the-can-of-soup <91906096+the-can-of-soup@users.noreply.github.com> Date: Wed, 4 Feb 2026 13:16:59 -0500 Subject: [PATCH 4/9] Add before and after step events (1/2) --- src/engine/runtime.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/engine/runtime.js b/src/engine/runtime.js index 95fd3dbe77..719493f1c7 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -1181,6 +1181,22 @@ class Runtime extends EventEmitter { return 'AFTER_TICK' } + /** + * Event name for before the sequencer steps a thread. + * @const {string} + */ + static get BEFORE_STEP () { + return 'BEFORE_STEP' + } + + /** + * Event name for after the sequencer steps a thread. + * @const {string} + */ + static get AFTER_STEP () { + return 'AFTER_STEP' + } + /** * Event name for sprite renaming. * @const {string} From fed3caf2a2d8fddd698a568d61a6fefe135bebde Mon Sep 17 00:00:00 2001 From: the-can-of-soup <91906096+the-can-of-soup@users.noreply.github.com> Date: Wed, 4 Feb 2026 13:23:02 -0500 Subject: [PATCH 5/9] Add before and after step events (2/2) --- src/engine/sequencer.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/engine/sequencer.js b/src/engine/sequencer.js index 98b04ae743..924545ba23 100644 --- a/src/engine/sequencer.js +++ b/src/engine/sequencer.js @@ -103,9 +103,11 @@ class Sequencer { // Attempt to run each thread one time. const threads = this.runtime.threads; this.runtime.emit('BEFORE_TICK', threads); - for (this.activeThreadIndex = 0; this.activeThreadIndex < threads.length; this.activeThreadIndex++) { + for (this.activeThreadIndex = 0; this.activeThreadIndex < threads.length; this.activeThreadIndex++, + this.runtime.emit('AFTER_STEP', this.activeThread)) { const i = this.activeThreadIndex; const activeThread = this.activeThread = threads[i]; + this.runtime.emit('BEFORE_STEP', activeThread); // Check if the thread is done so it is not executed. if (activeThread.stack.length === 0 || activeThread.status === Thread.STATUS_DONE) { From d71a2b79f6903589123cc8a4930fa5205d1a1ac9 Mon Sep 17 00:00:00 2001 From: the-can-of-soup <91906096+the-can-of-soup@users.noreply.github.com> Date: Wed, 4 Feb 2026 20:06:51 -0500 Subject: [PATCH 6/9] Rename before and after thread step events (1/2) --- src/engine/runtime.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/engine/runtime.js b/src/engine/runtime.js index 719493f1c7..afdd599c33 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -1185,16 +1185,16 @@ class Runtime extends EventEmitter { * Event name for before the sequencer steps a thread. * @const {string} */ - static get BEFORE_STEP () { - return 'BEFORE_STEP' + static get BEFORE_THREAD_STEP () { + return 'BEFORE_THREAD_STEP' } /** * Event name for after the sequencer steps a thread. * @const {string} */ - static get AFTER_STEP () { - return 'AFTER_STEP' + static get AFTER_THREAD_STEP () { + return 'AFTER_THREAD_STEP' } /** From e83dcd676cf6309e43e0f4d550772c8a9ba51d32 Mon Sep 17 00:00:00 2001 From: the-can-of-soup <91906096+the-can-of-soup@users.noreply.github.com> Date: Wed, 4 Feb 2026 20:07:13 -0500 Subject: [PATCH 7/9] Rename before and after thread step events (2/2) --- src/engine/sequencer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/engine/sequencer.js b/src/engine/sequencer.js index 924545ba23..015eb5a9bf 100644 --- a/src/engine/sequencer.js +++ b/src/engine/sequencer.js @@ -104,10 +104,10 @@ class Sequencer { const threads = this.runtime.threads; this.runtime.emit('BEFORE_TICK', threads); for (this.activeThreadIndex = 0; this.activeThreadIndex < threads.length; this.activeThreadIndex++, - this.runtime.emit('AFTER_STEP', this.activeThread)) { + this.runtime.emit('AFTER_THREAD_STEP', this.activeThread)) { const i = this.activeThreadIndex; const activeThread = this.activeThread = threads[i]; - this.runtime.emit('BEFORE_STEP', activeThread); + this.runtime.emit('BEFORE_THREAD_STEP', activeThread); // Check if the thread is done so it is not executed. if (activeThread.stack.length === 0 || activeThread.status === Thread.STATUS_DONE) { From 984741bb1b8f537a3eae5bd40d8f9acb696af1ae Mon Sep 17 00:00:00 2001 From: the-can-of-soup <91906096+the-can-of-soup@users.noreply.github.com> Date: Wed, 4 Feb 2026 20:58:15 -0500 Subject: [PATCH 8/9] Split before and after step event into two (1/2) --- src/engine/sequencer.js | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/engine/sequencer.js b/src/engine/sequencer.js index 015eb5a9bf..e12229d054 100644 --- a/src/engine/sequencer.js +++ b/src/engine/sequencer.js @@ -104,10 +104,10 @@ class Sequencer { const threads = this.runtime.threads; this.runtime.emit('BEFORE_TICK', threads); for (this.activeThreadIndex = 0; this.activeThreadIndex < threads.length; this.activeThreadIndex++, - this.runtime.emit('AFTER_THREAD_STEP', this.activeThread)) { + this.runtime.emit('AFTER_THREAD_CONSIDERED', this.activeThread)) { const i = this.activeThreadIndex; const activeThread = this.activeThread = threads[i]; - this.runtime.emit('BEFORE_THREAD_STEP', activeThread); + this.runtime.emit('BEFORE_THREAD_CONSIDERED', activeThread); // Check if the thread is done so it is not executed. if (activeThread.stack.length === 0 || activeThread.status === Thread.STATUS_DONE) { @@ -189,8 +189,11 @@ class Sequencer { * @param {!Thread} thread Thread object to step. */ stepThread (thread) { + this.runtime.emit('BEFORE_THREAD_STEP', thread); + if (thread.isCompiled) { compilerExecute(thread); + this.runtime.emit('AFTER_THREAD_STEP', thread); return; } @@ -203,6 +206,7 @@ class Sequencer { if (thread.stack.length === 0) { thread.status = Thread.STATUS_DONE; this.runtime.emit('THREAD_FINISHED', thread); + this.runtime.emit('AFTER_THREAD_STEP', thread); return; } } @@ -244,12 +248,15 @@ class Sequencer { // A promise was returned by the primitive. Yield the thread // until the promise resolves. Promise resolution should reset // thread.status to Thread.STATUS_RUNNING. + this.runtime.emit('AFTER_THREAD_STEP', thread); return; } else if (thread.status === Thread.STATUS_YIELD_TICK) { // stepThreads will reset the thread to Thread.STATUS_RUNNING + this.runtime.emit('AFTER_THREAD_STEP', thread); return; } else if (thread.status === Thread.STATUS_DONE) { // Nothing more to execute. + this.runtime.emit('AFTER_THREAD_STEP', thread); return; } // If no control flow has happened, switch to next block. @@ -264,6 +271,7 @@ class Sequencer { // No more stack to run! thread.status = Thread.STATUS_DONE; this.runtime.emit('THREAD_FINISHED', thread); + this.runtime.emit('AFTER_THREAD_STEP', thread); return; } @@ -279,22 +287,27 @@ class Sequencer { thread.warpTimer.timeElapsed() > Sequencer.WARP_TIME) { // Don't do anything to the stack, since loops need // to be re-executed. + this.runtime.emit('AFTER_THREAD_STEP', thread); return; } // Don't go to the next block for this level of the stack, // since loops need to be re-executed. + this.runtime.emit('AFTER_THREAD_STEP', thread); continue; } else if (stackFrame.waitingReporter) { // This level of the stack was waiting for a value. // This means a reporter has just returned - so don't go // to the next block for this level of the stack. + this.runtime.emit('AFTER_THREAD_STEP', thread); return; } // Get next block of existing block on the stack. thread.goToNextBlock(); } } + + this.runtime.emit('AFTER_THREAD_STEP', thread); } /** From 6e4bb738eb27fa0932567f75cf01e2b1bcd367ba Mon Sep 17 00:00:00 2001 From: the-can-of-soup <91906096+the-can-of-soup@users.noreply.github.com> Date: Wed, 4 Feb 2026 21:00:14 -0500 Subject: [PATCH 9/9] Split before and after step event into two (2/2) --- src/engine/runtime.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/engine/runtime.js b/src/engine/runtime.js index afdd599c33..d7df350d70 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -1181,6 +1181,22 @@ class Runtime extends EventEmitter { return 'AFTER_TICK' } + /** + * Event name for before the sequencer considers a thread to be stepped. + * @const {string} + */ + static get BEFORE_THREAD_CONSIDERED () { + return 'BEFORE_THREAD_CONSIDERED' + } + + /** + * Event name for after the sequencer considers a thread to be stepped. + * @const {string} + */ + static get AFTER_THREAD_CONSIDERED () { + return 'AFTER_THREAD_CONSIDERED' + } + /** * Event name for before the sequencer steps a thread. * @const {string}