diff --git a/builtins/web/timers.cpp b/builtins/web/timers.cpp index d4e9a8cb..fe3519b7 100644 --- a/builtins/web/timers.cpp +++ b/builtins/web/timers.cpp @@ -229,4 +229,12 @@ bool install(api::Engine *engine) { return JS_DefineFunctions(engine->cx(), engine->global(), methods); } +void reset() { + for (auto &[id, timer] : TIMERS_MAP->timers_) { + timer->cancel(ENGINE); + } + TIMERS_MAP->timers_.clear(); + TIMERS_MAP->next_timer_id = 1; +} + } // namespace builtins::web::timers diff --git a/builtins/web/timers.h b/builtins/web/timers.h index f88d36bd..38a6cba7 100644 --- a/builtins/web/timers.h +++ b/builtins/web/timers.h @@ -14,6 +14,7 @@ bool set_interval(JSContext *cx, HandleObject handler, JS::HandleValueVector arg void clear_timeout_or_interval(int32_t timer_id); bool install(api::Engine *engine); +void reset(); } // namespace builtins::web::timers diff --git a/include/extension-api.h b/include/extension-api.h index 55af98e7..68da8ab6 100644 --- a/include/extension-api.h +++ b/include/extension-api.h @@ -172,6 +172,7 @@ class Engine { void report_unhandled_promise_rejections(); static void clear_unhandled_promise_rejections(); + void reset(); void abort(const char *reason); static bool debug_logging_enabled(); diff --git a/runtime/engine.cpp b/runtime/engine.cpp index e9da55dd..ae5f025a 100644 --- a/runtime/engine.cpp +++ b/runtime/engine.cpp @@ -3,6 +3,7 @@ #include "debugger.h" #include "encode.h" #include "event_loop.h" +#include "../builtins/web/timers.h" #include "script_loader.h" #include "js/CompilationAndEvaluation.h" @@ -708,3 +709,11 @@ void Engine::report_unhandled_promise_rejections() { void Engine::clear_unhandled_promise_rejections() { JS::SetClear(CONTEXT, unhandledRejectedPromises); } +void Engine::reset() { + clear_unhandled_promise_rejections(); + core::EventLoop::reset(this); + builtins::web::timers::reset(); + core::EventLoop::reset(this); + JS::PrepareForFullGC(cx()); + JS::NonIncrementalGC(cx(), JS::GCOptions::Normal, JS::GCReason::API); +} diff --git a/runtime/event_loop.cpp b/runtime/event_loop.cpp index cdcdaabf..a41994b8 100644 --- a/runtime/event_loop.cpp +++ b/runtime/event_loop.cpp @@ -99,4 +99,13 @@ bool EventLoop::run_event_loop(api::Engine *engine, double total_compute) { void EventLoop::init(JSContext *cx) { queue.init(cx); } +void EventLoop::reset(api::Engine *engine) { + auto &q = queue.get(); + for (const auto& task : q.tasks) { + task->cancel(engine); + } + q.tasks.clear(); + q.interest_cnt = 0; +} + } // namespace core diff --git a/runtime/event_loop.h b/runtime/event_loop.h index acca516c..d8354e1b 100644 --- a/runtime/event_loop.h +++ b/runtime/event_loop.h @@ -41,6 +41,11 @@ class EventLoop { * Remove a queued async task. */ static bool cancel_async_task(api::Engine *engine, const RefPtr& task); + + /** + * Reset the event loop state, cancelling all pending tasks and clearing interest count. + */ + static void reset(api::Engine *engine); }; } // namespace core