Skip to content

esm: WebAssembly.Global unwrapping for Wasm Namespaces #57525

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

guybedford
Copy link
Contributor

This is a draft PR implementing a Wasm ESM Integration PR for global unwrapping in WebAssembly/esm-integration#104.

Opening here as a draft only for feedback and discussion, as it helps to have a concrete implementation for understanding and experimentation.

With this change, WebAssembly namespaces exporting globals have the global value provided directly on the namespace exports, instead of exporting WebAssembly.Global requiring a global.value getter access in turn to retrieve the underlying binding. With this, Wasm namespaces can effectively export any JS binding type when using Wasm GC, instead of just Memory, Table, Function and Global.

We do this by unwrapping the global on the Wasm namespace exports interface, while still linking Wasm - Wasm imports to the underlying global. Ideally this would support live exported bindings as well, but that would require V8 work in turn.

@nodejs-github-bot
Copy link
Collaborator

Review requested:

  • @nodejs/loaders

@nodejs-github-bot nodejs-github-bot added esm Issues and PRs related to the ECMAScript Modules implementation. needs-ci PRs that need a full CI run. labels Mar 18, 2025
@guybedford guybedford force-pushed the wasm-globals-ns-unwrapping branch 3 times, most recently from 0f49b0a to 91278fe Compare March 24, 2025 20:56
@syg
Copy link
Contributor

syg commented Apr 9, 2025

Is the plan to gate this behind an experimental flag, independently of unflagging Wasm ESM integration generally? I didn't get the sense there's consensus for this from the Wasm CG.

@guybedford
Copy link
Contributor Author

guybedford commented Apr 9, 2025

@syg I'll only land this once WebAssembly/esm-integration#104 has landed. The Wasm CG vote was 6 for, 15 neutral and 1 against. The 1 vote against has since been resolved via WebAssembly/esm-integration#108. I'm therefore planning to post a summary on WebAssembly/esm-integration#104 before landing that soon, unless you have outstanding concerns.

@syg
Copy link
Contributor

syg commented Apr 9, 2025

I'll only land this once WebAssembly/esm-integration#104 has landed

To clarify, "land this" means land it unflagged?

The Wasm CG vote was 6 for, 15 neutral and 1 against. The 1 vote against has since been resolved via WebAssembly/esm-integration#108.

Wasn't that a temperature check? I did not get the sense that we had browser agreement to eventually implement the unwrapping.

@guybedford
Copy link
Contributor Author

guybedford commented Apr 9, 2025

To clarify, "land this" means land it unflagged?

The ESM Integration in Node.js remains flagged overall, there are no plans to have a separate flag for this feature, no.

Wasn't that a temperature check? I did not get the sense that we had browser agreement to eventually implement the unwrapping.

There is no requirement for Phase 3 specification changes to go through CG vote. The temperature check was to ensure we are making all members aware and to engage on any concerns. I wasn't aware that there was any outstanding disagreement - do you have outstanding concerns?

@syg
Copy link
Contributor

syg commented Apr 9, 2025

I wasn't aware that there was any outstanding disagreement - do you have outstanding concerns?

My concern is that this change has had the least baking time, and if Node will be the first one to ship for a while, by the time the browsers get to implementing and giving implementation feedback, there may be interop issues with Node's behavior.

@guybedford
Copy link
Contributor Author

By landing this flagged we can continue to build implementation feedback per Phase 3 process. We will also continue to bring implementation updates to the CG to ensure adequate feedback throughout the process.

Point taken on ensuring baking time, and it's good for others to be aware of this as well. We very much would like to see this alignment come together for a fully supported WebAssembly Module Record in V8.

Unflagging will not be rushed as discussed, but if the concern of implementation divergence leads to delays of many months or next year then that does start to affect adoption quite considerably, and put Node.js in a position where we may have to unflag first and without Chrome's implementation experience.

To avoid any implementation divergence scenario, it would help to have any concerns from Chromium clearly raised early in the process, and also to have a clear statement if there remains after shipping the source phase no intent to ship the instance phase. It would be a real shame to continue to hold Node.js and other environments back in this regard unnecessarily by not providing clear intent when these environments could be benefitting from this feature already. If Chromium does not want to ship the instance phase, it cannot simultaneously block the feature for other environments like Node.js and Deno that do want to ship it, by claiming it doesn't have implementation experience when that is a choice that was made by Chrome not to engage in implementation and not a choice made by Node.js and Deno.

@guybedford
Copy link
Contributor Author

WebAssembly/esm-integration#104 has now landed, so I'm marking that as non-draft for further review.

@syg please do open upstream issues if you have any concerns here at all or items to discuss, and feel free to reach out to me directly.

@guybedford guybedford marked this pull request as ready for review April 10, 2025 19:08
Copy link

codecov bot commented Apr 10, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 90.16%. Comparing base (5d3e1b5) to head (1d7e15f).
Report is 10 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #57525      +/-   ##
==========================================
+ Coverage   89.64%   90.16%   +0.52%     
==========================================
  Files         630      630              
  Lines      186470   186521      +51     
  Branches    36305    36622     +317     
==========================================
+ Hits       167160   168185    +1025     
+ Misses      12073    11127     -946     
+ Partials     7237     7209      -28     
Files with missing lines Coverage Δ
lib/internal/modules/esm/create_dynamic_module.js 95.78% <100.00%> (ø)
lib/internal/modules/esm/translators.js 92.24% <100.00%> (+0.84%) ⬆️

... and 93 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Member

@JakobJingleheimer JakobJingleheimer left a comment

Choose a reason for hiding this comment

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

I dunno too much about Wasm, so I can only comment on the code itself and how it fits into modules.

@guybedford guybedford force-pushed the wasm-globals-ns-unwrapping branch from 13a34c8 to 7e69a90 Compare May 2, 2025 20:21
@guybedford
Copy link
Contributor Author

Thanks @JakobJingleheimer for the review here, I believe I've covered all the feedback.

@JakobJingleheimer
Copy link
Member

Thanks! I think it does look/flow better now :) I see there are test failures now; I'm not sure if they were there before? If they're new, sorry 😅 Do you want help debugging?

@guybedford
Copy link
Contributor Author

@JakobJingleheimer tests are passing here finally.

Copy link
Member

@JakobJingleheimer JakobJingleheimer left a comment

Choose a reason for hiding this comment

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

LGTM aside from the spread thing that I'm not sure about.

const { module } = createDynamicModule(imports, exports, url, (reflect) => {
const createDynamicModule = require('internal/modules/esm/create_dynamic_module');

const { module } = createDynamicModule([...importsList], [...exportsList], url, (reflect) => {
Copy link
Member

Choose a reason for hiding this comment

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

Spread might not be safe even on Safe* objects. @aduh95 I think you know better.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
esm Issues and PRs related to the ECMAScript Modules implementation. needs-ci PRs that need a full CI run.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants