diff --git a/c/interface.c b/c/interface.c index 2f1f1b1f..3196c6c9 100644 --- a/c/interface.c +++ b/c/interface.c @@ -597,20 +597,20 @@ JSValueConst *QTS_ArgvGetJSValueConstPointer(JSValueConst *argv, int index) { // -------------------- // interrupt: C -> Host #ifdef __EMSCRIPTEN__ -EM_JS(int, qts_host_interrupt_handler, (JSRuntime * rt), { +EM_JS(int, qts_host_interrupt_handler, (JSRuntime * rt, JSContext *ctx), { // Async not supported here. // #ifdef QTS_ASYNCIFY // const asyncify = Asyncify; // #else const asyncify = undefined; // #endif - return Module['callbacks']['shouldInterrupt'](asyncify, rt); + return Module['callbacks']['shouldInterrupt'](asyncify, rt, ctx); }); #endif // interrupt: QuickJS -> C -int qts_interrupt_handler(JSRuntime *rt, void *_unused) { - return qts_host_interrupt_handler(rt); +int qts_interrupt_handler(JSRuntime *rt, JSContext *ctx, void *_unused) { + return qts_host_interrupt_handler(rt, ctx); } // interrupt: Host -> QuickJS diff --git a/quickjs/quickjs-libc.c b/quickjs/quickjs-libc.c index e180dd0c..058a3cc1 100644 --- a/quickjs/quickjs-libc.c +++ b/quickjs/quickjs-libc.c @@ -721,7 +721,7 @@ static JSValue js_std_gc(JSContext *ctx, JSValueConst this_val, return JS_UNDEFINED; } -static int interrupt_handler(JSRuntime *rt, void *opaque) +static int interrupt_handler(JSRuntime *rt, JSContext *ctx, void *opaque) { return (os_pending_signals >> SIGINT) & 1; } diff --git a/quickjs/quickjs.c b/quickjs/quickjs.c index 48aeffc6..3af8e624 100644 --- a/quickjs/quickjs.c +++ b/quickjs/quickjs.c @@ -6775,7 +6775,7 @@ static no_inline __exception int __js_poll_interrupts(JSContext *ctx) JSRuntime *rt = ctx->rt; ctx->interrupt_counter = JS_INTERRUPT_COUNTER_INIT; if (rt->interrupt_handler) { - if (rt->interrupt_handler(rt, rt->interrupt_opaque)) { + if (rt->interrupt_handler(rt, ctx, rt->interrupt_opaque)) { /* XXX: should set a specific flag to avoid catching */ JS_ThrowInternalError(ctx, "interrupted"); JS_SetUncatchableError(ctx, ctx->rt->current_exception, TRUE); diff --git a/quickjs/quickjs.h b/quickjs/quickjs.h index d4a5cd31..a47f5d49 100644 --- a/quickjs/quickjs.h +++ b/quickjs/quickjs.h @@ -840,7 +840,7 @@ typedef void JSHostPromiseRejectionTracker(JSContext *ctx, JSValueConst promise, void JS_SetHostPromiseRejectionTracker(JSRuntime *rt, JSHostPromiseRejectionTracker *cb, void *opaque); /* return != 0 if the JS code needs to be interrupted */ -typedef int JSInterruptHandler(JSRuntime *rt, void *opaque); +typedef int JSInterruptHandler(JSRuntime *rt, JSContext *ctx, void *opaque); void JS_SetInterruptHandler(JSRuntime *rt, JSInterruptHandler *cb, void *opaque); /* if can_block is TRUE, Atomics.wait() can be used */ void JS_SetCanBlock(JSRuntime *rt, JS_BOOL can_block); diff --git a/ts/emscripten-types.ts b/ts/emscripten-types.ts index 6f5023f2..1f726a0c 100644 --- a/ts/emscripten-types.ts +++ b/ts/emscripten-types.ts @@ -147,7 +147,8 @@ export interface EmscriptenModuleCallbacks { shouldInterrupt: ( asyncify: Asyncify | undefined, - rt: JSRuntimePointer + rt: JSRuntimePointer, + ctx: JSContextPointer, ) => 0 | 1 | AsyncifySleepResult<0 | 1> } diff --git a/ts/runtime.ts b/ts/runtime.ts index 77489d37..16e58560 100644 --- a/ts/runtime.ts +++ b/ts/runtime.ts @@ -30,7 +30,7 @@ import { SuccessOrFail } from "./vm-interface" * @returns `true` to interrupt JS execution inside the VM. * @returns `false` or `undefined` to continue JS execution inside the VM. */ -export type InterruptHandler = (runtime: QuickJSRuntime) => boolean | undefined +export type InterruptHandler = (runtime: QuickJSRuntime, context?: QuickJSContext) => boolean | undefined /** * Used as an optional for the results of executing pendingJobs. @@ -340,17 +340,19 @@ export class QuickJSRuntime implements Disposable { } private cToHostCallbacks: RuntimeCallbacks = { - shouldInterrupt: (rt) => { + shouldInterrupt: (rt, ctx) => { if (rt !== this.rt.value) { throw new Error("QuickJSContext instance received C -> JS interrupt with mismatched rt") } + const context = this.contextMap.get(ctx) + const fn = this.interruptHandler if (!fn) { throw new Error("QuickJSContext had no interrupt handler") } - return fn(this) ? 1 : 0 + return fn(this, context) ? 1 : 0 }, loadModuleSource: maybeAsyncFn(this, function* (awaited, rt, ctx, moduleName) {