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.initialize(); }, 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.initialize(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 _initialize() 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 { 50 _initialize: 5, 51 memory: new WebAssembly.Memory({ initial: 1 }), 52 }; 53 }, 54 }); 55 assert.throws( 56 () => { wasi.initialize(instance); }, 57 { 58 code: 'ERR_INVALID_ARG_TYPE', 59 message: /"instance\.exports\._initialize" property must be of type function/, 60 }, 61 ); 62 } 63 64 { 65 // Verify that a _start export was not passed. 66 const wasi = new WASI({}); 67 const wasm = await WebAssembly.compile(bufferSource); 68 const instance = await WebAssembly.instantiate(wasm); 69 70 Object.defineProperty(instance, 'exports', { 71 get() { 72 return { 73 _start() {}, 74 _initialize() {}, 75 memory: new WebAssembly.Memory({ initial: 1 }), 76 }; 77 }, 78 }); 79 assert.throws( 80 () => { wasi.initialize(instance); }, 81 { 82 code: 'ERR_INVALID_ARG_TYPE', 83 message: 'The "instance.exports._start" property must be' + 84 ' undefined. Received function _start', 85 }, 86 ); 87 } 88 89 { 90 // Verify that a memory export was passed. 91 const wasi = new WASI({}); 92 const wasm = await WebAssembly.compile(bufferSource); 93 const instance = await WebAssembly.instantiate(wasm); 94 95 Object.defineProperty(instance, 'exports', { 96 get() { return { _initialize() {} }; }, 97 }); 98 assert.throws( 99 () => { wasi.initialize(instance); }, 100 { 101 code: 'ERR_INVALID_ARG_TYPE', 102 message: /"instance\.exports\.memory" property must be a WebAssembly\.Memory object/, 103 }, 104 ); 105 } 106 107 { 108 // Verify that a WebAssembly.Instance from another VM context is accepted. 109 const wasi = new WASI({}); 110 const instance = await vm.runInNewContext(` 111 (async () => { 112 const wasm = await WebAssembly.compile(bufferSource); 113 const instance = await WebAssembly.instantiate(wasm); 114 115 Object.defineProperty(instance, 'exports', { 116 get() { 117 return { 118 _initialize() {}, 119 memory: new WebAssembly.Memory({ initial: 1 }) 120 }; 121 } 122 }); 123 124 return instance; 125 })() 126 `, { bufferSource }); 127 128 wasi.initialize(instance); 129 } 130 131 { 132 // Verify that initialize() can only be called once. 133 const wasi = new WASI({}); 134 const wasm = await WebAssembly.compile(bufferSource); 135 const instance = await WebAssembly.instantiate(wasm); 136 137 Object.defineProperty(instance, 'exports', { 138 get() { 139 return { 140 _initialize() {}, 141 memory: new WebAssembly.Memory({ initial: 1 }), 142 }; 143 }, 144 }); 145 wasi.initialize(instance); 146 assert.throws( 147 () => { wasi.initialize(instance); }, 148 { 149 code: 'ERR_WASI_ALREADY_STARTED', 150 message: /^WASI instance has already started$/, 151 }, 152 ); 153 } 154})().then(common.mustCall()); 155