Skip to content

Commit f50597d

Browse files
authored
fix(worker): rethrow ordinary failures until a termination materializes
ReThrowToV8 skipped the throw whenever the runtime's termination-requested flag was set. Between terminate() setting that flag and V8 delivering the interrupt, JS still runs, so an ordinary native failure in that window returned nothing: require() yielded undefined and a native constructor handed back an uninitialized object, which a following call could trip an assert on in Debug builds. The skip now keys on IsExecutionTerminating() alone; inside a callback a materialized termination is never cleared on the way up, so that signal is sufficient there. Also gives the module-instantiate failure in LoadESModule the same termination check as the runner's other failure sites, so a terminated link is reported as an interruption rather than logged as an instantiation error.
1 parent f21db6f commit f50597d

2 files changed

Lines changed: 13 additions & 7 deletions

File tree

‎NativeScript/runtime/ModuleInternal.mm‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1652,6 +1652,13 @@ throw NativeScriptException(isolate, tcCompile,
16521652

16531653
if (!linked) {
16541654
RemoveModuleFromRegistry(isolate, canonicalPath);
1655+
Runtime* runtime = Runtime::GetRuntime(isolate);
1656+
if (tcLink.HasTerminated() || isolate->IsExecutionTerminating() ||
1657+
(runtime != nullptr && runtime->IsTerminationRequested())) {
1658+
logPhase("instantiate", "terminated");
1659+
throw NativeScriptException("Module evaluation interrupted by isolate termination: " +
1660+
canonicalPath);
1661+
}
16551662
const char* classification = "unknown";
16561663
if (tcLink.HasCaught()) {
16571664
Local<Message> msg = tcLink.Message();

‎NativeScript/runtime/NativeScriptException.mm‎

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -714,13 +714,12 @@ static bool GiveWorkerOnErrorAChance(Isolate* isolate, Local<Context> context, L
714714
}
715715

716716
void NativeScriptException::ReThrowToV8(Isolate* isolate) {
717-
// An isolate that is terminating keeps its termination pending until the JS
718-
// frames below unwind; throwing on it would replace that with an ordinary
719-
// error, and building the error allocates on a heap that may have just hit
720-
// its cap. The failure being re-armed here is the termination itself.
721-
Runtime* runtime = Runtime::GetRuntime(isolate);
722-
if (isolate->IsExecutionTerminating() ||
723-
(runtime != nullptr && runtime->IsTerminationRequested())) {
717+
// A materialized termination stays pending until the JS frames below
718+
// unwind; throwing would replace it with an ordinary error. Only the V8
719+
// signal counts here, not the runtime's termination-requested flag: while
720+
// the request has not materialized, JS still runs, and an ordinary failure
721+
// must still throw or the caller would continue with a bogus result.
722+
if (isolate->IsExecutionTerminating()) {
724723
return;
725724
}
726725
@try {

0 commit comments

Comments
 (0)