loader: add experimental text import#62300
Conversation
|
Review requested:
|
|
Note that the import-bytes proposal requires producing Uint8Arrays backed by immutable ArrayBuffers, which are not yet supported in V8. I would be hesitant to ship this with mutable backing buffers, even flagged as experimental, lest people come to rely on that. Text imports don't have the same problem. |
That's a great point, looks like I've missed that. I've removed |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #62300 +/- ##
=======================================
Coverage 89.63% 89.63%
=======================================
Files 708 708
Lines 220402 220447 +45
Branches 42271 42293 +22
=======================================
+ Hits 197551 197598 +47
+ Misses 14706 14701 -5
- Partials 8145 8148 +3
🚀 New features to boost your workflow:
|
This is really good knowledge that would be good to preserve somewhere. Maybe add a comment near the most appropriate spot in the new code, such as where the |
pdeveltere
left a comment
There was a problem hiding this comment.
in loader.js, you can add:
/**
* @typedef {'builtin'|'commonjs'|'json'|'module'|'text'|'wasm'} ModuleFormat
*/
Yeah makes sense, I've added a comment right below |
| await assert.rejects( | ||
| import('../fixtures/file-to-read-without-bom.txt'), | ||
| { code: 'ERR_UNKNOWN_FILE_EXTENSION' }, | ||
| ); |
There was a problem hiding this comment.
Please add a test for what happens when you try to import a binary data file such as an image.png or mod.wasm.
I encourage Node.js to take a strict view here. The following code should throw an exception
import text from "image.png" with { type: "text" };There was a problem hiding this comment.
Hmm, I'm not so sure. I would just allow any file to be read as text. You never know it might have a use case. And implementing a list of potential extensions which don't make sense could be a never ending process?
There was a problem hiding this comment.
I'm really not sure why it should - if there's a text representation of a file, it should give it. If it's nonsense, that's the developer's problem to solve.
There was a problem hiding this comment.
Hmm, I'm not so sure. I would just allow any file to be read as text. You never know it might have a use case.
Replacement characters render the text form of a non-text file unusable and unrecoverable, so it's hard to think of a use case.
And implementing a list of potential extensions which don't make sense could be a never ending process?
I don't suggest filtering by extension. I suggest throwing an exception if any non-text byte is encountered when reading the file.
There was a problem hiding this comment.
Which bytes are always, universally, non-text?
There was a problem hiding this comment.
but valid javascript strings can have lone surrogates, so i'm a bit confused why we'd want to do either one - meaning, throwing kills use cases, and silently substituting results in artificially well-formed utf8?
There was a problem hiding this comment.
When reading files, it's always necessary to push them through a text decoder, except the unusual case where the file is stored on disk as UTF-16. There is no such thing as lone surrogates in UTF-8.
There was a problem hiding this comment.
I'm a bit unsure about throwing here. Neither Deno nor Bun throw on invalid UTF-8 in this case, so I'm leaning toward keeping Node aligned.
Of course, I'm open to being challenged if there's a strong reason.
There was a problem hiding this comment.
Do Deno and Bun ship this feature? It is not a standard feature yet; it is moving through committee. Node should do what's right, not what implementations of a non-standard feature have done.
There was a problem hiding this comment.
It's unflagged in Bun since April 2024, and flagged in Deno since June 2025.
That doesn't necessarily mean anyone's depending on being able to import invalid UTF-8 with replacement characters instead of an error, though.
|
Does this actually need to be behind an experimental flag? The proposal is stage 3, and pretty simple. |
I agree. We don't have to use experimental for anything, especially since it will require additional burden about promoting to stable at some point. Since the feature is low risk and unlikely to change in the future (which I how I envision "experimental" is meant to use), I would directly insert as stable. |
|
I think this should be introduced as experimental. I can’t think of any modules features we’ve introduced directly as stable. Modules features have compatibility concerns with other runtimes; we want to see how import-type-text behaves in Deno and Bun and browsers before we promote our version to stable. There’s also the issue that as soon as our version is stable, people start relying on it in published public npm packages; we want to make sure we have ours fully correct before that happens. |
I'm honestly fine with this as well. |
Marking this as experimental is one thing, but gating it behind a flag is another. Couldn't you just mark it as experimental but not gate it? Afaik, not all Node.js experimental features are behind a flag, and a flag doesn't encourage the community to test this feature and share feedback.
If an npm package adopts this and you have to change the semantics, that can be considered a bug fix, not a breaking change, considering there's a public/std spec you need to conform to. If there are gaps in the spec that lead different implementations to behave differently, that's another problem 😅 |
|
I initially put it behind a flag because this PR was implementing both |
Please introduce this behind a flag and cite it in the docs as experimental status 1.0 - Early development. This is how all modules features are introduced. |
Fair enough. Thanks for taking time and elaborating on your initial comments! I took some time to better understand the flow and I see your point. Would appreciate another review I'll address the rest of the comments later |
|
BTW for those of you asking about experimental statuses and flags, you can look in the GitHub history and you'll find the PRs related to the original implementation of import assertions, which was Stage 3 at the time for a syntax |
41af9be to
d04ff90
Compare
I've added the docs for the flag 👍 |
|
There's a conflict, can you please rebase the PR?
I could be wrong but I don't see what change V8 could do related to that, it already supports the |
|
oh yeah aduh95 had right that nodejs code that handle loading of json module. But https://github.com/tc39/proposal-source-phase-imports will need v8 thing
|
|
Yes, this is similar to how json is handled on our end. I've resolved the conflict |
Signed-off-by: Efe Karasakal <hi@efe.dev>
36dc64d to
3d1a260
Compare
https://issues.chromium.org/issues/494350643 ☝️ The "parent", which links to PRs etc The V8-specific PR that would bring this to node is https://chromium-review.googlesource.com/c/v8/v8/+/7844854 |
Unless I'm missing something, that's just the implementation in the d8 shell? I don't think that will affect node at all. I think this is something embedders have to do on their own, same as for json despite that also being implemented in d8. The actual implementation of text imports in Chrome is in this CL. |
|
Landed in 54296cb |
|
Oh. That's unexpected. In that case, nevermind—carry on. |
Add missing `--experimental-import-text` option to `doc/node.1`. Signed-off-by: Richard Lau <richard.lau@ibm.com> PR-URL: #64156 Refs: #62300 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Chengzhong Wu <legendecas@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Signed-off-by: Efe Karasakal <hi@efe.dev> PR-URL: #62300 Reviewed-By: Aviv Keller <me@aviv.sh> Reviewed-By: Ilyas Shabi <ilyasshabi94@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Add missing `--experimental-import-text` option to `doc/node.1`. Signed-off-by: Richard Lau <richard.lau@ibm.com> PR-URL: #64156 Refs: #62300 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Chengzhong Wu <legendecas@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Notable changes: buffer: * (SEMVER-MINOR) implement blob.textStream() (Matthew Aitken) #64036 esm: * (SEMVER-MINOR) add `--experimental-import-text` flag (Efe) #62300 perf_hooks: * (SEMVER-MINOR) sample delay per event loop iteration (Pablo Erhard) #62935 stream: * (SEMVER-MINOR) expose ReadableStreamTee (Matteo Collina) #64195 tls: * (SEMVER-MINOR) report negotiated TLS groups (Filip Skokan) #64119 PR-URL: #64329
Notable changes: buffer: * (SEMVER-MINOR) implement blob.textStream() (Matthew Aitken) #64036 esm: * (SEMVER-MINOR) add `--experimental-import-text` flag (Efe) #62300 perf_hooks: * (SEMVER-MINOR) sample delay per event loop iteration (Pablo Erhard) #62935 stream: * (SEMVER-MINOR) expose ReadableStreamTee (Matteo Collina) #64195 tls: * (SEMVER-MINOR) report negotiated TLS groups (Filip Skokan) #64119 PR-URL: #64329 Signed-off-by: Richard Lau <richard.lau@ibm.com>
Notable changes: buffer: * (SEMVER-MINOR) implement blob.textStream() (Matthew Aitken) #64036 esm: * (SEMVER-MINOR) add `--experimental-import-text` flag (Efe) #62300 perf_hooks: * (SEMVER-MINOR) sample delay per event loop iteration (Pablo Erhard) #62935 stream: * (SEMVER-MINOR) expose ReadableStreamTee (Matteo Collina) #64195 tls: * (SEMVER-MINOR) report negotiated TLS groups (Filip Skokan) #64119 PR-URL: #64329 Signed-off-by: Richard Lau <richard.lau@ibm.com>
Signed-off-by: Efe Karasakal <hi@efe.dev> PR-URL: #62300 Reviewed-By: Aviv Keller <me@aviv.sh> Reviewed-By: Ilyas Shabi <ilyasshabi94@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Add missing `--experimental-import-text` option to `doc/node.1`. Signed-off-by: Richard Lau <richard.lau@ibm.com> PR-URL: #64156 Refs: #62300 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Chengzhong Wu <legendecas@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
This MR contains the following updates: | Package | Update | Change | |---|---|---| | [node](https://nodejs.org) ([source](https://github.com/nodejs/node)) | minor | `26.3.1` → `26.5.0` | MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot). **Proposed changes to behavior should be submitted there as MRs.** --- ### Release Notes <details> <summary>nodejs/node (node)</summary> ### [`v26.5.0`](https://github.com/nodejs/node/releases/tag/v26.5.0): 2026-07-08, Version 26.5.0 (Current), @​richardlau [Compare Source](nodejs/node@v26.3.1...v26.5.0) ##### Notable Changes ##### New release key Welcome to our newest releaser, [Stewart X Addison](https://github.com/sxa). Future Node.js releases may be signed with his [release key](https://github.com/nodejs/node/blob/main/README.md#release-keys), `655F3B5C1FB3FA8D1A0CA6BDE4A7D232B936D2FD`. ##### Other notable changes - \[[`55f48446c7`](nodejs/node@55f48446c7)] - **(SEMVER-MINOR)** **buffer**: implement blob.textStream() (Matthew Aitken) [#​64036](nodejs/node#64036) - \[[`b373202efc`](nodejs/node@b373202efc)] - **(SEMVER-MINOR)** **esm**: add `--experimental-import-text` flag (Efe) [#​62300](nodejs/node#62300) - \[[`39e0c14455`](nodejs/node@39e0c14455)] - **(SEMVER-MINOR)** **perf\_hooks**: sample delay per event loop iteration (Pablo Erhard) [#​62935](nodejs/node#62935) - \[[`999a83c937`](nodejs/node@999a83c937)] - **(SEMVER-MINOR)** **stream**: expose ReadableStreamTee (Matteo Collina) [#​64195](nodejs/node#64195) - \[[`4e0236dc3d`](nodejs/node@4e0236dc3d)] - **(SEMVER-MINOR)** **tls**: report negotiated TLS groups (Filip Skokan) [#​64119](nodejs/node#64119) ##### Commits - \[[`87648c0a6c`](nodejs/node@87648c0a6c)] - **benchmark**: trim down the argon2 sets (Filip Skokan) [#​64218](nodejs/node#64218) - \[[`a483bfd3f0`](nodejs/node@a483bfd3f0)] - **buffer**: remove unreachable overflow check in atob (haramjeong) [#​60161](nodejs/node#60161) - \[[`6d14279688`](nodejs/node@6d14279688)] - **buffer**: add fast api for isUtf8 and isAscii (Gürgün Dayıoğlu) [#​64169](nodejs/node#64169) - \[[`55f48446c7`](nodejs/node@55f48446c7)] - **(SEMVER-MINOR)** **buffer**: implement blob.textStream() (Matthew Aitken) [#​64036](nodejs/node#64036) - \[[`a67d9a7a44`](nodejs/node@a67d9a7a44)] - **build**: allow linting node.1 (Aviv Keller) [#​64157](nodejs/node#64157) - \[[`06c1fbc25b`](nodejs/node@06c1fbc25b)] - **build**: enable Maglev for riscv64 (Jamie Magee) [#​62605](nodejs/node#62605) - \[[`518309c363`](nodejs/node@518309c363)] - **build**: suppress clang errors building libffi on Windows (René) [#​64222](nodejs/node#64222) - \[[`6a80ab485c`](nodejs/node@6a80ab485c)] - **build**: add manually-dispatched stress-test workflow (Joyee Cheung) [#​64118](nodejs/node#64118) - \[[`f4e7bf1f1c`](nodejs/node@f4e7bf1f1c)] - **build**: pin envinfo versions in github actions (Joyee Cheung) [#​64117](nodejs/node#64117) - \[[`66f6ac0d86`](nodejs/node@66f6ac0d86)] - **build**: support setting an emulator from configure script (Ivan Trubach) [#​53899](nodejs/node#53899) - \[[`7f26c54aa6`](nodejs/node@7f26c54aa6)] - **child\_process**: fix permission model propagation via NODE\_OPTIONS (Matteo Collina) [#​63972](nodejs/node#63972) - \[[`32bb554f5b`](nodejs/node@32bb554f5b)] - **crypto**: fix large DH generator validation (Tobias Nießen) [#​64092](nodejs/node#64092) - \[[`0908d76ef6`](nodejs/node@0908d76ef6)] - **crypto**: reject small-order EdDSA points during verify (Filip Skokan) [#​64026](nodejs/node#64026) - \[[`7f7e5863c2`](nodejs/node@7f7e5863c2)] - **deps**: update undici to 8.7.0 (Node.js GitHub Bot) [#​64282](nodejs/node#64282) - \[[`af91029801`](nodejs/node@af91029801)] - **deps**: update nghttp3 to 1.17.0 (Node.js GitHub Bot) [#​64182](nodejs/node#64182) - \[[`2e500ba7b0`](nodejs/node@2e500ba7b0)] - **deps**: update googletest to [`8b53336`](nodejs/node@8b53336) (Node.js GitHub Bot) [#​64181](nodejs/node#64181) - \[[`74e3aa24ba`](nodejs/node@74e3aa24ba)] - **deps**: update sqlite to 3.53.3 (Node.js GitHub Bot) [#​64180](nodejs/node#64180) - \[[`c7e57f55a7`](nodejs/node@c7e57f55a7)] - **deps**: c-ares: cherry-pick [`8ba37af`](nodejs/node@8ba37af8e3fb) (René) [#​64110](nodejs/node#64110) - \[[`879fdc4daf`](nodejs/node@879fdc4daf)] - **deps**: V8: backport [`da20a19`](nodejs/node@da20a197a7f9) (Kevin Gibbons) [#​64101](nodejs/node#64101) - \[[`a640543a7c`](nodejs/node@a640543a7c)] - **deps**: V8: cherry-pick [`0cc9eb2`](nodejs/node@0cc9eb22c0b0) (Kevin Gibbons) [#​64101](nodejs/node#64101) - \[[`feefd179e5`](nodejs/node@feefd179e5)] - **deps**: V8: cherry-pick [`1a391f9`](nodejs/node@1a391f98cc7a) (Kevin Gibbons) [#​64101](nodejs/node#64101) - \[[`8ef643d4b0`](nodejs/node@8ef643d4b0)] - **deps**: update googletest to [`0b1e895`](nodejs/node@0b1e895) (Node.js GitHub Bot) [#​64039](nodejs/node#64039) - \[[`9e50bb0655`](nodejs/node@9e50bb0655)] - **dgram**: skip dns.lookup() for literal IP addresses (Ruben Bridgewater) [#​64133](nodejs/node#64133) - \[[`dc052c095c`](nodejs/node@dc052c095c)] - **diagnostics\_channel**: return original thenable (Stephen Belanger) [#​62407](nodejs/node#62407) - \[[`a22a840293`](nodejs/node@a22a840293)] - **doc**: clarify QUIC stream state wording (EduardF1) [#​63660](nodejs/node#63660) - \[[`8d4bec2d71`](nodejs/node@8d4bec2d71)] - **doc**: update Http2SecureServer.on("timeout") default value (YuSheng Chen) [#​64187](nodejs/node#64187) - \[[`da88f70afa`](nodejs/node@da88f70afa)] - **doc**: add note on visibility of CI failures to new contributor guide (Stewart X Addison) [#​64256](nodejs/node#64256) - \[[`20ce359ccb`](nodejs/node@20ce359ccb)] - **doc**: clarify HTTP/1.1 response ordering (Matteo Collina) [#​64213](nodejs/node#64213) - \[[`05eae2835c`](nodejs/node@05eae2835c)] - **doc**: recommend node-stress-single-test for flaky tests (Trivikram Kamat) [#​64223](nodejs/node#64223) - \[[`3966eb67e7`](nodejs/node@3966eb67e7)] - **doc**: fix typo in examples (Vas Sudanagunta) [#​64184](nodejs/node#64184) - \[[`12a2b9daa3`](nodejs/node@12a2b9daa3)] - **doc**: fix typo in node-config-schema.json (Hamid Reza Ghavami) [#​64188](nodejs/node#64188) - \[[`0854482671`](nodejs/node@0854482671)] - **doc**: clarify defense-in-depth issues (Matteo Collina) [#​64215](nodejs/node#64215) - \[[`ef4915fc3a`](nodejs/node@ef4915fc3a)] - **doc**: fix Fast FFI argument count in ffi.md (Daijiro Wachi) [#​63960](nodejs/node#63960) - \[[`bb2eed863c`](nodejs/node@bb2eed863c)] - **doc**: add sxa GPG key ([`ed25519`](nodejs/node@ed25519)) (Stewart X Addison) [#​64193](nodejs/node#64193) - \[[`b7bf6e3a06`](nodejs/node@b7bf6e3a06)] - **doc**: add guide and answers to FAQs for first-time contributors (Joyee Cheung) [#​63685](nodejs/node#63685) - \[[`ff537ba858`](nodejs/node@ff537ba858)] - **doc**: update `Http2Server.close` & `Http2SecureServer.close` (YuSheng Chen) [#​63298](nodejs/node#63298) - \[[`f3db304588`](nodejs/node@f3db304588)] - **doc**: update list of people in `SECURITY.md` (Richard Lau) [#​64152](nodejs/node#64152) - \[[`2a126647b0`](nodejs/node@2a126647b0)] - **doc**: clarify vfs is not a sandbox (Matteo Collina) [#​64143](nodejs/node#64143) - \[[`85fc79dd9b`](nodejs/node@85fc79dd9b)] - **doc**: fix broken links and duplicate stability label (Antoine du Hamel) [#​64130](nodejs/node#64130) - \[[`189e830eb3`](nodejs/node@189e830eb3)] - **doc**: add missing option to man page (Richard Lau) [#​64156](nodejs/node#64156) - \[[`7a16ccccd0`](nodejs/node@7a16ccccd0)] - **doc**: announce upcoming end of tier 2 support for macOS x64 (Antoine du Hamel) [#​63931](nodejs/node#63931) - \[[`d5f826045f`](nodejs/node@d5f826045f)] - **doc**: update toolchain for official AIX releases (Richard Lau) [#​64068](nodejs/node#64068) - \[[`60abc4400f`](nodejs/node@60abc4400f)] - **doc**: fix callback example import in fs docs (Kamal Rawal) [#​63912](nodejs/node#63912) - \[[`e470c74a6c`](nodejs/node@e470c74a6c)] - **doc**: fix keepAliveTimeout default in http.createServer options (Jahanzaib iqbal) [#​63974](nodejs/node#63974) - \[[`851b460583`](nodejs/node@851b460583)] - **esm**: improve ERR\_REQUIRE\_ASYNC\_MODULE (Joyee Cheung) [#​64260](nodejs/node#64260) - \[[`0cd443df39`](nodejs/node@0cd443df39)] - **esm**: print required top-level await locations without evaluating (Joyee Cheung) [#​64154](nodejs/node#64154) - \[[`b373202efc`](nodejs/node@b373202efc)] - **(SEMVER-MINOR)** **esm**: add `--experimental-import-text` flag (Efe) [#​62300](nodejs/node#62300) - \[[`eacfbd0ca5`](nodejs/node@eacfbd0ca5)] - **http**: add CONNECT method handling for default Host header with proxy (Archkon) [#​64114](nodejs/node#64114) - \[[`aeb539a383`](nodejs/node@aeb539a383)] - **http**: fix drain event with cork/uncork (David Evans) [#​64038](nodejs/node#64038) - \[[`8e8874b216`](nodejs/node@8e8874b216)] - **http**: document and validate options.path when it's in absolute-form (Joyee Cheung) [#​64108](nodejs/node#64108) - \[[`eb2e96bc28`](nodejs/node@eb2e96bc28)] - **inspector**: fix crash when writing to closed inspector socket (ympark2011) [#​64209](nodejs/node#64209) - \[[`243b0e4e57`](nodejs/node@243b0e4e57)] - **lib**: reject string "0" in validatePort when allowZero is false (Daijiro Wachi) [#​64174](nodejs/node#64174) - \[[`34a537c0ed`](nodejs/node@34a537c0ed)] - **lib**: use `__proto__: null` when calling `ObjectDefineProperty` (Antoine du Hamel) [#​64239](nodejs/node#64239) - \[[`1f72393f19`](nodejs/node@1f72393f19)] - **lib**: lazily initialize kEvents and kHandlers maps (Guilherme Araújo) [#​63702](nodejs/node#63702) - \[[`92a3dc3191`](nodejs/node@92a3dc3191)] - **lib,permission**: fix addon permission drop (Martin Wagner) [#​64007](nodejs/node#64007) - \[[`87b8f2a296`](nodejs/node@87b8f2a296)] - **meta**: fix linter warning in `stale.yml` (Antoine du Hamel) [#​64281](nodejs/node#64281) - \[[`829c4a5913`](nodejs/node@829c4a5913)] - **meta**: bump actions/cache from 5.0.5 to 6.1.0 (dependabot\[bot]) [#​64248](nodejs/node#64248) - \[[`0808dcd31c`](nodejs/node@0808dcd31c)] - **meta**: bump github/codeql-action/autobuild from 4.36.1 to 4.36.2 (dependabot\[bot]) [#​64247](nodejs/node#64247) - \[[`64aa17058f`](nodejs/node@64aa17058f)] - **meta**: bump github/codeql-action/analyze from 4.36.1 to 4.36.2 (dependabot\[bot]) [#​64246](nodejs/node#64246) - \[[`873d1e0412`](nodejs/node@873d1e0412)] - **meta**: bump actions/checkout from 6.0.2 to 7.0.0 (dependabot\[bot]) [#​64245](nodejs/node#64245) - \[[`fe460ccf0b`](nodejs/node@fe460ccf0b)] - **meta**: bump codecov/codecov-action from 6.0.1 to 7.0.0 (dependabot\[bot]) [#​64244](nodejs/node#64244) - \[[`845c63ed50`](nodejs/node@845c63ed50)] - **meta**: bump rtCamp/action-slack-notify from 2.3.3 to 2.4.0 (dependabot\[bot]) [#​64243](nodejs/node#64243) - \[[`2cad2d6de5`](nodejs/node@2cad2d6de5)] - **meta**: bump github/codeql-action/init from 4.36.1 to 4.36.2 (dependabot\[bot]) [#​64242](nodejs/node#64242) - \[[`0ddde950c7`](nodejs/node@0ddde950c7)] - **meta**: bump actions/setup-python from 6.2.0 to 6.3.0 (dependabot\[bot]) [#​64241](nodejs/node#64241) - \[[`c0a8760d2f`](nodejs/node@c0a8760d2f)] - **meta**: bump github/codeql-action/upload-sarif from 4.36.1 to 4.36.2 (dependabot\[bot]) [#​64240](nodejs/node#64240) - \[[`f49704b9d0`](nodejs/node@f49704b9d0)] - **meta**: clarify V8 flags are outside threat model (Matteo Collina) [#​64224](nodejs/node#64224) - \[[`6b8dc58e6e`](nodejs/node@6b8dc58e6e)] - **meta**: move one or more collaborators to emeritus (Node.js GitHub Bot) [#​64057](nodejs/node#64057) - \[[`fe5260cca7`](nodejs/node@fe5260cca7)] - **meta**: update status of past strategic initiatives (Joyee Cheung) [#​63480](nodejs/node#63480) - \[[`7b01040008`](nodejs/node@7b01040008)] - **meta**: speed up stale bot (Aviv Keller) [#​64075](nodejs/node#64075) - \[[`874c46c24f`](nodejs/node@874c46c24f)] - **meta**: update sccache version in test-linux-quic (René) [#​64043](nodejs/node#64043) - \[[`48c5c86363`](nodejs/node@48c5c86363)] - **module**: enable import support for addons by default (Chengzhong Wu) [#​64221](nodejs/node#64221) - \[[`39e0c14455`](nodejs/node@39e0c14455)] - **(SEMVER-MINOR)** **perf\_hooks**: sample delay per event loop iteration (Pablo Erhard) [#​62935](nodejs/node#62935) - \[[`f90f1bd032`](nodejs/node@f90f1bd032)] - **perf\_hooks**: add NODE\_PERFORMANCE\_GC\_MINOR\_MARK\_SWEEP constant (Attila Szegedi) [#​63877](nodejs/node#63877) - \[[`bdf32628c7`](nodejs/node@bdf32628c7)] - **process**: fix finalization cleanup ref tracking (Trivikram Kamat) [#​64087](nodejs/node#64087) - \[[`9a65b7fff4`](nodejs/node@9a65b7fff4)] - **quic**: drop version negotiation packets with oversized CIDs (Mohamed Sayed) [#​64228](nodejs/node#64228) - \[[`2699fe4706`](nodejs/node@2699fe4706)] - **quic**: fixes undefined handle in QuicStream kInspect (Marten Richter) [#​64170](nodejs/node#64170) - \[[`00dea28bb3`](nodejs/node@00dea28bb3)] - **repl**: lazy-load acorn and defer vm context creation (Daijiro Wachi) [#​63879](nodejs/node#63879) - \[[`ce659a1cf9`](nodejs/node@ce659a1cf9)] - **src**: fix escaping of single quotes in task runner (Antoine du Hamel) [#​64089](nodejs/node#64089) - \[[`dbb3126e5c`](nodejs/node@dbb3126e5c)] - **src**: abstract tracing agent for both legacy and perfetto (Chengzhong Wu) [#​64053](nodejs/node#64053) - \[[`12edf1d68d`](nodejs/node@12edf1d68d)] - **src**: avoid redundant call to `std::get_if<>()` (Tobias Nießen) [#​64094](nodejs/node#64094) - \[[`eda91b6d01`](nodejs/node@eda91b6d01)] - **src**: avoid copying source string in TextEncoder.encode (Yagiz Nizipli) [#​63897](nodejs/node#63897) - \[[`efbbb9a03c`](nodejs/node@efbbb9a03c)] - **stream**: preserve half-open duplexes in async iteration (Efe) [#​64275](nodejs/node#64275) - \[[`999a83c937`](nodejs/node@999a83c937)] - **(SEMVER-MINOR)** **stream**: expose ReadableStreamTee (Matteo Collina) [#​64195](nodejs/node#64195) - \[[`ab5ed72903`](nodejs/node@ab5ed72903)] - **stream**: reject iter consumers on abort (Trivikram Kamat) [#​64066](nodejs/node#64066) - \[[`d3fa77c5e2`](nodejs/node@d3fa77c5e2)] - **stream**: fix merge abort for pending sources (Trivikram Kamat) [#​64013](nodejs/node#64013) - \[[`38b99140ed`](nodejs/node@38b99140ed)] - **stream**: refactor unnecessary optional chaining away (Antoine du Hamel) [#​64253](nodejs/node#64253) - \[[`c81f894ebe`](nodejs/node@c81f894ebe)] - **stream**: cut per-chunk overhead in WHATWG streams (Matteo Collina) [#​64252](nodejs/node#64252) - \[[`f162234f24`](nodejs/node@f162234f24)] - **stream**: normalize Broadcast.from() byte inputs (Trivikram Kamat) [#​64082](nodejs/node#64082) - \[[`1182ad8f3b`](nodejs/node@1182ad8f3b)] - **stream**: proxy first own method in Readable.wrap() (Daijiro Wachi) [#​64048](nodejs/node#64048) - \[[`d0b830b382`](nodejs/node@d0b830b382)] - **stream**: observe abort while awaiting pipeTo source (Trivikram Kamat) [#​64015](nodejs/node#64015) - \[[`f7adcd8359`](nodejs/node@f7adcd8359)] - **stream**: respect iter consumer abort signals (Trivikram Kamat) [#​63997](nodejs/node#63997) - \[[`b09e624c6f`](nodejs/node@b09e624c6f)] - **test**: make blob desiredSize assertion robust (Trivikram Kamat) [#​64106](nodejs/node#64106) - \[[`d0d8f0c774`](nodejs/node@d0d8f0c774)] - **test**: update WPT for urlpattern to [`11a459a`](nodejs/node@11a459a2b1) (Node.js GitHub Bot) [#​64037](nodejs/node#64037) - \[[`ff9122c20c`](nodejs/node@ff9122c20c)] - **test**: improve lcov reporter snapshot diagnostics (Trivikram Kamat) [#​64049](nodejs/node#64049) - \[[`570952d4f3`](nodejs/node@570952d4f3)] - **test**: keep finalization close fixture ref alive (Trivikram Kamat) [#​64085](nodejs/node#64085) - \[[`1b4f213380`](nodejs/node@1b4f213380)] - **test**: fix typo from overriden to overridden (parkhojeong) [#​63403](nodejs/node#63403) - \[[`4c91090b8b`](nodejs/node@4c91090b8b)] - **test**: fix typo from funciton to function (parkhojeong) [#​63403](nodejs/node#63403) - \[[`bf080c7917`](nodejs/node@bf080c7917)] - **test**: mark hr-time WPT flaky on macos15-x64 (Trivikram Kamat) [#​64054](nodejs/node#64054) - \[[`24e32098c5`](nodejs/node@24e32098c5)] - **test**: use one-off agent in http consumed timeout test (Trivikram Kamat) [#​64052](nodejs/node#64052) - \[[`3229886de2`](nodejs/node@3229886de2)] - **test**: fix flaky test-runner coverage threshold test (Trivikram Kamat) [#​64051](nodejs/node#64051) - \[[`83b91ea6ec`](nodejs/node@83b91ea6ec)] - **test\_runner**: filter execArgv fallback for child tests (Trivikram Kamat) [#​64056](nodejs/node#64056) - \[[`269b609a3d`](nodejs/node@269b609a3d)] - **test\_runner**: improve coverage failure diagnostics (Trivikram Kamat) [#​64050](nodejs/node#64050) - \[[`0342744c34`](nodejs/node@0342744c34)] - **test\_runner**: add timestamp to JUnit reporter testsuites (sangwook) [#​64029](nodejs/node#64029) - \[[`086741d121`](nodejs/node@086741d121)] - **timers**: reuse Timeout objects in setStreamTimeout (Matteo Collina) [#​64254](nodejs/node#64254) - \[[`4e0236dc3d`](nodejs/node@4e0236dc3d)] - **(SEMVER-MINOR)** **tls**: report negotiated TLS groups (Filip Skokan) [#​64119](nodejs/node#64119) - \[[`3bdd7e20be`](nodejs/node@3bdd7e20be)] - **tls**: handle large RSA exponents in X.509 cert (Tobias Nießen) [#​64093](nodejs/node#64093) - \[[`c96c838977`](nodejs/node@c96c838977)] - **tools**: update RUSTC\_VERSION for remaining GHA workflows (René) [#​64325](nodejs/node#64325) - \[[`ee873b7aaf`](nodejs/node@ee873b7aaf)] - **tools**: bump `temporal_rs` version (Antoine du Hamel) [#​63281](nodejs/node#63281) - \[[`ea3b870155`](nodejs/node@ea3b870155)] - **tools**: remove `envinfo` from our workflows (Antoine du Hamel) [#​64259](nodejs/node#64259) - \[[`d940f02e8b`](nodejs/node@d940f02e8b)] - **tools**: bump the eslint group in /tools/eslint with 8 updates (dependabot\[bot]) [#​64249](nodejs/node#64249) - \[[`fe0ea2bb5d`](nodejs/node@fe0ea2bb5d)] - **tools**: bump [@​node-core/doc-kit](https://github.com/node-core/doc-kit) (dependabot\[bot]) [#​64010](nodejs/node#64010) - \[[`4dceefde1e`](nodejs/node@4dceefde1e)] - **tools**: bump undici from 6.24.1 to 6.27.0 in /tools/doc (dependabot\[bot]) [#​64031](nodejs/node#64031) - \[[`6e187db7d7`](nodejs/node@6e187db7d7)] - **tools**: update c-ares updater script (Antoine du Hamel) [#​64194](nodejs/node#64194) - \[[`657a35f5a2`](nodejs/node@657a35f5a2)] - **tools**: validate version number in release proposal commit message lint (Antoine du Hamel) [#​64070](nodejs/node#64070) - \[[`17228a861c`](nodejs/node@17228a861c)] - **tools**: add GHA benchmark runner (Antoine du Hamel) [#​60293](nodejs/node#60293) - \[[`6d11a71d91`](nodejs/node@6d11a71d91)] - **tools**: update `build-shared/action.yml` to a reusable workflow (Antoine du Hamel) [#​64059](nodejs/node#64059) - \[[`7a17c50b7f`](nodejs/node@7a17c50b7f)] - **tools**: update libffi updater script (Antoine du Hamel) [#​64046](nodejs/node#64046) - \[[`28047a3e71`](nodejs/node@28047a3e71)] - **tools**: exclude `libffi` changes from `test-shared` GHA CI (Antoine du Hamel) [#​64047](nodejs/node#64047) - \[[`58d9685acc`](nodejs/node@58d9685acc)] - **typings**: add typing for crypto (Filip Skokan) [#​64122](nodejs/node#64122) - \[[`7a9dcad44d`](nodejs/node@7a9dcad44d)] - **util**: fix OOM in inspect color stack formatting (Ijtihed Kilani) [#​64022](nodejs/node#64022) - \[[`d5f01bbbde`](nodejs/node@d5f01bbbde)] - **vfs**: reject rename into descendant directory (Trivikram Kamat) [#​64285](nodejs/node#64285) - \[[`0b6af91081`](nodejs/node@0b6af91081)] - **vfs**: handle current-position sentinel in memory files (Trivikram Kamat) [#​64163](nodejs/node#64163) - \[[`322230d641`](nodejs/node@322230d641)] - **vfs**: support writeFileSync with virtual fds (Trivikram Kamat) [#​64165](nodejs/node#64165) - \[[`9395d209c7`](nodejs/node@9395d209c7)] - **vfs**: avoid recursive readdir symlink cycles (Matteo Collina) [#​64168](nodejs/node#64168) - \[[`bbdd7643b6`](nodejs/node@bbdd7643b6)] - **vfs**: read RealFSProvider files from open fd (Trivikram Kamat) [#​64104](nodejs/node#64104) - \[[`92859b8097`](nodejs/node@92859b8097)] - **vm**: fix copying PropertyDescriptor (Chengzhong Wu) [#​64073](nodejs/node#64073) - \[[`9046035475`](nodejs/node@9046035475)] - **zlib**: validate flush king for all streams (Ic3b3rg) [#​63746](nodejs/node#63746) - \[[`98be4304a3`](nodejs/node@98be4304a3)] - **zlib**: validate flush kind for brotli streams (Ic3b3rg) [#​63746](nodejs/node#63746) - \[[`90007a59a9`](nodejs/node@90007a59a9)] - **zlib**: expose rejectGarbageAfterEnd option (Filip Skokan) [#​64023](nodejs/node#64023) - \[[`5933516066`](nodejs/node@5933516066)] - **zlib**: reject trailing gzip members in web streams (Filip Skokan) [#​64023](nodejs/node#64023) </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this MR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box --- This MR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yNTYuMCIsInVwZGF0ZWRJblZlciI6IjQzLjI1Ni4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJSZW5vdmF0ZSBCb3QiLCJhdXRvbWF0aW9uOmJvdC1hdXRob3JlZCIsImRlcGVuZGVuY3ktdHlwZTo6bWlub3IiXX0=-->
Node 26.5.0 added `--experimental-import-text` (nodejs/node#62300), which gates `import x from './f' with { type: 'text' }`. nub already provides text imports on every version that parses the `with` syntax (Node 18.20+) via its loader polyfill (loadTextImport). Per the additive contract, defer to Node's own textStrategy where it now exists and keep the polyfill only below it. - feature_matrix: import-text Unflag row [26.5.0, inf) so nub injects --experimental-import-text (open-ended; never default-on through Node 27). Below the floor the flag is not injected and is stripped from an inherited NODE_OPTIONS (it is a "bad option" there). - preload-common.cjs (fast tier): feature-detect native support via process.allowedNodeEnvironmentFlags; on 26.5+ nextLoad to native, else loadTextImport. preload-async-hooks.mjs (compat tier) always polyfills -- that tier tops out at Node 22.14, below 26.5. - docs: Modern APIs row now reads "polyfilled below Node 26.5, native above", floored at Node 18.20 (the `with`-syntax parse floor). Verified byte-for-byte parity against `node --experimental-import-text` on 26.5.0; polyfill path on 26.4.0/18.20.4; SyntaxError on 18.19.1. Claude-Session: https://claude.ai/code/session_01BgByKuKHWvYLhy6NSgdMkh
Closes #62082
Adds support for text import under
--experimental-import-textflag.Example:
Import text is a Stage 3 TC39 proposal
Deno supports text imports with
--unstable-raw-imports.Bun supports text imports directly.
Not entirely sure what the current stance is on not-yet-landed proposals, but putting this up for discussion and feedback.