Skip to content

feat(unenv-preset): add support for native node:readline module#11734

Merged
petebacondarwin merged 4 commits intomainfrom
devin/1766396834-readline-native-module
Feb 18, 2026
Merged

feat(unenv-preset): add support for native node:readline module#11734
petebacondarwin merged 4 commits intomainfrom
devin/1766396834-readline-native-module

Conversation

@petebacondarwin
Copy link
Copy Markdown
Contributor

@petebacondarwin petebacondarwin commented Dec 22, 2025

Similar to #11733 (native inspector module support), this PR adds support for the native node:readline and node:readline/promises modules when the enable_nodejs_readline_module compatibility flag is enabled.

Since readline is marked as $experimental in workerd with no $impliedByAfterDate, this feature requires both the enable_nodejs_readline_module and experimental compatibility flags to be set.

Updates since last revision

  • Cleanly rebased onto latest main (no merge commits)
  • Verified getReadlineOverrides() correctly requires both enable_nodejs_readline_module AND experimental flags
  • Reinstated readline/promises in nativeModules now that workerd 1.20251223.0 includes the fix from fix promises export for readline & inspector workerd#5740
  • Added testReadlinePromises() test for the node:readline/promises module

Implementation Comparison

Implementations are at:

The three readline implementations differ as follows:

Node.js (full implementation): Complete readline support with terminal handling, line editing, history, tab completion, and the Interface class for interactive input.

workerd (non-functional stub): Exports the expected API surface (Interface, clearLine, clearScreenDown, createInterface, cursorTo, emitKeypressEvents, moveCursor, promises). Basic functions like clearLine(), cursorTo(), moveCursor() return false. The Interface constructor throws ERR_METHOD_NOT_IMPLEMENTED.

unenv (polyfill stub): Similar API surface to workerd. Basic functions return false or are no-ops. The Interface class is a no-op stub that doesn't throw - methods like question() immediately call the callback with an empty string.

Potential Breaking Changes

Code that relies on unenv's silent no-op behavior will break when switching to the native module, as workerd throws ERR_METHOD_NOT_IMPLEMENTED for many APIs.

node:readline

API workerd unenv
createInterface() throws (creates Interface) returns stub
Interface constructor throws no-op
Interface.getPrompt() throws returns ""
Interface.question() throws calls callback with ""
Interface.close() throws no-op

node:readline/promises

API workerd unenv
createInterface() throws (creates Interface) returns stub
Interface constructor throws no-op
Interface.question() throws returns Promise.resolve("")
Readline constructor throws no-op
Readline.commit() throws no-op

Human Review Checklist

  • Verify getReadlineOverrides() correctly requires both enable_nodejs_readline_module AND experimental flags
  • Verify tests include experimental flag in compatibility flags
  • Verify testReadline() assertions include promises: "object" to confirm promises API is accessible
  • Verify testReadlinePromises() assertions match workerd's readline/promises exports
  • Confirm breaking change tables accurately reflect workerd vs unenv behavior
  • Confirm workerd 1.20251223.0 includes readline/promises support (from workerd#5740)
  • Determine if breaking changes need mitigation beyond documentation (given experimental flag gating)

Devin PR requested by @petebacondarwin
Link to Devin run: https://app.devin.ai/sessions/3dd68b14916446e09725083926e3408d


  • Tests
    • Tests included/updated
    • Tests not necessary because:
  • Public documentation
    • Cloudflare docs PR(s):
    • Documentation not necessary because: readline is already documented as partially supported in the Workers docs
  • Wrangler V3 Backport
    • Wrangler PR:
    • Not necessary because: This is a new experimental feature in unenv-preset, not a bug fix requiring backport

@devin-ai-integration
Copy link
Copy Markdown
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. Add '(aside)' to your comment to have me ignore it.
  • 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
Copy Markdown

changeset-bot bot commented Dec 22, 2025

🦋 Changeset detected

Latest commit: aa0af81

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

@claude
Copy link
Copy Markdown
Contributor

claude bot commented Dec 22, 2025

Claude finished @petebacondarwin's task —— View job


Changeset Review

Reviewing the changeset file for this PR...

Todo List:

  • Read changeset guidelines from .changeset/README.md
  • Read the changeset file .changeset/native-readline-module.md
  • Validate version type
  • Validate changelog quality
  • Check for markdown headers (h1/h2/h3)
  • Check analytics consideration
  • Check experimental feature note
  • Report findings

All changesets look good

The changeset properly:

  • Uses minor version type (appropriate for a new feature)
  • Provides a clear description of what's being added
  • Avoids problematic markdown headers
  • Includes explicit note about experimental feature requirements (both enable_nodejs_readline_module and experimental flags)

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Dec 22, 2025

create-cloudflare

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

@cloudflare/kv-asset-handler

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

miniflare

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

@cloudflare/pages-shared

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

@cloudflare/unenv-preset

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

@cloudflare/vite-plugin

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

@cloudflare/vitest-pool-workers

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

@cloudflare/workers-editor-shared

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

@cloudflare/workers-utils

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

wrangler

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

commit: aa0af81

@devin-ai-integration devin-ai-integration bot force-pushed the devin/1766396834-readline-native-module branch from 8167373 to 735fa35 Compare December 22, 2025 14:09
@petebacondarwin
Copy link
Copy Markdown
Contributor Author

The promises aspect of this is blocked on cloudflare/workerd#5740

@devin-ai-integration
Copy link
Copy Markdown
Contributor

Thanks for confirming! I've updated the PR to remove readline/promises from nativeModules since workerd doesn't currently bundle it as a separate module. The promises API is still accessible via readline.promises on the main module, which is tested in testReadline().

Once cloudflare/workerd#5740 lands and a new workerd version is released, we can add readline/promises back to nativeModules and add the testReadlinePromises() test.

@petebacondarwin
Copy link
Copy Markdown
Contributor Author

The fix in workerd has been released at version v1.20251223.0. Please rebase on main, reinstate the promises entry point stuff and bump the peer dependency of workerd in the unenv-preset to 1.20251223.0.

@devin-ai-integration devin-ai-integration bot force-pushed the devin/1766396834-readline-native-module branch from 6508943 to 989c5d2 Compare December 23, 2025 09:07
@petebacondarwin petebacondarwin marked this pull request as ready for review December 23, 2025 10:44
@petebacondarwin petebacondarwin requested a review from a team as a code owner December 23, 2025 10:44
@petebacondarwin
Copy link
Copy Markdown
Contributor Author

Urgh looks like there is another potential breaking change to mitigate...

@devin-ai-integration
Copy link
Copy Markdown
Contributor

Could you clarify which breaking change you're referring to? Is it related to createInterface() / promises.createInterface() throwing (since they create an Interface internally), or something else in the readline/promises module?

I can update the PR description's breaking change table to include any additional APIs that throw in workerd but are no-ops in unenv.

@devin-ai-integration
Copy link
Copy Markdown
Contributor

I've updated the PR description with a more comprehensive breaking change table covering both node:readline and node:readline/promises. The key breaking changes are:

  • createInterface() throws in workerd (because it creates an Interface internally) but returns a stub in unenv
  • Interface and Readline constructors throw in workerd but are no-ops in unenv
  • Various methods like question(), close(), commit() throw in workerd but return empty values in unenv

Since this is gated behind both enable_nodejs_readline_module AND experimental flags, users have to explicitly opt-in. Let me know if you want any additional mitigation beyond documenting these differences (e.g., keeping certain entry points on unenv/hybrid until workerd behavior aligns better).

@petebacondarwin petebacondarwin added blocked Blocked on other work nodejs compat Relating to the node runtime compatibility flag labels Dec 23, 2025
@petebacondarwin
Copy link
Copy Markdown
Contributor Author

Please rebase and fix conflicts.

@devin-ai-integration devin-ai-integration bot force-pushed the devin/1766396834-readline-native-module branch 2 times, most recently from 1f27c3b to 6288cd0 Compare January 21, 2026 16:18
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 3 additional flags.

Open in Devin Review

petebacondarwin added a commit to cloudflare/workerd that referenced this pull request Feb 4, 2026
Change the readline Interface class and the readline/promises Interface
and Readline classes to be no-op stubs instead of throwing errors.

This matches the behavior of unenv's readline implementation, which allows
code that depends on readline to work without crashing even though the
functionality is not fully implemented.

Methods now return sensible defaults (empty strings, zero values, etc.)
instead of throwing ERR_METHOD_NOT_IMPLEMENTED errors.

Fixes compatibility with cloudflare/workers-sdk#11734
@petebacondarwin petebacondarwin force-pushed the devin/1766396834-readline-native-module branch 4 times, most recently from dead525 to 7cb7b54 Compare February 13, 2026 16:13
petebacondarwin added a commit to cloudflare/workerd that referenced this pull request Feb 17, 2026
Change the readline Interface class and the readline/promises Interface
and Readline classes to be no-op stubs instead of throwing errors.

This matches the behavior of unenv's readline implementation, which allows
code that depends on readline to work without crashing even though the
functionality is not fully implemented.

Methods now return sensible defaults (empty strings, zero values, etc.)
instead of throwing ERR_METHOD_NOT_IMPLEMENTED errors.

Fixes compatibility with cloudflare/workers-sdk#11734
@petebacondarwin
Copy link
Copy Markdown
Contributor Author

Blocked on cloudflare/workerd#6016

devin-ai-integration bot and others added 2 commits February 18, 2026 08:27
Co-Authored-By: pbacondarwin@cloudflare.com <pete@bacondarwin.com>
@petebacondarwin petebacondarwin force-pushed the devin/1766396834-readline-native-module branch from 7cb7b54 to 10d1d2f Compare February 18, 2026 08:33
"peerDependencies": {
"unenv": "2.0.0-rc.24",
"workerd": "^1.20260214.0"
"workerd": "^1.20260218.0"
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This bump is required to include the fix to the Interface class in workerd: cloudflare/workerd#6016

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

Blocked on cloudflare/workerd#6016

Now merged and released. Unblocking this PR

@petebacondarwin petebacondarwin requested a review from vicb February 18, 2026 11:15
@github-project-automation github-project-automation bot moved this from Untriaged to Approved in workers-sdk Feb 18, 2026
@petebacondarwin petebacondarwin merged commit 5f9f0b4 into main Feb 18, 2026
35 checks passed
@petebacondarwin petebacondarwin deleted the devin/1766396834-readline-native-module branch February 18, 2026 12:06
@github-project-automation github-project-automation bot moved this from Approved to Done in workers-sdk Feb 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

nodejs compat Relating to the node runtime compatibility flag unenv

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants