1'use strict'; 2 3const common = require('../common'); 4const assert = require('assert'); 5const vm = require('vm'); 6const { WASI } = require('wasi'); 7 8const fixtures = require('../common/fixtures'); 9const bufferSource = fixtures.readSync('simple.wasm'); 10 11(async () => { 12 { 13 // Verify that a WebAssembly.Instance is passed in. 14 const wasi = new WASI(); 15 16 assert.throws( 17 () => { wasi.start(); }, 18 { 19 code: 'ERR_INVALID_ARG_TYPE', 20 message: /"instance" argument must be of type object/, 21 }, 22 ); 23 } 24 25 { 26 // Verify that the passed instance has an exports objects. 27 const wasi = new WASI({}); 28 const wasm = await WebAssembly.compile(bufferSource); 29 const instance = await WebAssembly.instantiate(wasm); 30 31 Object.defineProperty(instance, 'exports', { get() { return null; } }); 32 assert.throws( 33 () => { wasi.start(instance); }, 34 { 35 code: 'ERR_INVALID_ARG_TYPE', 36 message: /"instance\.exports" property must be of type object/, 37 }, 38 ); 39 } 40 41 { 42 // Verify that a _start() export was passed. 43 const wasi = new WASI({}); 44 const wasm = await WebAssembly.compile(bufferSource); 45 const instance = await WebAssembly.instantiate(wasm); 46 47 Object.defineProperty(instance, 'exports', { 48 get() { 49 return { memory: new WebAssembly.Memory({ initial: 1 }) }; 50 }, 51 }); 52 assert.throws( 53 () => { wasi.start(instance); }, 54 { 55 code: 'ERR_INVALID_ARG_TYPE', 56 message: /"instance\.exports\._start" property must be of type function/, 57 }, 58 ); 59 } 60 61 { 62 // Verify that an _initialize export was not passed. 63 const wasi = new WASI({}); 64 const wasm = await WebAssembly.compile(bufferSource); 65 const instance = await WebAssembly.instantiate(wasm); 66 67 Object.defineProperty(instance, 'exports', { 68 get() { 69 return { 70 _start() {}, 71 _initialize() {}, 72 memory: new WebAssembly.Memory({ initial: 1 }), 73 }; 74 }, 75 }); 76 assert.throws( 77 () => { wasi.start(instance); }, 78 { 79 code: 'ERR_INVALID_ARG_TYPE', 80 message: 'The "instance.exports._initialize" property must be' + 81 ' undefined. Received function _initialize', 82 }, 83 ); 84 } 85 86 { 87 // Verify that a memory export was passed. 88 const wasi = new WASI({}); 89 const wasm = await WebAssembly.compile(bufferSource); 90 const instance = await WebAssembly.instantiate(wasm); 91 92 Object.defineProperty(instance, 'exports', { 93 get() { return { _start() {} }; }, 94 }); 95 assert.throws( 96 () => { wasi.start(instance); }, 97 { 98 code: 'ERR_INVALID_ARG_TYPE', 99 message: /"instance\.exports\.memory" property must be a WebAssembly\.Memory object/, 100 }, 101 ); 102 } 103 104 { 105 // Verify that a WebAssembly.Instance from another VM context is accepted. 106 const wasi = new WASI({}); 107 const instance = await vm.runInNewContext(` 108 (async () => { 109 const wasm = await WebAssembly.compile(bufferSource); 110 const instance = await WebAssembly.instantiate(wasm); 111 112 Object.defineProperty(instance, 'exports', { 113 get() { 114 return { 115 _start() {}, 116 memory: new WebAssembly.Memory({ initial: 1 }) 117 }; 118 } 119 }); 120 121 return instance; 122 })() 123 `, { bufferSource }); 124 125 wasi.start(instance); 126 } 127 128 { 129 // Verify that start() can only be called once. 130 const wasi = new WASI({}); 131 const wasm = await WebAssembly.compile(bufferSource); 132 const instance = await WebAssembly.instantiate(wasm); 133 134 Object.defineProperty(instance, 'exports', { 135 get() { 136 return { 137 _start() {}, 138 memory: new WebAssembly.Memory({ initial: 1 }), 139 }; 140 }, 141 }); 142 wasi.start(instance); 143 assert.throws( 144 () => { wasi.start(instance); }, 145 { 146 code: 'ERR_WASI_ALREADY_STARTED', 147 message: /^WASI instance has already started$/, 148 }, 149 ); 150 } 151})().then(common.mustCall()); 152