stability: drop async module completions after termination

Assisted-By: devx/c74ae588-eb01-43ac-9c5d-2e6938841883
This commit is contained in:
Scott Taylor committed 2026-08-24 12:32:26 -04:00
1 parent 910395c764
commit 8673f0815e
1 file changed
+39
+39
View File
@@ -912,6 +912,12 @@ fn dynamicModuleSourceCallback(ctx: *anyopaque, module_source_: anyerror!ScriptM
const state: *DynamicModuleResolveState = @ptrCast(@alignCast(ctx));
var self = state.context;
if (self.env.terminatePending()) {
var module_source = module_source_ catch return;
module_source.deinit();
return;
}
var ls: js.Local.Scope = undefined;
self.localScope(&ls);
defer ls.deinit();
@@ -1024,6 +1030,39 @@ fn resolveDynamicModule(self: *Context, state: *DynamicModuleResolveState, modul
};
}
const testing = @import("../../testing.zig");
test "Context: terminated async module completion does not re-enter V8" {
const frame = try testing.createFrame();
defer testing.test_session.closeAllPages();
var ls: js.Local.Scope = undefined;
frame.js.localScope(&ls);
defer ls.deinit();
const local = &ls.local;
const resolver = local.createPromiseResolver();
const promise = resolver.promise();
const resolver_global = try resolver.persist();
defer resolver_global.deinit();
var state = DynamicModuleResolveState{
.module = null,
.context_id = frame.js.id,
.context = frame.js,
.specifier = "https://example.com/late-module.js",
.resolver = resolver_global,
};
const env = frame.js.env;
env.terminate();
js.v8.v8__Isolate__CancelTerminateExecution(env.isolate.handle);
defer env.cancelTerminate();
dynamicModuleSourceCallback(&state, error.Abort);
try testing.expectEqual(js.Promise.State.pending, promise.state());
}
// Used to make temporarily enter and exit a context, updating and restoring
// frame.js:
// var hs: js.HandleScope = undefined;