diff --git a/doc/api/cli.md b/doc/api/cli.md index c983ec334de..5e1fb9c6399 100644 --- a/doc/api/cli.md +++ b/doc/api/cli.md @@ -33,8 +33,7 @@ If a file is found, its path will be passed to the * The program was started with a command-line flag that forces the entry point to be loaded with ECMAScript module loader, such as `--import`. -* The file has an `.mjs` or `.wasm` (with `--experimental-wasm-modules`) - extension. +* The file has an `.mjs` or `.wasm` extension. * The file does not have a `.cjs` extension, and the nearest parent `package.json` file contains a top-level [`"type"`][] field with a value of `"module"`. @@ -49,7 +48,6 @@ entry point, the `node` command will accept as input only files with `.js`, `.mjs`, or `.cjs` extensions. With the following flags, additional file extensions are enabled: -* [`--experimental-wasm-modules`][] for files with `.wasm` extension. * [`--experimental-addon-modules`][] for files with `.node` extension. ## Options @@ -1255,14 +1253,6 @@ changes: Enable experimental WebAssembly System Interface (WASI) support. -### `--experimental-wasm-modules` - - - -Enable experimental WebAssembly module support. - ### `--experimental-webstorage` Importing both WebAssembly module instances and WebAssembly source phase -imports are supported under the `--experimental-wasm-modules` flag. +imports is supported. Both of these integrations are in line with the [ES Module Integration Proposal for WebAssembly][]. -Instance imports allow any `.wasm` files to be imported as normal modules, -supporting their module imports in turn. - -For example, an `index.js` containing: - -```js -import * as M from './library.wasm'; -console.log(M); -``` - -executed under: - -```bash -node --experimental-wasm-modules index.mjs -``` - -would provide the exports interface for the instantiation of `library.wasm`. - ### Wasm Source Phase Imports +> Stability: 1.2 - Release candidate + @@ -766,6 +755,8 @@ const instance = await WebAssembly.instantiate(dynamicLibrary, importObject); ### JavaScript String Builtins +> Stability: 1.2 - Release candidate + @@ -815,14 +806,36 @@ const { exports: { getLength } } = await WebAssembly.instantiate(mod, {}); getLength('foo'); // Also returns 3. ``` +### Wasm Instance Phase Imports + +> Stability: 1.1 - Active development + +Instance imports allow any `.wasm` files to be imported as normal modules, +supporting their module imports in turn. + +For example, an `index.js` containing: + +```js +import * as M from './library.wasm'; +console.log(M); +``` + +executed under: + +```bash +node index.mjs +``` + +would provide the exports interface for the instantiation of `library.wasm`. + ### Reserved Wasm Namespaces -When importing WebAssembly modules through the ESM Integration, they cannot use -import module names or import/export names that start with reserved prefixes: +When importing WebAssembly module instances, they cannot use import module +names or import/export names that start with reserved prefixes: * `wasm-js:` - reserved in all module import names, module names and export names. @@ -1189,7 +1202,7 @@ _isImports_, _conditions_) > 1. Return _"commonjs"_. > 4. If _url_ ends in _".json"_, then > 1. Return _"json"_. -> 5. If `--experimental-wasm-modules` is enabled and _url_ ends in +> 5. If _url_ ends in > _".wasm"_, then > 1. Return _"wasm"_. > 6. If `--experimental-addon-modules` is enabled and _url_ ends in @@ -1207,9 +1220,8 @@ _isImports_, _conditions_) > 1. Return _"module"_. > 3. Return _"commonjs"_. > 12. If _url_ does not have any extension, then -> 1. If _packageType_ is _"module"_ and `--experimental-wasm-modules` is -> enabled and the file at _url_ contains the header for a WebAssembly -> module, then +> 1. If _packageType_ is _"module"_ and the file at _url_ contains the +> "application/wasm" content type header for a WebAssembly module, then > 1. Return _"wasm"_. > 2. If _packageType_ is not **null**, then > 1. Return _packageType_. diff --git a/doc/node-config-schema.json b/doc/node-config-schema.json index 2c23ed9c84a..e280834028c 100644 --- a/doc/node-config-schema.json +++ b/doc/node-config-schema.json @@ -180,9 +180,6 @@ "experimental-vm-modules": { "type": "boolean" }, - "experimental-wasm-modules": { - "type": "boolean" - }, "experimental-websocket": { "type": "boolean" }, diff --git a/doc/node.1 b/doc/node.1 index 76abd99b534..14ce85c9e6c 100644 --- a/doc/node.1 +++ b/doc/node.1 @@ -223,9 +223,6 @@ Enable experimental ES module support in VM module. Enable experimental WebAssembly System Interface support. This flag is no longer required as WASI is enabled by default. . -.It Fl -experimental-wasm-modules -Enable experimental WebAssembly module support. -. .It Fl -experimental-quic Enable the experimental QUIC support. . diff --git a/lib/internal/modules/esm/formats.js b/lib/internal/modules/esm/formats.js index d21ea5fa216..8d4af32b612 100644 --- a/lib/internal/modules/esm/formats.js +++ b/lib/internal/modules/esm/formats.js @@ -9,7 +9,6 @@ const { getValidatedPath } = require('internal/fs/utils'); const fsBindings = internalBinding('fs'); const { internal: internalConstants } = internalBinding('constants'); -const experimentalWasmModules = getOptionValue('--experimental-wasm-modules'); const experimentalAddonModules = getOptionValue('--experimental-addon-modules'); const extensionFormatMap = { @@ -18,12 +17,9 @@ const extensionFormatMap = { '.js': 'module', '.json': 'json', '.mjs': 'module', + '.wasm': 'wasm', }; -if (experimentalWasmModules) { - extensionFormatMap['.wasm'] = 'wasm'; -} - if (experimentalAddonModules) { extensionFormatMap['.node'] = 'addon'; } @@ -46,7 +42,7 @@ function mimeToFormat(mime) { ) !== null ) { return 'module'; } if (mime === 'application/json') { return 'json'; } - if (experimentalWasmModules && mime === 'application/wasm') { return 'wasm'; } + if (mime === 'application/wasm') { return 'wasm'; } return null; } @@ -58,7 +54,6 @@ function mimeToFormat(mime) { * @returns {'wasm'|'module'} */ function getFormatOfExtensionlessFile(url) { - if (!experimentalWasmModules) { return 'module'; } const path = getValidatedPath(url); switch (fsBindings.getFormatOfExtensionlessFile(path)) { case internalConstants.EXTENSIONLESS_FORMAT_WASM: diff --git a/lib/internal/modules/esm/translators.js b/lib/internal/modules/esm/translators.js index e837f2d1ff3..b6ac42302a1 100644 --- a/lib/internal/modules/esm/translators.js +++ b/lib/internal/modules/esm/translators.js @@ -495,8 +495,6 @@ translators.set('json', function jsonStrategy(url, source) { */ const wasmInstances = new SafeWeakMap(); translators.set('wasm', async function(url, source) { - emitExperimentalWarning('Importing WebAssembly modules'); - assertBufferSource(source, false, 'load'); debug(`Translating WASMModule ${url}`); @@ -546,6 +544,7 @@ translators.set('wasm', async function(url, source) { const createDynamicModule = require('internal/modules/esm/create_dynamic_module'); const { module } = createDynamicModule([...importsList], [...exportsList], url, (reflect) => { + emitExperimentalWarning('Importing WebAssembly module instances'); for (const impt of importsList) { const importNs = reflect.imports[impt]; const wasmInstance = wasmInstances.get(importNs); diff --git a/src/node.cc b/src/node.cc index 1adca8e8d58..18a1f388881 100644 --- a/src/node.cc +++ b/src/node.cc @@ -773,9 +773,7 @@ static ExitCode ProcessGlobalArgsInternal(std::vector* args, env_opts->abort_on_uncaught_exception = true; } - if (env_opts->experimental_wasm_modules) { - v8_args.emplace_back("--js-source-phase-imports"); - } + v8_args.emplace_back("--js-source-phase-imports"); #ifdef __POSIX__ // Block SIGPROF signals when sleeping in epoll_wait/kevent/etc. Avoids the diff --git a/src/node_options.cc b/src/node_options.cc index f54ea2e6cce..6aaa67c38df 100644 --- a/src/node_options.cc +++ b/src/node_options.cc @@ -536,10 +536,7 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { kAllowedInEnvvar); AddAlias("--loader", "--experimental-loader"); AddOption("--experimental-modules", "", NoOp{}, kAllowedInEnvvar); - AddOption("--experimental-wasm-modules", - "experimental ES Module support for webassembly modules", - &EnvironmentOptions::experimental_wasm_modules, - kAllowedInEnvvar); + AddOption("--experimental-wasm-modules", "", NoOp{}, kAllowedInEnvvar); AddOption("--experimental-import-meta-resolve", "experimental ES Module import.meta.resolve() parentURL support", &EnvironmentOptions::experimental_import_meta_resolve, diff --git a/src/node_options.h b/src/node_options.h index 84a9d1de860..8bd537f7d9e 100644 --- a/src/node_options.h +++ b/src/node_options.h @@ -133,7 +133,6 @@ class EnvironmentOptions : public Options { std::string localstorage_file; bool experimental_global_navigator = true; bool experimental_global_web_crypto = true; - bool experimental_wasm_modules = false; bool experimental_import_meta_resolve = false; std::string input_type; // Value of --input-type bool entry_is_url = false; diff --git a/test/es-module/test-esm-wasm.mjs b/test/es-module/test-esm-wasm.mjs index 86aa347c357..5f3632c8390 100644 --- a/test/es-module/test-esm-wasm.mjs +++ b/test/es-module/test-esm-wasm.mjs @@ -9,7 +9,6 @@ describe('ESM: WASM modules', { concurrency: !process.env.TEST_PARALLEL }, () => it('should load exports', async () => { const { code, stderr, stdout } = await spawnPromisified(execPath, [ '--no-warnings', - '--experimental-wasm-modules', '--input-type=module', '--eval', [ @@ -32,7 +31,6 @@ describe('ESM: WASM modules', { concurrency: !process.env.TEST_PARALLEL }, () => it('should not allow code injection through export names', async () => { const { code, stderr, stdout } = await spawnPromisified(execPath, [ '--no-warnings', - '--experimental-wasm-modules', '--input-type=module', '--eval', `import * as wasmExports from ${JSON.stringify(fixtures.fileURL('es-modules/export-name-code-injection.wasm'))};`, @@ -46,7 +44,6 @@ describe('ESM: WASM modules', { concurrency: !process.env.TEST_PARALLEL }, () => it('should allow non-identifier export names', async () => { const { code, stderr, stdout } = await spawnPromisified(execPath, [ '--no-warnings', - '--experimental-wasm-modules', '--input-type=module', '--eval', [ @@ -64,7 +61,6 @@ describe('ESM: WASM modules', { concurrency: !process.env.TEST_PARALLEL }, () => it('should properly handle all WebAssembly global types', async () => { const { code, stderr, stdout } = await spawnPromisified(execPath, [ '--no-warnings', - '--experimental-wasm-modules', '--input-type=module', '--eval', [ @@ -211,7 +207,6 @@ describe('ESM: WASM modules', { concurrency: !process.env.TEST_PARALLEL }, () => it('should properly escape import names as well', async () => { const { code, stderr, stdout } = await spawnPromisified(execPath, [ '--no-warnings', - '--experimental-wasm-modules', '--input-type=module', '--eval', [ @@ -226,22 +221,20 @@ describe('ESM: WASM modules', { concurrency: !process.env.TEST_PARALLEL }, () => strictEqual(code, 0); }); - it('should emit experimental warning', async () => { + it('should emit experimental warning for module instances', async () => { const { code, signal, stderr } = await spawnPromisified(execPath, [ - '--experimental-wasm-modules', fixtures.path('es-modules/wasm-modules.mjs'), ]); strictEqual(code, 0); strictEqual(signal, null); match(stderr, /ExperimentalWarning/); - match(stderr, /WebAssembly/); + match(stderr, /Importing WebAssembly module instances/); }); it('should support top-level execution', async () => { const { code, stderr, stdout } = await spawnPromisified(execPath, [ '--no-warnings', - '--experimental-wasm-modules', fixtures.path('es-modules/top-level-wasm.wasm'), ]); @@ -253,7 +246,6 @@ describe('ESM: WASM modules', { concurrency: !process.env.TEST_PARALLEL }, () => it('should support static source phase imports', async () => { const { code, stderr, stdout } = await spawnPromisified(execPath, [ '--no-warnings', - '--experimental-wasm-modules', '--input-type=module', '--eval', [ @@ -274,7 +266,6 @@ describe('ESM: WASM modules', { concurrency: !process.env.TEST_PARALLEL }, () => it('should support dynamic source phase imports', async () => { const { code, stderr, stdout } = await spawnPromisified(execPath, [ '--no-warnings', - '--experimental-wasm-modules', '--input-type=module', '--eval', [ @@ -296,7 +287,6 @@ describe('ESM: WASM modules', { concurrency: !process.env.TEST_PARALLEL }, () => it('should not execute source phase imports', async () => { const { code, stderr, stdout } = await spawnPromisified(execPath, [ '--no-warnings', - '--experimental-wasm-modules', '--input-type=module', '--eval', [ @@ -315,7 +305,6 @@ describe('ESM: WASM modules', { concurrency: !process.env.TEST_PARALLEL }, () => it('should not execute dynamic source phase imports', async () => { const { code, stderr, stdout } = await spawnPromisified(execPath, [ '--no-warnings', - '--experimental-wasm-modules', '--input-type=module', '--eval', `await import.source(${JSON.stringify(fixtures.fileURL('es-modules/unimportable.wasm'))})`, @@ -330,7 +319,6 @@ describe('ESM: WASM modules', { concurrency: !process.env.TEST_PARALLEL }, () => const fileUrl = fixtures.fileURL('es-modules/wasm-source-phase.js'); const { code, stderr, stdout } = await spawnPromisified(execPath, [ '--no-warnings', - '--experimental-wasm-modules', '--input-type=module', '--eval', [ @@ -353,7 +341,6 @@ describe('ESM: WASM modules', { concurrency: !process.env.TEST_PARALLEL }, () => const fileUrl = fixtures.fileURL('es-modules/wasm-source-phase.js'); const { code, stderr, stdout } = await spawnPromisified(execPath, [ '--no-warnings', - '--experimental-wasm-modules', '--input-type=module', '--eval', `import source nosource from ${JSON.stringify(fileUrl)};`, @@ -367,7 +354,6 @@ describe('ESM: WASM modules', { concurrency: !process.env.TEST_PARALLEL }, () => it('should throw for vm source phase static import', async () => { const { code, stderr, stdout } = await spawnPromisified(execPath, [ '--no-warnings', - '--experimental-wasm-modules', '--experimental-vm-modules', '--input-type=module', '--eval', @@ -386,7 +372,6 @@ describe('ESM: WASM modules', { concurrency: !process.env.TEST_PARALLEL }, () => it('should throw for vm source phase dynamic import', async () => { const { code, stderr, stdout } = await spawnPromisified(execPath, [ '--no-warnings', - '--experimental-wasm-modules', '--experimental-vm-modules', '--input-type=module', '--eval', @@ -407,7 +392,6 @@ describe('ESM: WASM modules', { concurrency: !process.env.TEST_PARALLEL }, () => it('should reject wasm: import names', async () => { const { code, stderr, stdout } = await spawnPromisified(execPath, [ '--no-warnings', - '--experimental-wasm-modules', '--input-type=module', '--eval', `import(${JSON.stringify(fixtures.fileURL('es-modules/invalid-import-name.wasm'))})`, @@ -421,7 +405,6 @@ describe('ESM: WASM modules', { concurrency: !process.env.TEST_PARALLEL }, () => it('should reject wasm-js: import names', async () => { const { code, stderr, stdout } = await spawnPromisified(execPath, [ '--no-warnings', - '--experimental-wasm-modules', '--input-type=module', '--eval', `import(${JSON.stringify(fixtures.fileURL('es-modules/invalid-import-name-wasm-js.wasm'))})`, @@ -435,7 +418,6 @@ describe('ESM: WASM modules', { concurrency: !process.env.TEST_PARALLEL }, () => it('should reject wasm-js: import module names', async () => { const { code, stderr, stdout } = await spawnPromisified(execPath, [ '--no-warnings', - '--experimental-wasm-modules', '--input-type=module', '--eval', `import(${JSON.stringify(fixtures.fileURL('es-modules/invalid-import-module.wasm'))})`, @@ -449,7 +431,6 @@ describe('ESM: WASM modules', { concurrency: !process.env.TEST_PARALLEL }, () => it('should reject wasm: export names', async () => { const { code, stderr, stdout } = await spawnPromisified(execPath, [ '--no-warnings', - '--experimental-wasm-modules', '--input-type=module', '--eval', `import(${JSON.stringify(fixtures.fileURL('es-modules/invalid-export-name.wasm'))})`, @@ -463,7 +444,6 @@ describe('ESM: WASM modules', { concurrency: !process.env.TEST_PARALLEL }, () => it('should reject wasm-js: export names', async () => { const { code, stderr, stdout } = await spawnPromisified(execPath, [ '--no-warnings', - '--experimental-wasm-modules', '--input-type=module', '--eval', `import(${JSON.stringify(fixtures.fileURL('es-modules/invalid-export-name-wasm-js.wasm'))})`, @@ -477,7 +457,6 @@ describe('ESM: WASM modules', { concurrency: !process.env.TEST_PARALLEL }, () => it('should support js-string builtins', async () => { const { code, stderr, stdout } = await spawnPromisified(execPath, [ '--no-warnings', - '--experimental-wasm-modules', '--input-type=module', '--eval', [ diff --git a/test/module-hooks/test-module-hooks-import-wasm.mjs b/test/module-hooks/test-module-hooks-import-wasm.mjs index f2c357cd503..00e6cd41265 100644 --- a/test/module-hooks/test-module-hooks-import-wasm.mjs +++ b/test/module-hooks/test-module-hooks-import-wasm.mjs @@ -1,6 +1,5 @@ -// Flags: --no-experimental-wasm-modules // This tests that module.registerHooks() can be used to support unknown formats, like -// import(wasm) (without --experimental-wasm-modules). +// import(wasm) import '../common/index.mjs'; import assert from 'node:assert'; diff --git a/test/module-hooks/test-module-hooks-require-wasm.js b/test/module-hooks/test-module-hooks-require-wasm.js index b4276bcc749..1cf7da6451f 100644 --- a/test/module-hooks/test-module-hooks-require-wasm.js +++ b/test/module-hooks/test-module-hooks-require-wasm.js @@ -1,8 +1,7 @@ -// Flags: --no-experimental-wasm-modules 'use strict'; // This tests that module.registerHooks() can be used to support unknown formats, like -// require(wasm) and import(wasm) (without --experimental-wasm-modules). +// require(wasm) and import(wasm) const common = require('../common'); const assert = require('assert'); diff --git a/test/parallel/test-process-env-allowed-flags-are-documented.js b/test/parallel/test-process-env-allowed-flags-are-documented.js index 1522e5b865c..07e38748b07 100644 --- a/test/parallel/test-process-env-allowed-flags-are-documented.js +++ b/test/parallel/test-process-env-allowed-flags-are-documented.js @@ -118,6 +118,7 @@ assert(undocumented.delete('--debug-arraybuffer-allocations')); assert(undocumented.delete('--no-debug-arraybuffer-allocations')); assert(undocumented.delete('--es-module-specifier-resolution')); assert(undocumented.delete('--experimental-fetch')); +assert(undocumented.delete('--experimental-wasm-modules')); assert(undocumented.delete('--experimental-global-customevent')); assert(undocumented.delete('--experimental-global-webcrypto')); assert(undocumented.delete('--experimental-report'));