Skip to content

Commit ceb1153

Browse files
committed
fix(worker): surface worker entry-script load errors to worker.onerror
In debug builds the module loader swallows compile/require errors (CompileScript returns an empty script; RunModule logs and returns success) so a bad HMR edit doesn't abort the main app. That also swallowed a *worker's* entry-script error, so `worker.onerror` never fired (e.g. a worker loaded from a syntactically invalid script hung the spec until the Jasmine async timeout). Gate the debug swallow on `!isWorker`: worker isolates now propagate the error (as release already does) and keep the V8 exception pending so the worker entry's TryCatch routes it to `worker.onerror`. Main-isolate HMR behavior is unchanged.
1 parent 5dd6277 commit ceb1153

1 file changed

Lines changed: 14 additions & 2 deletions

File tree

NativeScript/runtime/ModuleInternal.mm

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,9 @@ static inline void SetOutErrorMessage(std::string* outErrorMessage,
302302
success = requireFunc->Call(context, globalObject, 1, args).ToLocal(&result);
303303

304304
if (!success || tc.HasCaught()) {
305-
if (RuntimeConfig.IsDebug) {
305+
// Main isolate stays alive in debug for HMR; worker isolates must surface
306+
// the failure so `worker.onerror` fires (handled in the else branch).
307+
if (RuntimeConfig.IsDebug && !cache->isWorker) {
306308
Log(@"***** JavaScript exception occurred - detailed stack trace follows *****");
307309
Log(@"Error in require() call:");
308310
Log(@" Requested module: '%s'", path.c_str());
@@ -347,6 +349,12 @@ static inline void SetOutErrorMessage(std::string* outErrorMessage,
347349
std::string("require() failed for module ") + path;
348350
}
349351
SetOutErrorMessage(outErrorMessage, requireFailureMessage);
352+
// For worker isolates, keep the V8 exception pending so the worker entry's
353+
// TryCatch (Worker.mm) catches it and routes it to worker.onerror. The
354+
// main isolate's release path is unchanged (no rethrow).
355+
if (cache->isWorker && tc.HasCaught()) {
356+
tc.ReThrow();
357+
}
350358
return false;
351359
}
352360
}
@@ -934,7 +942,11 @@ ScriptOrigin origin(isolate, urlString,
934942
TryCatch tc(isolate);
935943
Local<Script> script;
936944
if (!ScriptCompiler::Compile(context, &source, opts).ToLocal(&script) || tc.HasCaught()) {
937-
if (RuntimeConfig.IsDebug) {
945+
// The main isolate swallows compile errors in debug and continues so a bad
946+
// HMR edit doesn't abort the app (the dev overlay surfaces it). Worker
947+
// isolates must NOT swallow: a worker entry-script error has to propagate so
948+
// `worker.onerror` fires. So fall through to the throw path for workers.
949+
if (RuntimeConfig.IsDebug && !Caches::Get(isolate)->isWorker) {
938950
// Mark that a JavaScript error occurred
939951
jsErrorOccurred = true;
940952

0 commit comments

Comments
 (0)