Skip to content

Commit 7efae93

Browse files
committed
wasi: make version non-optional
- remove default for version - updates tests to specify version - add test for when version is not specified Signed-off-by: Michael Dawson <[email protected]> PR-URL: #47391 Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Tobias Nießen <[email protected]>
1 parent 509b1eb commit 7efae93

11 files changed

+54
-83
lines changed

doc/api/wasi.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,9 @@ added:
118118
- v13.3.0
119119
- v12.16.0
120120
changes:
121+
- version: REPLACEME
122+
pr-url: https://github.com/nodejs/node/pull/47391
123+
description: The version option is now required and has no default value.
121124
- version: v19.8.0
122125
pr-url: https://github.com/nodejs/node/pull/46469
123126
description: version field added to options.
@@ -144,7 +147,8 @@ changes:
144147
* `stderr` {integer} The file descriptor used as standard error in the
145148
WebAssembly application. **Default:** `2`.
146149
* `version` {string} The version of WASI requested. Currently the only
147-
supported versions are `unstable` and `preview1`. **Default:** `preview1`.
150+
supported versions are `unstable` and `preview1`. This option is
151+
mandatory.
148152
149153
### `wasi.getImportObject()`
150154

lib/wasi.js

+15-22
Original file line numberDiff line numberDiff line change
@@ -48,28 +48,21 @@ class WASI {
4848
validateObject(options, 'options');
4949

5050
let _WASI;
51-
if (options.version !== undefined) {
52-
validateString(options.version, 'options.version');
53-
switch (options.version) {
54-
case 'unstable':
55-
({ WASI: _WASI } = internalBinding('wasi'));
56-
this[kBindingName] = 'wasi_unstable';
57-
break;
58-
// When adding support for additional wasi versions add case here
59-
case 'preview1':
60-
({ WASI: _WASI } = internalBinding('wasi'));
61-
this[kBindingName] = 'wasi_snapshot_preview1';
62-
break;
63-
// When adding support for additional wasi versions add case here
64-
default:
65-
throw new ERR_INVALID_ARG_VALUE('options.version',
66-
options.version,
67-
'unsupported WASI version');
68-
}
69-
} else {
70-
// TODO(mdawson): Remove this in a SemVer major PR before Node.js 20
71-
({ WASI: _WASI } = internalBinding('wasi'));
72-
this[kBindingName] = 'wasi_snapshot_preview1';
51+
validateString(options.version, 'options.version');
52+
switch (options.version) {
53+
case 'unstable':
54+
({ WASI: _WASI } = internalBinding('wasi'));
55+
this[kBindingName] = 'wasi_unstable';
56+
break;
57+
case 'preview1':
58+
({ WASI: _WASI } = internalBinding('wasi'));
59+
this[kBindingName] = 'wasi_snapshot_preview1';
60+
break;
61+
// When adding support for additional wasi versions add case here
62+
default:
63+
throw new ERR_INVALID_ARG_VALUE('options.version',
64+
options.version,
65+
'unsupported WASI version');
7366
}
7467

7568
if (options.args !== undefined)

test/wasi/test-return-on-exit.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const modulePath = path.join(wasmDir, 'exitcode.wasm');
99
const buffer = fs.readFileSync(modulePath);
1010

1111
(async () => {
12-
const wasi = new WASI({ returnOnExit: true });
12+
const wasi = new WASI({ version: 'preview1', returnOnExit: true });
1313
const importObject = { wasi_snapshot_preview1: wasi.wasiImport };
1414
const { instance } = await WebAssembly.instantiate(buffer, importObject);
1515

@@ -19,7 +19,7 @@ const buffer = fs.readFileSync(modulePath);
1919
(async () => {
2020
// Verify that if a WASI application throws an exception, Node rethrows it
2121
// properly.
22-
const wasi = new WASI({ returnOnExit: true });
22+
const wasi = new WASI({ version: 'preview1', returnOnExit: true });
2323
const patchedExit = () => { throw new Error('test error'); };
2424
wasi.wasiImport.proc_exit = patchedExit.bind(wasi.wasiImport);
2525
const importObject = { wasi_snapshot_preview1: wasi.wasiImport };

test/wasi/test-wasi-initialize-validation.js

+7-7
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const bufferSource = fixtures.readSync('simple.wasm');
1111
(async () => {
1212
{
1313
// Verify that a WebAssembly.Instance is passed in.
14-
const wasi = new WASI();
14+
const wasi = new WASI({ version: 'preview1' });
1515

1616
assert.throws(
1717
() => { wasi.initialize(); },
@@ -24,7 +24,7 @@ const bufferSource = fixtures.readSync('simple.wasm');
2424

2525
{
2626
// Verify that the passed instance has an exports objects.
27-
const wasi = new WASI({});
27+
const wasi = new WASI({ version: 'preview1' });
2828
const wasm = await WebAssembly.compile(bufferSource);
2929
const instance = await WebAssembly.instantiate(wasm);
3030

@@ -40,7 +40,7 @@ const bufferSource = fixtures.readSync('simple.wasm');
4040

4141
{
4242
// Verify that a _initialize() export was passed.
43-
const wasi = new WASI({});
43+
const wasi = new WASI({ version: 'preview1' });
4444
const wasm = await WebAssembly.compile(bufferSource);
4545
const instance = await WebAssembly.instantiate(wasm);
4646

@@ -63,7 +63,7 @@ const bufferSource = fixtures.readSync('simple.wasm');
6363

6464
{
6565
// Verify that a _start export was not passed.
66-
const wasi = new WASI({});
66+
const wasi = new WASI({ version: 'preview1' });
6767
const wasm = await WebAssembly.compile(bufferSource);
6868
const instance = await WebAssembly.instantiate(wasm);
6969

@@ -88,7 +88,7 @@ const bufferSource = fixtures.readSync('simple.wasm');
8888

8989
{
9090
// Verify that a memory export was passed.
91-
const wasi = new WASI({});
91+
const wasi = new WASI({ version: 'preview1' });
9292
const wasm = await WebAssembly.compile(bufferSource);
9393
const instance = await WebAssembly.instantiate(wasm);
9494

@@ -106,7 +106,7 @@ const bufferSource = fixtures.readSync('simple.wasm');
106106

107107
{
108108
// Verify that a WebAssembly.Instance from another VM context is accepted.
109-
const wasi = new WASI({});
109+
const wasi = new WASI({ version: 'preview1' });
110110
const instance = await vm.runInNewContext(`
111111
(async () => {
112112
const wasm = await WebAssembly.compile(bufferSource);
@@ -130,7 +130,7 @@ const bufferSource = fixtures.readSync('simple.wasm');
130130

131131
{
132132
// Verify that initialize() can only be called once.
133-
const wasi = new WASI({});
133+
const wasi = new WASI({ version: 'preview1' });
134134
const wasm = await WebAssembly.compile(bufferSource);
135135
const instance = await WebAssembly.instantiate(wasm);
136136

test/wasi/test-wasi-not-started.js

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ if (process.argv[2] === 'wasi-child') {
88

99
const { WASI } = require('wasi');
1010
const wasi = new WASI({
11+
version: 'preview1',
1112
args: ['foo', '-bar', '--baz=value'],
1213
});
1314
const importObject = { wasi_snapshot_preview1: wasi.wasiImport };

test/wasi/test-wasi-options-validation.js

+12-9
Original file line numberDiff line numberDiff line change
@@ -5,34 +5,34 @@ const assert = require('assert');
55
const { WASI } = require('wasi');
66

77
// If args is undefined, it should default to [] and should not throw.
8-
new WASI({});
8+
new WASI({ version: 'preview1' });
99

1010
// If args is not an Array and not undefined, it should throw.
11-
assert.throws(() => { new WASI({ args: 'fhqwhgads' }); },
11+
assert.throws(() => { new WASI({ version: 'preview1', args: 'fhqwhgads' }); },
1212
{ code: 'ERR_INVALID_ARG_TYPE', message: /\bargs\b/ });
1313

1414
// If env is not an Object and not undefined, it should throw.
15-
assert.throws(() => { new WASI({ env: 'fhqwhgads' }); },
15+
assert.throws(() => { new WASI({ version: 'preview1', env: 'fhqwhgads' }); },
1616
{ code: 'ERR_INVALID_ARG_TYPE', message: /\benv\b/ });
1717

1818
// If preopens is not an Object and not undefined, it should throw.
19-
assert.throws(() => { new WASI({ preopens: 'fhqwhgads' }); },
19+
assert.throws(() => { new WASI({ version: 'preview1', preopens: 'fhqwhgads' }); },
2020
{ code: 'ERR_INVALID_ARG_TYPE', message: /\bpreopens\b/ });
2121

2222
// If returnOnExit is not a boolean and not undefined, it should throw.
23-
assert.throws(() => { new WASI({ returnOnExit: 'fhqwhgads' }); },
23+
assert.throws(() => { new WASI({ version: 'preview1', returnOnExit: 'fhqwhgads' }); },
2424
{ code: 'ERR_INVALID_ARG_TYPE', message: /\breturnOnExit\b/ });
2525

2626
// If stdin is not an int32 and not undefined, it should throw.
27-
assert.throws(() => { new WASI({ stdin: 'fhqwhgads' }); },
27+
assert.throws(() => { new WASI({ version: 'preview1', stdin: 'fhqwhgads' }); },
2828
{ code: 'ERR_INVALID_ARG_TYPE', message: /\bstdin\b/ });
2929

3030
// If stdout is not an int32 and not undefined, it should throw.
31-
assert.throws(() => { new WASI({ stdout: 'fhqwhgads' }); },
31+
assert.throws(() => { new WASI({ version: 'preview1', stdout: 'fhqwhgads' }); },
3232
{ code: 'ERR_INVALID_ARG_TYPE', message: /\bstdout\b/ });
3333

3434
// If stderr is not an int32 and not undefined, it should throw.
35-
assert.throws(() => { new WASI({ stderr: 'fhqwhgads' }); },
35+
assert.throws(() => { new WASI({ version: 'preview1', stderr: 'fhqwhgads' }); },
3636
{ code: 'ERR_INVALID_ARG_TYPE', message: /\bstderr\b/ });
3737

3838
// If options is provided, but not an object, the constructor should throw.
@@ -43,13 +43,16 @@ assert.throws(() => { new WASI({ stderr: 'fhqwhgads' }); },
4343

4444
// Verify that exceptions thrown from the binding layer are handled.
4545
assert.throws(() => {
46-
new WASI({ preopens: { '/sandbox': '__/not/real/path' } });
46+
new WASI({ version: 'preview1', preopens: { '/sandbox': '__/not/real/path' } });
4747
}, { code: 'UVWASI_ENOENT', message: /uvwasi_init/ });
4848

4949
// If version is not a string, it should throw
5050
assert.throws(() => { new WASI({ version: { x: 'y' } }); },
5151
{ code: 'ERR_INVALID_ARG_TYPE', message: /\bversion\b/ });
5252

53+
// If version is not specified, it should throw.
54+
assert.throws(() => { new WASI(); },
55+
{ code: 'ERR_INVALID_ARG_TYPE', message: /\bversion\b/ });
5356

5457
// If version is an unsupported version, it should throw
5558
assert.throws(() => { new WASI({ version: 'not_a_version' }); },

test/wasi/test-wasi-start-validation.js

+7-7
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const bufferSource = fixtures.readSync('simple.wasm');
1111
(async () => {
1212
{
1313
// Verify that a WebAssembly.Instance is passed in.
14-
const wasi = new WASI();
14+
const wasi = new WASI({ version: 'preview1' });
1515

1616
assert.throws(
1717
() => { wasi.start(); },
@@ -24,7 +24,7 @@ const bufferSource = fixtures.readSync('simple.wasm');
2424

2525
{
2626
// Verify that the passed instance has an exports objects.
27-
const wasi = new WASI({});
27+
const wasi = new WASI({ version: 'preview1' });
2828
const wasm = await WebAssembly.compile(bufferSource);
2929
const instance = await WebAssembly.instantiate(wasm);
3030

@@ -40,7 +40,7 @@ const bufferSource = fixtures.readSync('simple.wasm');
4040

4141
{
4242
// Verify that a _start() export was passed.
43-
const wasi = new WASI({});
43+
const wasi = new WASI({ version: 'preview1' });
4444
const wasm = await WebAssembly.compile(bufferSource);
4545
const instance = await WebAssembly.instantiate(wasm);
4646

@@ -60,7 +60,7 @@ const bufferSource = fixtures.readSync('simple.wasm');
6060

6161
{
6262
// Verify that an _initialize export was not passed.
63-
const wasi = new WASI({});
63+
const wasi = new WASI({ version: 'preview1' });
6464
const wasm = await WebAssembly.compile(bufferSource);
6565
const instance = await WebAssembly.instantiate(wasm);
6666

@@ -85,7 +85,7 @@ const bufferSource = fixtures.readSync('simple.wasm');
8585

8686
{
8787
// Verify that a memory export was passed.
88-
const wasi = new WASI({});
88+
const wasi = new WASI({ version: 'preview1' });
8989
const wasm = await WebAssembly.compile(bufferSource);
9090
const instance = await WebAssembly.instantiate(wasm);
9191

@@ -103,7 +103,7 @@ const bufferSource = fixtures.readSync('simple.wasm');
103103

104104
{
105105
// Verify that a WebAssembly.Instance from another VM context is accepted.
106-
const wasi = new WASI({});
106+
const wasi = new WASI({ version: 'preview1' });
107107
const instance = await vm.runInNewContext(`
108108
(async () => {
109109
const wasm = await WebAssembly.compile(bufferSource);
@@ -127,7 +127,7 @@ const bufferSource = fixtures.readSync('simple.wasm');
127127

128128
{
129129
// Verify that start() can only be called once.
130-
const wasi = new WASI({});
130+
const wasi = new WASI({ version: 'preview1' });
131131
const wasm = await WebAssembly.compile(bufferSource);
132132
const instance = await WebAssembly.instantiate(wasm);
133133

test/wasi/test-wasi-stdio.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ writeFileSync(stdinFile, 'x'.repeat(33));
1818
const stdin = openSync(stdinFile, 'r');
1919
const stdout = openSync(stdoutFile, 'a');
2020
const stderr = openSync(stderrFile, 'a');
21-
const wasi = new WASI({ stdin, stdout, stderr, returnOnExit: true });
21+
const wasi = new WASI({ version: 'preview1', stdin, stdout, stderr, returnOnExit: true });
2222
const importObject = { wasi_snapshot_preview1: wasi.wasiImport };
2323

2424
(async () => {

test/wasi/test-wasi-symlinks.js

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ if (process.argv[2] === 'wasi-child') {
1010
const { WASI } = require('wasi');
1111
const wasmDir = path.join(__dirname, 'wasm');
1212
const wasi = new WASI({
13+
version: 'preview1',
1314
args: [],
1415
env: process.env,
1516
preopens: {

test/wasi/test-wasi-worker-terminate.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ if (!process.env.HAS_STARTED_WORKER) {
3434
}
3535

3636
async function go() {
37-
const wasi = new WASI({ returnOnExit: true });
37+
const wasi = new WASI({ version: 'preview1', returnOnExit: true });
3838
const imports = { wasi_snapshot_preview1: wasi.wasiImport };
3939
const module = await WebAssembly.compile(bytecode);
4040
const instance = await WebAssembly.instantiate(module, imports);

test/wasi/test-wasi.js

+2-33
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,7 @@
11
'use strict';
22
const common = require('../common');
33

4-
if (process.argv[2] === 'wasi-child-default') {
5-
// test default case
6-
const fixtures = require('../common/fixtures');
7-
const tmpdir = require('../common/tmpdir');
8-
const fs = require('fs');
9-
const path = require('path');
10-
11-
common.expectWarning('ExperimentalWarning',
12-
'WASI is an experimental feature and might change at any time');
13-
14-
const { WASI } = require('wasi');
15-
tmpdir.refresh();
16-
const wasmDir = path.join(__dirname, 'wasm');
17-
const wasi = new WASI({
18-
args: ['foo', '-bar', '--baz=value'],
19-
env: process.env,
20-
preopens: {
21-
'/sandbox': fixtures.path('wasi'),
22-
'/tmp': tmpdir.path,
23-
},
24-
});
25-
const importObject = { wasi_snapshot_preview1: wasi.wasiImport };
26-
const modulePath = path.join(wasmDir, `${process.argv[3]}.wasm`);
27-
const buffer = fs.readFileSync(modulePath);
28-
29-
(async () => {
30-
const { instance } = await WebAssembly.instantiate(buffer, importObject);
31-
32-
wasi.start(instance);
33-
})().then(common.mustCall());
34-
} else if (process.argv[2] === 'wasi-child-preview1') {
4+
if (process.argv[2] === 'wasi-child-preview1') {
355
// Test version set to preview1
366
const assert = require('assert');
377
const fixtures = require('../common/fixtures');
@@ -73,7 +43,7 @@ if (process.argv[2] === 'wasi-child-default') {
7343
const cp = require('child_process');
7444
const { checkoutEOL } = common;
7545

76-
function innerRunWASI(options, args, flavor = 'default') {
46+
function innerRunWASI(options, args, flavor = 'preview1') {
7747
console.log('executing', options.test);
7848
const opts = {
7949
env: {
@@ -101,7 +71,6 @@ if (process.argv[2] === 'wasi-child-default') {
10171
function runWASI(options) {
10272
innerRunWASI(options, ['--no-turbo-fast-api-calls']);
10373
innerRunWASI(options, ['--turbo-fast-api-calls']);
104-
innerRunWASI(options, ['--turbo-fast-api-calls'], 'preview1');
10574
}
10675

10776
runWASI({ test: 'cant_dotdot' });

0 commit comments

Comments
 (0)