diff --git a/doc/api/wasi.md b/doc/api/wasi.md index f70470d8dc0732..bd84a320ae24e9 100644 --- a/doc/api/wasi.md +++ b/doc/api/wasi.md @@ -118,6 +118,9 @@ added: - v13.3.0 - v12.16.0 changes: + - version: REPLACEME + pr-url: https://github.com/nodejs/node/pull/47390 + description: default for returnOnExit changed to true. - version: v19.8.0 pr-url: https://github.com/nodejs/node/pull/46469 description: version field added to options. @@ -133,10 +136,11 @@ changes: sandbox directory structure. The string keys of `preopens` are treated as directories within the sandbox. The corresponding values in `preopens` are the real paths to those directories on the host machine. - * `returnOnExit` {boolean} By default, WASI applications terminate the Node.js - process via the `__wasi_proc_exit()` function. Setting this option to `true` - causes `wasi.start()` to return the exit code rather than terminate the - process. **Default:** `false`. + * `returnOnExit` {boolean} By default, when WASI applications call + `__wasi_proc_exit()` `wasi.start()` will returns with the exit code + specified rather than terminatng the process. Setting this option to + `false` will cause the Node.js process to exit with the specified + exit code instead. **Default:** `true`. * `stdin` {integer} The file descriptor used as standard input in the WebAssembly application. **Default:** `0`. * `stdout` {integer} The file descriptor used as standard output in the diff --git a/lib/wasi.js b/lib/wasi.js index 78e7025ba338df..8d54450baf96ec 100644 --- a/lib/wasi.js +++ b/lib/wasi.js @@ -109,11 +109,13 @@ class WASI { wrap[prop] = FunctionPrototypeBind(wrap[prop], wrap); } + let returnOnExit = true; if (options.returnOnExit !== undefined) { - validateBoolean(options.returnOnExit, 'options.returnOnExit'); - if (options.returnOnExit) - wrap.proc_exit = FunctionPrototypeBind(wasiReturnOnProcExit, this); + returnOnExit = options.returnOnExit; + validateBoolean(returnOnExit, 'options.returnOnExit'); } + if (returnOnExit === true) + wrap.proc_exit = FunctionPrototypeBind(wasiReturnOnProcExit, this); this[kSetMemory] = wrap._setMemory; delete wrap._setMemory; diff --git a/test/wasi/test-wasi.js b/test/wasi/test-wasi.js index 2ddc4290352a20..f3cd380797cdfc 100644 --- a/test/wasi/test-wasi.js +++ b/test/wasi/test-wasi.js @@ -1,6 +1,14 @@ 'use strict'; const common = require('../common'); +function returnOnExitEnvToValue(env) { + const envValue = env.RETURN_ON_EXIT; + if (envValue !== undefined) + return envValue === 'true'; + + return undefined; +} + if (process.argv[2] === 'wasi-child-default') { // test default case const fixtures = require('../common/fixtures'); @@ -21,6 +29,7 @@ if (process.argv[2] === 'wasi-child-default') { '/sandbox': fixtures.path('wasi'), '/tmp': tmpdir.path, }, + returnOnExit: returnOnExitEnvToValue(process.env), }); const importObject = { wasi_snapshot_preview1: wasi.wasiImport }; const modulePath = path.join(wasmDir, `${process.argv[3]}.wasm`); @@ -53,6 +62,7 @@ if (process.argv[2] === 'wasi-child-default') { '/sandbox': fixtures.path('wasi'), '/tmp': tmpdir.path, }, + returnOnExit: returnOnExitEnvToValue(process.env), }); // Validate the getImportObject helper @@ -86,6 +96,9 @@ if (process.argv[2] === 'wasi-child-default') { if (options.stdin !== undefined) opts.input = options.stdin; + if (options.returnOnExit === false) + opts.env.RETURN_ON_EXIT = 'false'; + const child = cp.spawnSync(process.execPath, [ ...args, __filename, @@ -110,7 +123,9 @@ if (process.argv[2] === 'wasi-child-default') { if (!common.isIBMi) { runWASI({ test: 'clock_getres' }); } - runWASI({ test: 'exitcode', exitCode: 120 }); + runWASI({ test: 'exitcode' }); + runWASI({ test: 'exitcode', returnOnExit: true }); + runWASI({ test: 'exitcode', exitCode: 120, returnOnExit: false }); runWASI({ test: 'fd_prestat_get_refresh' }); runWASI({ test: 'freopen', stdout: `hello from input2.txt${checkoutEOL}` }); runWASI({ test: 'ftruncate' });