| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent e1fe0b6 commit 7f845e6
3 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -70,14 +70,15 @@ added: v12.16.0 | |||
| 70 | 70 | ||
| 71 | 71 | * `instance` {WebAssembly.Instance} | |
| 72 | 72 | ||
| 73 | - Attempt to begin execution of `instance` by invoking its `_start()` export. | ||
| 74 | - If `instance` does not contain a `_start()` export, then `start()` attempts to | ||
| 75 | - invoke the `_initialize()` export. If neither of those exports is present on | ||
| 76 | - `instance`, then `start()` does nothing. | ||
| 73 | + Attempt to begin execution of `instance` as a WASI command by invoking its | ||
| 74 | + `_start()` export. If `instance` does not contain a `_start()` export, or if | ||
| 75 | + `instance` contains an `_initialize()` export, then an exception is thrown. | ||
| 77 | 76 | ||
| 78 | 77 | `start()` requires that `instance` exports a [`WebAssembly.Memory`][] named | |
| 79 | 78 | `memory`. If `instance` does not have a `memory` export an exception is thrown. | |
| 80 | 79 | ||
| 80 | + If `start()` is called more than once, an exception is thrown. | ||
| 81 | + | ||
| 81 | 82 | ### `wasi.wasiImport` | |
| 82 | 83 | <!-- YAML | |
| 83 | 84 | added: v12.16.0 | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -79,7 +79,17 @@ class WASI { | |||
| 79 | 79 | ||
| 80 | 80 | validateObject(exports, 'instance.exports'); | |
| 81 | 81 | ||
| 82 | - const { memory } = exports; | ||
| 82 | + const { _initialize, _start, memory } = exports; | ||
| 83 | + | ||
| 84 | + if (typeof _start !== 'function') { | ||
| 85 | + throw new ERR_INVALID_ARG_TYPE( | ||
| 86 | + 'instance.exports._start', 'function', _start); | ||
| 87 | + } | ||
| 88 | + | ||
| 89 | + if (_initialize !== undefined) { | ||
| 90 | + throw new ERR_INVALID_ARG_TYPE( | ||
| 91 | + 'instance.exports._initialize', 'undefined', _initialize); | ||
| 92 | + } | ||
| 83 | 93 | ||
| 84 | 94 | if (!(memory instanceof WebAssembly.Memory)) { | |
| 85 | 95 | throw new ERR_INVALID_ARG_TYPE( | |
@@ -94,10 +104,7 @@ class WASI { | |||
| 94 | 104 | this[kSetMemory](memory); | |
| 95 | 105 | ||
| 96 | 106 | try { | |
| 97 | - if (exports._start) | ||
| 98 | - exports._start(); | ||
| 99 | - else if (exports._initialize) | ||
| 100 | - exports._initialize(); | ||
| 107 | + exports._start(); | ||
| 101 | 108 | } catch (err) { | |
| 102 | 109 | if (err !== kExitCode) { | |
| 103 | 110 | throw err; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -8,85 +8,111 @@ const { WASI } = require('wasi'); | |||
| 8 | 8 | const fixtures = require('../common/fixtures'); | |
| 9 | 9 | const bufferSource = fixtures.readSync('simple.wasm'); | |
| 10 | 10 | ||
| 11 | - { | ||
| 12 | - const wasi = new WASI(); | ||
| 13 | - assert.throws( | ||
| 14 | - () => { | ||
| 15 | - wasi.start(); | ||
| 16 | - }, | ||
| 17 | - { code: 'ERR_INVALID_ARG_TYPE', message: /\bWebAssembly\.Instance\b/ } | ||
| 18 | - ); | ||
| 19 | - } | ||
| 20 | - | ||
| 21 | 11 | (async () => { | |
| 22 | - const wasi = new WASI({}); | ||
| 23 | - const wasm = await WebAssembly.compile(bufferSource); | ||
| 24 | - const instance = await WebAssembly.instantiate(wasm); | ||
| 12 | + { | ||
| 13 | + // Verify that a WebAssembly.Instance is passed in. | ||
| 14 | + const wasi = new WASI(); | ||
| 25 | 15 | ||
| 26 | - assert.throws( | ||
| 27 | - () => { wasi.start(instance); }, | ||
| 28 | - { code: 'ERR_INVALID_ARG_TYPE', message: /\bWebAssembly\.Memory\b/ } | ||
| 29 | - ); | ||
| 30 | - })(); | ||
| 16 | + assert.throws( | ||
| 17 | + () => { wasi.start(); }, | ||
| 18 | + { code: 'ERR_INVALID_ARG_TYPE', message: /\bWebAssembly\.Instance\b/ } | ||
| 19 | + ); | ||
| 20 | + } | ||
| 31 | 21 | ||
| 32 | - (async () => { | ||
| 33 | - const wasi = new WASI(); | ||
| 34 | - const wasm = await WebAssembly.compile(bufferSource); | ||
| 35 | - const instance = await WebAssembly.instantiate(wasm); | ||
| 36 | - const values = [undefined, null, 'foo', 42, true, false, () => {}]; | ||
| 37 | - let cnt = 0; | ||
| 22 | + { | ||
| 23 | + // Verify that the passed instance has an exports objects. | ||
| 24 | + const wasi = new WASI({}); | ||
| 25 | + const wasm = await WebAssembly.compile(bufferSource); | ||
| 26 | + const instance = await WebAssembly.instantiate(wasm); | ||
| 27 | + | ||
| 28 | + Object.defineProperty(instance, 'exports', { get() { return null; } }); | ||
| 29 | + assert.throws( | ||
| 30 | + () => { wasi.start(instance); }, | ||
| 31 | + { | ||
| 32 | + code: 'ERR_INVALID_ARG_TYPE', | ||
| 33 | + message: /"instance\.exports" property must be of type object/ | ||
| 34 | + } | ||
| 35 | + ); | ||
| 36 | + } | ||
| 38 | 37 | ||
| 39 | - // Mock instance.exports to trigger start() validation. | ||
| 40 | - Object.defineProperty(instance, 'exports', { | ||
| 41 | - get() { return values[cnt++]; } | ||
| 42 | - }); | ||
| 38 | + { | ||
| 39 | + // Verify that a _start() export was passed. | ||
| 40 | + const wasi = new WASI({}); | ||
| 41 | + const wasm = await WebAssembly.compile(bufferSource); | ||
| 42 | + const instance = await WebAssembly.instantiate(wasm); | ||
| 43 | 43 | ||
| 44 | - values.forEach((val) => { | ||
| 44 | + Object.defineProperty(instance, 'exports', { get() { return {}; } }); | ||
| 45 | 45 | assert.throws( | |
| 46 | 46 | () => { wasi.start(instance); }, | |
| 47 | - { code: 'ERR_INVALID_ARG_TYPE', message: /\binstance\.exports\b/ } | ||
| 47 | + { | ||
| 48 | + code: 'ERR_INVALID_ARG_TYPE', | ||
| 49 | + message: /"instance\.exports\._start" property must be of type function/ | ||
| 50 | + } | ||
| 48 | 51 | ); | |
| 49 | - }); | ||
| 50 | - })(); | ||
| 52 | + } | ||
| 51 | 53 | ||
| 52 | - (async () => { | ||
| 53 | - const wasi = new WASI(); | ||
| 54 | - const wasm = await WebAssembly.compile(bufferSource); | ||
| 55 | - const instance = await WebAssembly.instantiate(wasm); | ||
| 54 | + { | ||
| 55 | + // Verify that an _initialize export was not passed. | ||
| 56 | + const wasi = new WASI({}); | ||
| 57 | + const wasm = await WebAssembly.compile(bufferSource); | ||
| 58 | + const instance = await WebAssembly.instantiate(wasm); | ||
| 56 | 59 | ||
| 57 | - // Mock instance.exports.memory to bypass start() validation. | ||
| 58 | - Object.defineProperty(instance, 'exports', { | ||
| 59 | - get() { | ||
| 60 | - return { | ||
| 61 | - memory: new WebAssembly.Memory({ initial: 1 }) | ||
| 62 | - }; | ||
| 63 | - } | ||
| 64 | - }); | ||
| 60 | + Object.defineProperty(instance, 'exports', { | ||
| 61 | + get() { | ||
| 62 | + return { | ||
| 63 | + _start() {}, | ||
| 64 | + _initialize() {} | ||
| 65 | + }; | ||
| 66 | + } | ||
| 67 | + }); | ||
| 68 | + assert.throws( | ||
| 69 | + () => { wasi.start(instance); }, | ||
| 70 | + { | ||
| 71 | + code: 'ERR_INVALID_ARG_TYPE', | ||
| 72 | + message: /"instance\.exports\._initialize" property must be undefined/ | ||
| 73 | + } | ||
| 74 | + ); | ||
| 75 | + } | ||
| 65 | 76 | ||
| 66 | - wasi.start(instance); | ||
| 67 | - assert.throws( | ||
| 68 | - () => { wasi.start(instance); }, | ||
| 69 | - { | ||
| 70 | - code: 'ERR_WASI_ALREADY_STARTED', | ||
| 71 | - message: /^WASI instance has already started$/ | ||
| 72 | - } | ||
| 73 | - ); | ||
| 74 | - })(); | ||
| 77 | + { | ||
| 78 | + // Verify that a memory export was passed. | ||
| 79 | + const wasi = new WASI({}); | ||
| 80 | + const wasm = await WebAssembly.compile(bufferSource); | ||
| 81 | + const instance = await WebAssembly.instantiate(wasm); | ||
| 75 | 82 | ||
| 76 | - (async () => { | ||
| 77 | - const wasi = new WASI(); | ||
| 78 | - const wasm = await WebAssembly.compile(bufferSource); | ||
| 79 | - const instance = await WebAssembly.instantiate(wasm); | ||
| 83 | + Object.defineProperty(instance, 'exports', { | ||
| 84 | + get() { return { _start() {} }; } | ||
| 85 | + }); | ||
| 86 | + assert.throws( | ||
| 87 | + () => { wasi.start(instance); }, | ||
| 88 | + { | ||
| 89 | + code: 'ERR_INVALID_ARG_TYPE', | ||
| 90 | + message: /"instance\.exports\.memory" property .+ WebAssembly\.Memory/ | ||
| 91 | + } | ||
| 92 | + ); | ||
| 93 | + } | ||
| 80 | 94 | ||
| 81 | - // Mock instance.exports to bypass start() validation. | ||
| 82 | - Object.defineProperty(instance, 'exports', { | ||
| 83 | - get() { | ||
| 84 | - return { | ||
| 85 | - memory: new WebAssembly.Memory({ initial: 1 }), | ||
| 86 | - _initialize: common.mustCall() | ||
| 87 | - }; | ||
| 88 | - } | ||
| 89 | - }); | ||
| 95 | + { | ||
| 96 | + // Verify that start() can only be called once. | ||
| 97 | + const wasi = new WASI({}); | ||
| 98 | + const wasm = await WebAssembly.compile(bufferSource); | ||
| 99 | + const instance = await WebAssembly.instantiate(wasm); | ||
| 90 | 100 | ||
| 91 | - wasi.start(instance); | ||
| 92 | - })(); | ||
| 101 | + Object.defineProperty(instance, 'exports', { | ||
| 102 | + get() { | ||
| 103 | + return { | ||
| 104 | + _start() {}, | ||
| 105 | + memory: new WebAssembly.Memory({ initial: 1 }) | ||
| 106 | + }; | ||
| 107 | + } | ||
| 108 | + }); | ||
| 109 | + wasi.start(instance); | ||
| 110 | + assert.throws( | ||
| 111 | + () => { wasi.start(instance); }, | ||
| 112 | + { | ||
| 113 | + code: 'ERR_WASI_ALREADY_STARTED', | ||
| 114 | + message: /^WASI instance has already started$/ | ||
| 115 | + } | ||
| 116 | + ); | ||
| 117 | + } | ||
| 118 | + })().then(common.mustCall()); | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments