Skip to content

pass context through on interrupt handlers #91

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions c/interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion quickjs/quickjs-libc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion quickjs/quickjs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion quickjs/quickjs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion ts/emscripten-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,8 @@ export interface EmscriptenModuleCallbacks {

shouldInterrupt: (
asyncify: Asyncify | undefined,
rt: JSRuntimePointer
rt: JSRuntimePointer,
ctx: JSContextPointer,
) => 0 | 1 | AsyncifySleepResult<0 | 1>
}

Expand Down
8 changes: 5 additions & 3 deletions ts/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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) {
Expand Down