FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

fix(worker): route worker_threads errors like the web surface, and fire once listeners once by adrian-niculescu · Pull Request #491 · NativeScript/ios · GitHub

Repository navigation

fix(worker): route worker_threads errors like the web surface, and fire once listeners once - #491

Open
adrian-niculescu wants to merge 2 commits into
NativeScript:mainfrom
adrian-niculescu:fix/worker-threads-error-routing
Open

adrian-niculescu wants to merge 2 commits into
NativeScript:mainfrom
adrian-niculescu:fix/worker-threads-error-routing

Conversation

adrian-niculescu commented Oct 6, 2026 •
edited by coderabbitai Bot
Loading

Copy link
Copy Markdown
Contributor

A parentPort.on("message") listener that throws never reaches the worker's onerror or the parent's worker.on("error"). The relay dispatched without rethrowing, so the throw went to the uncaught-error reporter and stopped there. It now dispatches the way worker-global message delivery does.

An error that a worker.on("error") listener handled was also reported to the parent's global scope as unhandled, because the Worker's onerror returned nothing. It now returns whether a listener ran, which cancels the event, and the emitter reports that the way Node's emit does.

A once listener could fire twice: when an earlier listener emitted the same event again, the nested emit fired and removed it, and the outer emit then called it a second time from its snapshot. A once registration now records that it fired, as Node's once wrapper does, so a once listener an earlier listener removed still fires, as in Node.

The same fix for Android is NativeScript/android#2065. All three new specs fail on main and pass here, and the full TestRunner suite passes.

Summary by CodeRabbit

  • Bug Fixes
    • Worker errors handled by their registered error listeners are no longer also reported to the parent scope’s global error listener.
    • One-time event listeners now run only once, even when an event is emitted again recursively while the listener is running.
    • Errors thrown by message handlers are delivered to the parent worker’s error listener exactly once.

…errors like the web surface

A parentPort listener that threw was dispatched without rethrowing, so the error went to the uncaught-error reporter and never reached the worker's onerror or its parent. The relay now dispatches the way worker-global message delivery does.

The worker_threads Worker's onerror handler returned nothing, so an error its 'error' listeners took was also reported to the parent's global scope as unhandled. It returns whether a listener ran, which cancels the event.

coderabbitai Bot commented Oct 6, 2026 •
edited
Loading

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info ⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 28ff14d2-d3cf-4519-99ec-2164703f224c
📥 Commits

Reviewing files that changed from the base of the PR and between 4ae32eb and e823dff.

📒 Files selected for processing (3)
  • NativeScript/runtime/js/node-worker-threads.js
  • TestRunner/app/tests/MessagingTests.js
  • TestRunner/app/tests/messaging/parentPortThrowingWorker.js

Included review availability: This review used your included allowance. Your plan provides up to 2 included reviews per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

Worker event emission now reports whether listeners were registered and prevents a once-listener from firing again during nested emission. Worker-scope error forwarding uses rethrowing dispatch. New regression tests cover these event and error cases.

Changes

Worker event handling

Layer / File(s) Summary
Emission results and once-listeners
NativeScript/runtime/js/node-worker-threads.js, TestRunner/app/tests/MessagingTests.js
WorkerEmitter.emit returns false when no listeners are registered and true after dispatch. Once-listeners are marked fired before invocation. A regression test checks that recursive emission does not invoke a once-listener again.
Worker error forwarding
NativeScript/runtime/js/node-worker-threads.js, TestRunner/app/tests/MessagingTests.js, TestRunner/app/tests/messaging/parentPortThrowingWorker.js
The worker error handler returns the result of emitting "error", and the worker-scope relay uses dispatchEventRethrowing. Regression tests check handled worker errors and errors thrown by parentPort message listeners.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Suggested reviewers: edusperoni

Merge Risk: ⚪ Minimal · up to e823d

The reviewed worker error and once-listener paths show no actionable merge-blocking issue. Merge after normal checks.

🚥 Pre-merge checks | ✅ 5 ✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies both main changes: worker error routing and reentrant once-listener behavior.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 3…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

A rabbit taps a message through,
A once-listener runs once, not two.
An error finds its listener’s ear,
The worker sends the signal clear.
Then hops away, with tests in view.

Comment @coderabbitai help to get the list of available commands.

… reentrant emit

An earlier listener that emitted the same event again let the nested emit fire and remove a later once listener, and the outer emit then called it a second time from its snapshot. A once registration now records that it fired, as Node's once wrapper does.
adrian-niculescu changed the title fix(worker): route parentPort listener throws and handled Node-style errors like the web surface fix(worker): route worker_threads errors like the web surface, and fire once listeners once Oct 6, 2026
adrian-niculescu marked this pull request as ready for review October 6, 2026 19:22

Copy link
Copy Markdown
Collaborator

Thanks, the once-wrapper and relay changes look right. I checked the once semantics against Node 24.18 and lib/events.js on main: the fired flag matches _onceWrap, and the nested-emit case produces the same call sequence.

Two things before merging:

  1. What worker.on("error") receives. worker.onerror forwards the runtime's ErrorEvent, so a Node-style listener gets an event object, not an Error. In Node the listener gets the deserialized error (instanceof Error is true, name and message preserved). The new spec only asserts error.message, which both shapes satisfy, so it can't tell them apart. Could you build an Error from the event in worker.onerror (message, with stack from event.stackTrace) and have the spec assert error instanceof Error? The error name doesn't survive the forwarding payload today; that can stay a follow-up.

  2. The cancel. return self.emit("error", error) works because this runtime treats a truthy return from Worker.prototype.onerror as handled. Per HTML that's inverted for a Worker object: special error event handling only applies to global scopes, and on a Worker object return false is what cancels. We pin our behavior in the shared tests, so it isn't wrong here, but if (self.emit("error", error)) error.preventDefault(); says what it means and doesn't lean on that contract.

Not for this PR, just recording the remaining gap: Node terminates the worker after an uncaught throw and emits exit with code 1. We keep the worker alive and exit is always 0. No spec covers either side of that.

This branch has not been deployed

No deployments
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants


Back | FazBrowse Home | New Git URL