Skip to content

Conversation

@guybedford
Copy link
Contributor

@guybedford guybedford commented Feb 5, 2025

This implements the Stage 3 Source Phase Imports proposal for Node.js (with latest specification at tc39/ecma262#3492), based on the new V8 parser and module loading APIs for this feature.

Phases in the module pipeline represent the ability to load uninstantiated modules (and in future with import defer, unexecuted modules as well).

While we are still waiting for progression on https://github.com/tc39/proposal-esm-phase-imports for JS Source Phase objects, this implements only the WebAssembly source phase per the Wasm ESM Integration Phase 3 proposal (https://github.com/webassembly/esm-integration).

This PR adds support both for dynamic and static source phase syntax:

import source mod1 from './mod.wasm';
const mod2 = await import.source('./mod.wasm');

This allows obtaining a Wasm module through the ESM integration, without it being instantiated through the Node.js resolver, to permit custom instantiations:

import source mod from './mod.wasm';

const instance = await WebAssembly.instantiate(mod, imports);

The dynamic source phase support is a one-line TODO, which is pending #56842. When this lands the skipped tests have been tested against that branch to fully pass.

When a source phase representation for a module is not available, a new ERR_SOURCE_PHASE_NOT_DEFINED SyntaxError is thrown as per the standard.

The VM API is updated to take a string phase argument as its last argument, although the ability to define source phase representations for virtual modules is not currently supported, and left as a future integration point. Perhaps this will simplify with ESM Phase Imports in future as well allowing handles to modules outside of the VM graph.

Resolves #53178.

@nodejs/loaders

@nodejs-github-bot
Copy link
Collaborator

Review requested:

  • @nodejs/loaders
  • @nodejs/startup
  • @nodejs/vm

@nodejs-github-bot nodejs-github-bot added lib / src Issues and PRs related to general changes in the lib or src directory. needs-ci PRs that need a full CI run. labels Feb 5, 2025
@guybedford guybedford force-pushed the source-phase-imports branch 2 times, most recently from c485531 to 8b3ce05 Compare February 5, 2025 02:31
@guybedford guybedford changed the title esm: Support Source Phase Imports for WebAssembly esm: Source Phase Imports for WebAssembly Feb 5, 2025
@codecov
Copy link

codecov bot commented Feb 5, 2025

Codecov Report

Attention: Patch coverage is 83.85965% with 46 lines in your changes missing coverage. Please review.

Project coverage is 90.24%. Comparing base (1a6bef2) to head (f18b561).
Report is 10 commits behind head on main.

Files with missing lines Patch % Lines
src/module_wrap.cc 59.52% 23 Missing and 11 partials ⚠️
lib/internal/modules/esm/loader.js 87.50% 3 Missing and 1 partial ⚠️
lib/internal/modules/esm/module_job.js 95.45% 4 Missing ⚠️
lib/internal/vm/module.js 85.71% 3 Missing ⚠️
lib/repl.js 75.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #56919      +/-   ##
==========================================
- Coverage   90.26%   90.24%   -0.03%     
==========================================
  Files         630      630              
  Lines      184690   184891     +201     
  Branches    36142    36173      +31     
==========================================
+ Hits       166712   166854     +142     
- Misses      11021    11064      +43     
- Partials     6957     6973      +16     
Files with missing lines Coverage Δ
lib/internal/modules/cjs/loader.js 98.26% <100.00%> (ø)
lib/internal/modules/esm/translators.js 91.51% <100.00%> (+0.06%) ⬆️
lib/internal/modules/esm/utils.js 98.91% <100.00%> (+0.01%) ⬆️
lib/internal/modules/run_main.js 97.60% <100.00%> (ø)
lib/internal/process/execution.js 94.79% <100.00%> (-0.16%) ⬇️
lib/internal/vm.js 100.00% <100.00%> (ø)
src/module_wrap.h 0.00% <ø> (ø)
src/node.cc 74.06% <100.00%> (+0.10%) ⬆️
src/node_errors.h 87.50% <100.00%> (+2.20%) ⬆️
lib/repl.js 94.90% <75.00%> (-0.05%) ⬇️
... and 4 more

... and 25 files with indirect coverage changes

Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

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

lgtm

@mcollina mcollina added the request-ci Add this label to start a Jenkins CI on a PR. label Feb 5, 2025
@github-actions github-actions bot removed the request-ci Add this label to start a Jenkins CI on a PR. label Feb 5, 2025
@nodejs-github-bot
Copy link
Collaborator

@marco-ippolito marco-ippolito added esm Issues and PRs related to the ECMAScript Modules implementation. wasm Issues and PRs related to WebAssembly. labels Feb 5, 2025
@targos targos added dont-land-on-v18.x dont-land-on-v20.x PRs that should not land on the v20.x-staging branch and should not be released in v20.x. dont-land-on-v22.x PRs that should not land on the v22.x-staging branch and should not be released in v22.x. semver-minor PRs that contain new features and should be released in the next minor version. labels Feb 5, 2025
@legendecas legendecas linked an issue Feb 5, 2025 that may be closed by this pull request
sbc100 added a commit to sbc100/emscripten that referenced this pull request Mar 3, 2025
Now that node support has been landed we can test this, at least
against the latest node canary builds.

See nodejs/node#56919

Fixes: emscripten-core#23047
sbc100 added a commit to sbc100/emscripten that referenced this pull request Mar 3, 2025
Now that node support has been landed we can test this, at least
against the latest node canary builds.

See nodejs/node#56919

Fixes: emscripten-core#23047
sbc100 added a commit to sbc100/emscripten that referenced this pull request Mar 4, 2025
Now that node support has been landed we can test this, at least
against the latest node canary builds.

See nodejs/node#56919

Fixes: emscripten-core#23047
sbc100 added a commit to sbc100/emscripten that referenced this pull request Mar 4, 2025
Now that node support has been landed we can test this, at least
against the latest node canary builds.

See nodejs/node#56919

Fixes: emscripten-core#23047
sbc100 added a commit to emscripten-core/emscripten that referenced this pull request Mar 4, 2025
Now that node support has been landed we can test this, at least
against the latest node canary builds.
    
See nodejs/node#56919
    
Fixes: #23047
RafaelGSS pushed a commit that referenced this pull request Apr 1, 2025
PR-URL: #56919
Reviewed-By: Matteo Collina <[email protected]>
Reviewed-By: Michaël Zasso <[email protected]>
Reviewed-By: Stephen Belanger <[email protected]>
RafaelGSS pushed a commit that referenced this pull request Apr 1, 2025
PR-URL: #56919
Reviewed-By: Matteo Collina <[email protected]>
Reviewed-By: Michaël Zasso <[email protected]>
Reviewed-By: Stephen Belanger <[email protected]>
RafaelGSS pushed a commit that referenced this pull request May 1, 2025
PR-URL: #56919
Reviewed-By: Matteo Collina <[email protected]>
Reviewed-By: Michaël Zasso <[email protected]>
Reviewed-By: Stephen Belanger <[email protected]>
RafaelGSS pushed a commit that referenced this pull request May 2, 2025
PR-URL: #56919
Reviewed-By: Matteo Collina <[email protected]>
Reviewed-By: Michaël Zasso <[email protected]>
Reviewed-By: Stephen Belanger <[email protected]>
codebytere added a commit to electron/electron that referenced this pull request Oct 21, 2025
codebytere added a commit to electron/electron that referenced this pull request Oct 22, 2025
codebytere added a commit to electron/electron that referenced this pull request Oct 22, 2025
codebytere added a commit to electron/electron that referenced this pull request Oct 23, 2025
codebytere added a commit to electron/electron that referenced this pull request Oct 24, 2025
codebytere added a commit to electron/electron that referenced this pull request Oct 28, 2025
codebytere added a commit to electron/electron that referenced this pull request Oct 28, 2025
codebytere added a commit to electron/electron that referenced this pull request Oct 30, 2025
codebytere added a commit to electron/electron that referenced this pull request Oct 30, 2025
codebytere added a commit to electron/electron that referenced this pull request Oct 30, 2025
* chore: upgrade Node.js to v24.10.0

* chore: fixup crypto patch

* chore: fixup crypto test patch

* src: prepare for v8 sandboxing

nodejs/node#58376

* esm: fix module.exports export on CJS modules

nodejs/node#57366

* chore: fixup lazyload fs patch

* esm: Source Phase Imports for WebAssembly

nodejs/node#56919

* module: remove --experimental-default-type

nodejs/node#56092

* lib,src: refactor assert to load error source from memory

nodejs/node#59751

* src: add source location to v8::TaskRunner

nodejs/node#54077

* src: remove dependency on wrapper-descriptor-based CppHeap

nodejs/node#54077

* src: do not use soon-to-be-deprecated V8 API

nodejs/node#53174

* src: stop using deprecated fields of v8::FastApiCallbackOptions

nodejs/node#54077

* test: update v8-stats test for V8 12.6

nodejs/node#54077

* esm: unflag --experimental-wasm-modules

nodejs/node#57038

* test: adapt assert tests to stack trace changes

nodejs/node#58070

* src,test: unregister the isolate after disposal and before freeing

nodejs/node#58070

* src: use cppgc to manage ContextifyContext

nodejs/node#56522

* src: replace uses of FastApiTypedArray

nodejs/node#58070

* module: integrate TypeScript into compile cache

nodejs/node#56629

* deps: update ada to 3.2.7

nodejs/node#59336

* src: make minor cleanups in encoding_binding.cc

nodejs/node#57448

* src: switch from `Get/SetPrototype` to `Get/SetPrototypeV2`

nodejs/node#55453

* src: use non-deprecated Get/SetPrototype methods

nodejs/node#59671

* src: simplify string_bytes with views

nodejs/node#54876

* src: improve utf8 string generation performance

nodejs/node#54873

* src: use non-deprecated Utf8LengthV2() method

nodejs/node#58070

* src: use non-deprecated WriteUtf8V2() method

nodejs/node#58070

* src: refactor WriteUCS2 and remove flags argument

nodejs/node#58163

* src: use String::WriteV2() in TwoByteValue

nodejs/node#58164

* node-api: use WriteV2 in napi_get_value_string_utf16

nodejs/node#58165

* node-api: use WriteOneByteV2 in napi_get_value_string_latin1

nodejs/node#58325

* src: migrate WriteOneByte to WriteOneByteV2

nodejs/node#59634

* fs: introduce dirent\.parentPath

nodejs/node#50976

* src: avoid copy by using std::views::keys

nodejs/node#56080

* chore: fixup patch indices

* fix: errant use of context->GetIsolate()

* fix: tweak BoringSSL compat patch for new changes

* fix: add back missing isolate dtor declaration

* fixup! esm: fix module.exports export on CJS modules

* cli: remove --no-experimental-fetch flag

https://github.com/nodejs/node/pull/52611/files

* esm: Source Phase Imports for WebAssembly

nodejs/node#56919

* fixup! src: prepare for v8 sandboxing

* chore: bump @types/node to v24

* chore: fix const assignment in crypto test

* fix: sandbox pointer patch issues

* chore: rework source phase import patch

* src: add percentage support to --max-old-space-size

nodejs/node#59082

* chore: fixup crypto tests

* chore: HostImportModuleWithPhaseDynamically todo

* fix: cjs esm failures

* fix: v8::Object::Wrappable issues

- v8/node@b72a615
- v8/node@490bac2
- v8/node@4896a0d

* chore: remove deleted specs

* src: use v8::ExternalMemoryAccounter

nodejs/node#58070

* fs: port SonicBoom module to fs module as FastUtf8Stream

nodejs/node#58897

* chore: tweak sandboxed pr patch

* test: disable parallel/test-os-checked-function

* test: use WHATWG URL instead of url.parse

* fix: OPENSSL_secure_zalloc doesn't work in BoringSSL

* chore: fix accidental extra line

* 7017517: [defer-import-eval] Parse import defer syntax

https://chromium-review.googlesource.com/c/v8/v8/+/7017517
trop bot added a commit to electron/electron that referenced this pull request Oct 30, 2025
trop bot added a commit to electron/electron that referenced this pull request Oct 30, 2025
TheCommieAxolotl pushed a commit to TheCommieAxolotl/electron that referenced this pull request Nov 2, 2025
* chore: upgrade Node.js to v24.10.0

* chore: fixup crypto patch

* chore: fixup crypto test patch

* src: prepare for v8 sandboxing

nodejs/node#58376

* esm: fix module.exports export on CJS modules

nodejs/node#57366

* chore: fixup lazyload fs patch

* esm: Source Phase Imports for WebAssembly

nodejs/node#56919

* module: remove --experimental-default-type

nodejs/node#56092

* lib,src: refactor assert to load error source from memory

nodejs/node#59751

* src: add source location to v8::TaskRunner

nodejs/node#54077

* src: remove dependency on wrapper-descriptor-based CppHeap

nodejs/node#54077

* src: do not use soon-to-be-deprecated V8 API

nodejs/node#53174

* src: stop using deprecated fields of v8::FastApiCallbackOptions

nodejs/node#54077

* test: update v8-stats test for V8 12.6

nodejs/node#54077

* esm: unflag --experimental-wasm-modules

nodejs/node#57038

* test: adapt assert tests to stack trace changes

nodejs/node#58070

* src,test: unregister the isolate after disposal and before freeing

nodejs/node#58070

* src: use cppgc to manage ContextifyContext

nodejs/node#56522

* src: replace uses of FastApiTypedArray

nodejs/node#58070

* module: integrate TypeScript into compile cache

nodejs/node#56629

* deps: update ada to 3.2.7

nodejs/node#59336

* src: make minor cleanups in encoding_binding.cc

nodejs/node#57448

* src: switch from `Get/SetPrototype` to `Get/SetPrototypeV2`

nodejs/node#55453

* src: use non-deprecated Get/SetPrototype methods

nodejs/node#59671

* src: simplify string_bytes with views

nodejs/node#54876

* src: improve utf8 string generation performance

nodejs/node#54873

* src: use non-deprecated Utf8LengthV2() method

nodejs/node#58070

* src: use non-deprecated WriteUtf8V2() method

nodejs/node#58070

* src: refactor WriteUCS2 and remove flags argument

nodejs/node#58163

* src: use String::WriteV2() in TwoByteValue

nodejs/node#58164

* node-api: use WriteV2 in napi_get_value_string_utf16

nodejs/node#58165

* node-api: use WriteOneByteV2 in napi_get_value_string_latin1

nodejs/node#58325

* src: migrate WriteOneByte to WriteOneByteV2

nodejs/node#59634

* fs: introduce dirent\.parentPath

nodejs/node#50976

* src: avoid copy by using std::views::keys

nodejs/node#56080

* chore: fixup patch indices

* fix: errant use of context->GetIsolate()

* fix: tweak BoringSSL compat patch for new changes

* fix: add back missing isolate dtor declaration

* fixup! esm: fix module.exports export on CJS modules

* cli: remove --no-experimental-fetch flag

https://github.com/nodejs/node/pull/52611/files

* esm: Source Phase Imports for WebAssembly

nodejs/node#56919

* fixup! src: prepare for v8 sandboxing

* chore: bump @types/node to v24

* chore: fix const assignment in crypto test

* fix: sandbox pointer patch issues

* chore: rework source phase import patch

* src: add percentage support to --max-old-space-size

nodejs/node#59082

* chore: fixup crypto tests

* chore: HostImportModuleWithPhaseDynamically todo

* fix: cjs esm failures

* fix: v8::Object::Wrappable issues

- v8/node@b72a615
- v8/node@490bac2
- v8/node@4896a0d

* chore: remove deleted specs

* src: use v8::ExternalMemoryAccounter

nodejs/node#58070

* fs: port SonicBoom module to fs module as FastUtf8Stream

nodejs/node#58897

* chore: tweak sandboxed pr patch

* test: disable parallel/test-os-checked-function

* test: use WHATWG URL instead of url.parse

* fix: OPENSSL_secure_zalloc doesn't work in BoringSSL

* chore: fix accidental extra line

* 7017517: [defer-import-eval] Parse import defer syntax

https://chromium-review.googlesource.com/c/v8/v8/+/7017517
codebytere added a commit to electron/electron that referenced this pull request Nov 4, 2025
* chore: upgrade Node.js to v24.10.0

Co-authored-by: Shelley Vohr <[email protected]>

* chore: fixup crypto patch

Co-authored-by: Shelley Vohr <[email protected]>

* chore: fixup crypto test patch

Co-authored-by: Shelley Vohr <[email protected]>

* src: prepare for v8 sandboxing

nodejs/node#58376

Co-authored-by: Shelley Vohr <[email protected]>

* esm: fix module.exports export on CJS modules

nodejs/node#57366

Co-authored-by: Shelley Vohr <[email protected]>

* chore: fixup lazyload fs patch

Co-authored-by: Shelley Vohr <[email protected]>

* esm: Source Phase Imports for WebAssembly

nodejs/node#56919

Co-authored-by: Shelley Vohr <[email protected]>

* module: remove --experimental-default-type

nodejs/node#56092

Co-authored-by: Shelley Vohr <[email protected]>

* lib,src: refactor assert to load error source from memory

nodejs/node#59751

Co-authored-by: Shelley Vohr <[email protected]>

* src: add source location to v8::TaskRunner

nodejs/node#54077

Co-authored-by: Shelley Vohr <[email protected]>

* src: remove dependency on wrapper-descriptor-based CppHeap

nodejs/node#54077

Co-authored-by: Shelley Vohr <[email protected]>

* src: do not use soon-to-be-deprecated V8 API

nodejs/node#53174

Co-authored-by: Shelley Vohr <[email protected]>

* src: stop using deprecated fields of v8::FastApiCallbackOptions

nodejs/node#54077

Co-authored-by: Shelley Vohr <[email protected]>

* test: update v8-stats test for V8 12.6

nodejs/node#54077

Co-authored-by: Shelley Vohr <[email protected]>

* esm: unflag --experimental-wasm-modules

nodejs/node#57038

Co-authored-by: Shelley Vohr <[email protected]>

* test: adapt assert tests to stack trace changes

nodejs/node#58070

Co-authored-by: Shelley Vohr <[email protected]>

* src,test: unregister the isolate after disposal and before freeing

nodejs/node#58070

Co-authored-by: Shelley Vohr <[email protected]>

* src: use cppgc to manage ContextifyContext

nodejs/node#56522

Co-authored-by: Shelley Vohr <[email protected]>

* src: replace uses of FastApiTypedArray

nodejs/node#58070

Co-authored-by: Shelley Vohr <[email protected]>

* module: integrate TypeScript into compile cache

nodejs/node#56629

Co-authored-by: Shelley Vohr <[email protected]>

* deps: update ada to 3.2.7

nodejs/node#59336

Co-authored-by: Shelley Vohr <[email protected]>

* src: make minor cleanups in encoding_binding.cc

nodejs/node#57448

Co-authored-by: Shelley Vohr <[email protected]>

* src: switch from `Get/SetPrototype` to `Get/SetPrototypeV2`

nodejs/node#55453

Co-authored-by: Shelley Vohr <[email protected]>

* src: use non-deprecated Get/SetPrototype methods

nodejs/node#59671

Co-authored-by: Shelley Vohr <[email protected]>

* src: simplify string_bytes with views

nodejs/node#54876

Co-authored-by: Shelley Vohr <[email protected]>

* src: improve utf8 string generation performance

nodejs/node#54873

Co-authored-by: Shelley Vohr <[email protected]>

* src: use non-deprecated Utf8LengthV2() method

nodejs/node#58070

Co-authored-by: Shelley Vohr <[email protected]>

* src: use non-deprecated WriteUtf8V2() method

nodejs/node#58070

Co-authored-by: Shelley Vohr <[email protected]>

* src: refactor WriteUCS2 and remove flags argument

nodejs/node#58163

Co-authored-by: Shelley Vohr <[email protected]>

* src: use String::WriteV2() in TwoByteValue

nodejs/node#58164

Co-authored-by: Shelley Vohr <[email protected]>

* node-api: use WriteV2 in napi_get_value_string_utf16

nodejs/node#58165

Co-authored-by: Shelley Vohr <[email protected]>

* node-api: use WriteOneByteV2 in napi_get_value_string_latin1

nodejs/node#58325

Co-authored-by: Shelley Vohr <[email protected]>

* src: migrate WriteOneByte to WriteOneByteV2

nodejs/node#59634

Co-authored-by: Shelley Vohr <[email protected]>

* fs: introduce dirent\.parentPath

nodejs/node#50976

Co-authored-by: Shelley Vohr <[email protected]>

* src: avoid copy by using std::views::keys

nodejs/node#56080

Co-authored-by: Shelley Vohr <[email protected]>

* chore: fixup patch indices

Co-authored-by: Shelley Vohr <[email protected]>

* fix: errant use of context->GetIsolate()

Co-authored-by: Shelley Vohr <[email protected]>

* fix: tweak BoringSSL compat patch for new changes

Co-authored-by: Shelley Vohr <[email protected]>

* fix: add back missing isolate dtor declaration

Co-authored-by: Shelley Vohr <[email protected]>

* fixup! esm: fix module.exports export on CJS modules

Co-authored-by: Shelley Vohr <[email protected]>

* cli: remove --no-experimental-fetch flag

https://github.com/nodejs/node/pull/52611/files

Co-authored-by: Shelley Vohr <[email protected]>

* esm: Source Phase Imports for WebAssembly

nodejs/node#56919

Co-authored-by: Shelley Vohr <[email protected]>

* fixup! src: prepare for v8 sandboxing

Co-authored-by: Shelley Vohr <[email protected]>

* chore: bump @types/node to v24

Co-authored-by: Shelley Vohr <[email protected]>

* chore: fix const assignment in crypto test

Co-authored-by: Shelley Vohr <[email protected]>

* fix: sandbox pointer patch issues

Co-authored-by: Shelley Vohr <[email protected]>

* chore: rework source phase import patch

Co-authored-by: Shelley Vohr <[email protected]>

* src: add percentage support to --max-old-space-size

nodejs/node#59082

Co-authored-by: Shelley Vohr <[email protected]>

* chore: fixup crypto tests

Co-authored-by: Shelley Vohr <[email protected]>

* chore: HostImportModuleWithPhaseDynamically todo

Co-authored-by: Shelley Vohr <[email protected]>

* fix: cjs esm failures

Co-authored-by: Shelley Vohr <[email protected]>

* fix: v8::Object::Wrappable issues

- v8/node@b72a615
- v8/node@490bac2
- v8/node@4896a0d

Co-authored-by: Shelley Vohr <[email protected]>

* chore: remove deleted specs

Co-authored-by: Shelley Vohr <[email protected]>

* src: use v8::ExternalMemoryAccounter

nodejs/node#58070

Co-authored-by: Shelley Vohr <[email protected]>

* fs: port SonicBoom module to fs module as FastUtf8Stream

nodejs/node#58897

Co-authored-by: Shelley Vohr <[email protected]>

* chore: tweak sandboxed pr patch

Co-authored-by: Shelley Vohr <[email protected]>

* test: disable parallel/test-os-checked-function

Co-authored-by: Shelley Vohr <[email protected]>

* test: use WHATWG URL instead of url.parse

Co-authored-by: Shelley Vohr <[email protected]>

* fix: OPENSSL_secure_zalloc doesn't work in BoringSSL

Co-authored-by: Shelley Vohr <[email protected]>

* chore: fix accidental extra line

Co-authored-by: Shelley Vohr <[email protected]>

* 7017517: [defer-import-eval] Parse import defer syntax

https://chromium-review.googlesource.com/c/v8/v8/+/7017517

Co-authored-by: Shelley Vohr <[email protected]>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dont-land-on-v20.x PRs that should not land on the v20.x-staging branch and should not be released in v20.x. dont-land-on-v22.x PRs that should not land on the v22.x-staging branch and should not be released in v22.x. esm Issues and PRs related to the ECMAScript Modules implementation. lib / src Issues and PRs related to general changes in the lib or src directory. needs-ci PRs that need a full CI run. semver-minor PRs that contain new features and should be released in the next minor version. wasm Issues and PRs related to WebAssembly.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

WebAssembly source phase imports Tracking issue: latest ESM Integration support

10 participants