Skip to content

Comments

feat(unenv-preset): add native node:worker_threads module support#12043

Merged
petebacondarwin merged 22 commits intomainfrom
devin/1769080195-native-node-worker-threads
Feb 17, 2026
Merged

feat(unenv-preset): add native node:worker_threads module support#12043
petebacondarwin merged 22 commits intomainfrom
devin/1769080195-native-node-worker-threads

Conversation

@petebacondarwin
Copy link
Contributor

@petebacondarwin petebacondarwin commented Jan 22, 2026

Adds support for the native node:worker_threads module from workerd when both the enable_nodejs_worker_threads_module and experimental compatibility flags are enabled. This follows the same pattern as other experimental modules (repl).

Implementation Comparison

Export workerd unenv Breaking change?
MessageChannel globalThis.MessageChannel (native Web API) Custom stub class No - both export as function
MessagePort globalThis.MessagePort (native Web API) Custom stub class No - both export as function
BroadcastChannel throws ERR_METHOD_NOT_IMPLEMENTED No-op stub class Potential - constructor now throws
Worker throws ERR_METHOD_NOT_IMPLEMENTED No-op stub class Potential - constructor now throws
getEnvironmentData / setEnvironmentData Map-based Map-based No (same behavior)
isMainThread, parentPort, threadId, workerData, resourceLimits Same values Same values No
SHARE_ENV Same symbol Same symbol No
postMessageToThread throws ERR_METHOD_NOT_IMPLEMENTED throws "not implemented" No (both throw)
isInternalThread false false No

Breaking change analysis: The main behavioral differences are that Worker and BroadcastChannel constructors now throw ERR_METHOD_NOT_IMPLEMENTED instead of returning no-op instances. This is more correct behavior and uses proper Node.js error codes.

Implementation Notes

  • The test uses getRuntimeFlagValue("enable_nodejs_worker_threads_module") to detect native implementation at runtime (not export sniffing)

Human Review Checklist

  • Verify the getWorkerThreadsOverrides() function follows the same pattern as other experimental modules (requires experimental flag)
  • Confirm the compatibility flag names match workerd's compatibility-date.capnp (enable_nodejs_worker_threads_module / disable_nodejs_worker_threads_module)
  • Review the test coverage for both unenv stub and native workerd implementations
  • Verify native detection uses getRuntimeFlagValue() instead of sniffing exports

Link to Devin run


  • Tests
    • Tests included/updated
    • Automated tests not possible - manual testing has been completed as follows:
    • Additional testing not necessary because:
  • Public documentation
    • Cloudflare docs PR(s):
    • Documentation not necessary because: internal experimental feature, follows existing patterns

@devin-ai-integration
Copy link
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR that start with 'DevinAI' or '@devin'.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@changeset-bot
Copy link

changeset-bot bot commented Jan 22, 2026

🦋 Changeset detected

Latest commit: 3a9da95

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new
Copy link

pkg-pr-new bot commented Jan 22, 2026

create-cloudflare

npm i https://pkg.pr.new/create-cloudflare@12043

@cloudflare/kv-asset-handler

npm i https://pkg.pr.new/@cloudflare/kv-asset-handler@12043

miniflare

npm i https://pkg.pr.new/miniflare@12043

@cloudflare/pages-shared

npm i https://pkg.pr.new/@cloudflare/pages-shared@12043

@cloudflare/unenv-preset

npm i https://pkg.pr.new/@cloudflare/unenv-preset@12043

@cloudflare/vite-plugin

npm i https://pkg.pr.new/@cloudflare/vite-plugin@12043

@cloudflare/vitest-pool-workers

npm i https://pkg.pr.new/@cloudflare/vitest-pool-workers@12043

@cloudflare/workers-editor-shared

npm i https://pkg.pr.new/@cloudflare/workers-editor-shared@12043

@cloudflare/workers-utils

npm i https://pkg.pr.new/@cloudflare/workers-utils@12043

wrangler

npm i https://pkg.pr.new/wrangler@12043

commit: 3a9da95

devin-ai-integration[bot]

This comment was marked as resolved.

@claude
Copy link
Contributor

claude bot commented Jan 28, 2026

Claude finished @petebacondarwin's task —— View job


Changeset Review

Reviewing changeset files...

  • Read changeset guidelines
  • Review .changeset/native-worker-threads.md
  • Validate against criteria
  • Post findings

All changesets look good

The changeset .changeset/native-worker-threads.md follows all guidelines:

  1. Version Type: ✅ Minor is correct - this is a new feature
  2. Changelog Quality: ✅ Clear description with explicit note about experimental nature and required flags
  3. Markdown Headers: ✅ No h1/h2/h3 headers used
  4. Analytics: ✅ N/A - no analytics collection changes
  5. Dependabot: ✅ N/A - not a dependency update
  6. Experimental features: ✅ Includes explicit note about experimental status and required compatibility flags (nodejs_compat, experimental, and enable_nodejs_worker_threads_module)

@petebacondarwin petebacondarwin force-pushed the devin/1769080195-native-node-worker-threads branch from 95b868a to 949c436 Compare February 11, 2026 11:47
petebacondarwin added a commit to cloudflare/workerd that referenced this pull request Feb 13, 2026
… flag

The node:worker_threads module was previously importing MessageChannel and
MessagePort from globalThis, which meant it only worked when the
expose_global_message_channel compatibility flag was enabled.

This change introduces a new internal module (cloudflare-internal:messagechannel)
that exposes MessageChannel and MessagePort for use by built-in modules,
independent of the global flag.

Changes:
- Add MessageChannelModule C++ class in messagechannel.h
- Register cloudflare-internal:messagechannel as an internal module
- Update node:worker_threads to import from the internal module
- Add TypeScript type definitions for the internal module
- Remove expose_global_message_channel from worker_threads tests

This unblocks cloudflare/workers-sdk#12043 which needs worker_threads to
work without requiring the global flag.
@petebacondarwin petebacondarwin added blocked Blocked on other work unenv labels Feb 13, 2026
@petebacondarwin
Copy link
Contributor Author

Blocked on cloudflare/workerd#6069

@petebacondarwin petebacondarwin force-pushed the devin/1769080195-native-node-worker-threads branch from a5bfd5b to ce12ada Compare February 17, 2026 09:37
@petebacondarwin petebacondarwin marked this pull request as ready for review February 17, 2026 09:47
@petebacondarwin petebacondarwin requested a review from a team as a code owner February 17, 2026 09:47
devin-ai-integration[bot]

This comment was marked as resolved.

@petebacondarwin petebacondarwin removed the blocked Blocked on other work label Feb 17, 2026
@petebacondarwin
Copy link
Contributor Author

Blocked on cloudflare/workerd#6069

This landed in v1.20260214.0 and main is already up to date with this, so now unblocked.

vicb

This comment was marked as duplicate.

Copy link
Contributor

@vicb vicb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I that the thing you changed in worked recently?
So we need a peer dep bump?
Otherwise LGTM

@github-project-automation github-project-automation bot moved this from Untriaged to Approved in workers-sdk Feb 17, 2026
@petebacondarwin
Copy link
Contributor Author

I that the thing you changed in worked recently? So we need a peer dep bump? Otherwise LGTM

Oops! Good spot @vicb - I forgot that it was not enough to update workerd in general, we need to bump the peer dep. Will add that now.

@petebacondarwin
Copy link
Contributor Author

This is the change:

Make node:worker_threads independent of expose_global_message_channel flag by @petebacondarwin in cloudflare/workerd#6069

devin-ai-integration bot and others added 17 commits February 17, 2026 14:34
- Both workerd and unenv export MessageChannel, MessagePort, Worker, BroadcastChannel
- Use getRuntimeFlagValue() to check if native workerd is enabled
- Test behavioral differences (Worker/BroadcastChannel throw in native workerd)

Co-Authored-By: [email protected] <[email protected]>
- Native workerd exports MessageChannel/MessagePort as globalThis refs which may be undefined
- Split type assertions for native vs unenv stub implementations
- Only test MessageChannel in unenv stub mode

Co-Authored-By: [email protected] <[email protected]>
This actually now fails because the MessageChannel in the `node:worker_threads` module is pulled from the `global.MessageChannel` and that is only available if `expose_global_message_channel` compat flag is on...
> Make node:worker_threads independent of expose_global_message_channel flag by @petebacondarwin in cloudflare/workerd#6069
@petebacondarwin petebacondarwin force-pushed the devin/1769080195-native-node-worker-threads branch from 5d7060a to 2a78e21 Compare February 17, 2026 14:34
devin-ai-integration[bot]

This comment was marked as resolved.

> Make node:worker_threads independent of expose_global_message_channel flag by @petebacondarwin in cloudflare/workerd#6069
> Make node:worker_threads independent of expose_global_message_channel flag by @petebacondarwin in cloudflare/workerd#6069
> Make node:worker_threads independent of expose_global_message_channel flag by @petebacondarwin in cloudflare/workerd#6069
@petebacondarwin petebacondarwin merged commit 452cdc8 into main Feb 17, 2026
47 of 49 checks passed
@petebacondarwin petebacondarwin deleted the devin/1769080195-native-node-worker-threads branch February 17, 2026 17:11
@github-project-automation github-project-automation bot moved this from Approved to Done in workers-sdk Feb 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants