1// META: global=window,dedicatedworker,jsshell 2// META: script=/wasm/jsapi/wasm-module-builder.js 3 4let emptyModuleBinary; 5setup(() => { 6 emptyModuleBinary = new WasmModuleBuilder().toBuffer(); 7}); 8 9function assert_ModuleExportDescriptor(export_, expected) { 10 assert_equals(Object.getPrototypeOf(export_), Object.prototype, "Prototype"); 11 assert_true(Object.isExtensible(export_), "isExtensible"); 12 13 const name = Object.getOwnPropertyDescriptor(export_, "name"); 14 assert_true(name.writable, "name: writable"); 15 assert_true(name.enumerable, "name: enumerable"); 16 assert_true(name.configurable, "name: configurable"); 17 assert_equals(name.value, expected.name); 18 19 const kind = Object.getOwnPropertyDescriptor(export_, "kind"); 20 assert_true(kind.writable, "kind: writable"); 21 assert_true(kind.enumerable, "kind: enumerable"); 22 assert_true(kind.configurable, "kind: configurable"); 23 assert_equals(kind.value, expected.kind); 24} 25 26function assert_exports(exports, expected) { 27 assert_true(Array.isArray(exports), "Should be array"); 28 assert_equals(Object.getPrototypeOf(exports), Array.prototype, "Prototype"); 29 assert_true(Object.isExtensible(exports), "isExtensible"); 30 31 assert_equals(exports.length, expected.length); 32 for (let i = 0; i < expected.length; ++i) { 33 assert_ModuleExportDescriptor(exports[i], expected[i]); 34 } 35} 36 37test(() => { 38 assert_throws_js(TypeError, () => WebAssembly.Module.exports()); 39}, "Missing arguments"); 40 41test(() => { 42 const invalidArguments = [ 43 undefined, 44 null, 45 true, 46 "", 47 Symbol(), 48 1, 49 {}, 50 WebAssembly.Module, 51 WebAssembly.Module.prototype, 52 ]; 53 for (const argument of invalidArguments) { 54 assert_throws_js(TypeError, () => WebAssembly.Module.exports(argument), 55 `exports(${format_value(argument)})`); 56 } 57}, "Non-Module arguments"); 58 59test(() => { 60 const module = new WebAssembly.Module(emptyModuleBinary); 61 const fn = WebAssembly.Module.exports; 62 const thisValues = [ 63 undefined, 64 null, 65 true, 66 "", 67 Symbol(), 68 1, 69 {}, 70 WebAssembly.Module, 71 WebAssembly.Module.prototype, 72 ]; 73 for (const thisValue of thisValues) { 74 assert_array_equals(fn.call(thisValue, module), []); 75 } 76}, "Branding"); 77 78test(() => { 79 const module = new WebAssembly.Module(emptyModuleBinary); 80 const exports = WebAssembly.Module.exports(module); 81 assert_true(Array.isArray(exports)); 82}, "Return type"); 83 84test(() => { 85 const module = new WebAssembly.Module(emptyModuleBinary); 86 const exports = WebAssembly.Module.exports(module); 87 assert_exports(exports, []); 88}, "Empty module"); 89 90test(() => { 91 const module = new WebAssembly.Module(emptyModuleBinary); 92 assert_not_equals(WebAssembly.Module.exports(module), WebAssembly.Module.exports(module)); 93}, "Empty module: array caching"); 94 95test(() => { 96 const builder = new WasmModuleBuilder(); 97 98 builder 99 .addFunction("fn", kSig_v_v) 100 .addBody([]) 101 .exportFunc(); 102 builder 103 .addFunction("fn2", kSig_v_v) 104 .addBody([]) 105 .exportFunc(); 106 107 builder.setTableBounds(1); 108 builder.addExportOfKind("table", kExternalTable, 0); 109 110 builder.addGlobal(kWasmI32, true) 111 .exportAs("global") 112 .init = 7; 113 builder.addGlobal(kWasmF64, true) 114 .exportAs("global2") 115 .init = 1.2; 116 117 builder.addMemory(0, 256, true); 118 119 const buffer = builder.toBuffer() 120 const module = new WebAssembly.Module(buffer); 121 const exports = WebAssembly.Module.exports(module); 122 const expected = [ 123 { "kind": "function", "name": "fn" }, 124 { "kind": "function", "name": "fn2" }, 125 { "kind": "table", "name": "table" }, 126 { "kind": "global", "name": "global" }, 127 { "kind": "global", "name": "global2" }, 128 { "kind": "memory", "name": "memory" }, 129 ]; 130 assert_exports(exports, expected); 131}, "exports"); 132 133test(() => { 134 const builder = new WasmModuleBuilder(); 135 136 builder 137 .addFunction("", kSig_v_v) 138 .addBody([]) 139 .exportFunc(); 140 141 const buffer = builder.toBuffer() 142 const module = new WebAssembly.Module(buffer); 143 const exports = WebAssembly.Module.exports(module); 144 const expected = [ 145 { "kind": "function", "name": "" }, 146 ]; 147 assert_exports(exports, expected); 148}, "exports with empty name: function"); 149 150test(() => { 151 const builder = new WasmModuleBuilder(); 152 153 builder.setTableBounds(1); 154 builder.addExportOfKind("", kExternalTable, 0); 155 156 const buffer = builder.toBuffer() 157 const module = new WebAssembly.Module(buffer); 158 const exports = WebAssembly.Module.exports(module); 159 const expected = [ 160 { "kind": "table", "name": "" }, 161 ]; 162 assert_exports(exports, expected); 163}, "exports with empty name: table"); 164 165test(() => { 166 const builder = new WasmModuleBuilder(); 167 168 builder.addGlobal(kWasmI32, true) 169 .exportAs("") 170 .init = 7; 171 172 const buffer = builder.toBuffer() 173 const module = new WebAssembly.Module(buffer); 174 const exports = WebAssembly.Module.exports(module); 175 const expected = [ 176 { "kind": "global", "name": "" }, 177 ]; 178 assert_exports(exports, expected); 179}, "exports with empty name: global"); 180 181test(() => { 182 const module = new WebAssembly.Module(emptyModuleBinary); 183 const exports = WebAssembly.Module.exports(module, {}); 184 assert_exports(exports, []); 185}, "Stray argument"); 186