1// META: global=window,dedicatedworker,jsshell 2// META: script=/wasm/jsapi/wasm-module-builder.js 3// META: script=assertions.js 4 5let functions = {}; 6setup(() => { 7 const builder = new WasmModuleBuilder(); 8 9 builder 10 .addFunction("fn", kSig_v_d) 11 .addBody([]) 12 .exportFunc(); 13 builder 14 .addFunction("fn2", kSig_v_v) 15 .addBody([]) 16 .exportFunc(); 17 18 const buffer = builder.toBuffer() 19 const module = new WebAssembly.Module(buffer); 20 const instance = new WebAssembly.Instance(module, {}); 21 functions = instance.exports; 22}); 23 24test(() => { 25 const argument = { "element": "anyfunc", "initial": 5 }; 26 const table = new WebAssembly.Table(argument); 27 assert_throws_js(TypeError, () => table.get()); 28}, "Missing arguments: get"); 29 30test(t => { 31 const thisValues = [ 32 undefined, 33 null, 34 true, 35 "", 36 Symbol(), 37 1, 38 {}, 39 WebAssembly.Table, 40 WebAssembly.Table.prototype, 41 ]; 42 43 const argument = { 44 valueOf: t.unreached_func("Should not touch the argument (valueOf)"), 45 toString: t.unreached_func("Should not touch the argument (toString)"), 46 }; 47 48 const fn = WebAssembly.Table.prototype.get; 49 50 for (const thisValue of thisValues) { 51 assert_throws_js(TypeError, () => fn.call(thisValue, argument), `this=${format_value(thisValue)}`); 52 } 53}, "Branding: get"); 54 55test(() => { 56 const argument = { "element": "anyfunc", "initial": 5 }; 57 const table = new WebAssembly.Table(argument); 58 assert_throws_js(TypeError, () => table.set()); 59}, "Missing arguments: set"); 60 61test(t => { 62 const thisValues = [ 63 undefined, 64 null, 65 true, 66 "", 67 Symbol(), 68 1, 69 {}, 70 WebAssembly.Table, 71 WebAssembly.Table.prototype, 72 ]; 73 74 const argument = { 75 valueOf: t.unreached_func("Should not touch the argument (valueOf)"), 76 toString: t.unreached_func("Should not touch the argument (toString)"), 77 }; 78 79 const fn = WebAssembly.Table.prototype.set; 80 81 for (const thisValue of thisValues) { 82 assert_throws_js(TypeError, () => fn.call(thisValue, argument, null), `this=${format_value(thisValue)}`); 83 } 84}, "Branding: set"); 85 86test(() => { 87 const argument = { "element": "anyfunc", "initial": 5 }; 88 const table = new WebAssembly.Table(argument); 89 assert_equal_to_array(table, [null, null, null, null, null]); 90 91 const {fn, fn2} = functions; 92 93 assert_equals(table.set(0, fn), undefined, "set() returns undefined."); 94 table.set(2, fn2); 95 table.set(4, fn); 96 97 assert_equal_to_array(table, [fn, null, fn2, null, fn]); 98 99 table.set(0, null); 100 assert_equal_to_array(table, [null, null, fn2, null, fn]); 101}, "Basic"); 102 103test(() => { 104 const argument = { "element": "anyfunc", "initial": 5 }; 105 const table = new WebAssembly.Table(argument); 106 assert_equal_to_array(table, [null, null, null, null, null]); 107 108 const {fn, fn2} = functions; 109 110 table.set(0, fn); 111 table.set(2, fn2); 112 table.set(4, fn); 113 114 assert_equal_to_array(table, [fn, null, fn2, null, fn]); 115 116 table.grow(4); 117 118 assert_equal_to_array(table, [fn, null, fn2, null, fn, null, null, null, null]); 119}, "Growing"); 120 121test(() => { 122 const argument = { "element": "anyfunc", "initial": 5 }; 123 const table = new WebAssembly.Table(argument); 124 assert_equal_to_array(table, [null, null, null, null, null]); 125 126 const {fn} = functions; 127 128 // -1 is the wrong type hence the type check on entry gets this 129 // before the range check does. 130 assert_throws_js(TypeError, () => table.set(-1, fn)); 131 assert_throws_js(RangeError, () => table.set(5, fn)); 132 assert_equal_to_array(table, [null, null, null, null, null]); 133}, "Setting out-of-bounds"); 134 135test(() => { 136 const argument = { "element": "anyfunc", "initial": 1 }; 137 const table = new WebAssembly.Table(argument); 138 assert_equal_to_array(table, [null]); 139 140 const invalidArguments = [ 141 undefined, 142 true, 143 false, 144 "test", 145 Symbol(), 146 7, 147 NaN, 148 {}, 149 ]; 150 for (const argument of invalidArguments) { 151 assert_throws_js(TypeError, () => table.set(0, argument), 152 `set(${format_value(argument)})`); 153 } 154 assert_equal_to_array(table, [null]); 155}, "Setting non-function"); 156 157test(() => { 158 const argument = { "element": "anyfunc", "initial": 1 }; 159 const table = new WebAssembly.Table(argument); 160 assert_equal_to_array(table, [null]); 161 162 const fn = function() {}; 163 assert_throws_js(TypeError, () => table.set(0, fn)); 164 assert_equal_to_array(table, [null]); 165}, "Setting non-wasm function"); 166 167test(() => { 168 const argument = { "element": "anyfunc", "initial": 1 }; 169 const table = new WebAssembly.Table(argument); 170 assert_equal_to_array(table, [null]); 171 172 const fn = () => {}; 173 assert_throws_js(TypeError, () => table.set(0, fn)); 174 assert_equal_to_array(table, [null]); 175}, "Setting non-wasm arrow function"); 176 177const outOfRangeValues = [ 178 undefined, 179 NaN, 180 Infinity, 181 -Infinity, 182 -1, 183 0x100000000, 184 0x1000000000, 185 "0x100000000", 186 { valueOf() { return 0x100000000; } }, 187]; 188 189for (const value of outOfRangeValues) { 190 test(() => { 191 const argument = { "element": "anyfunc", "initial": 1 }; 192 const table = new WebAssembly.Table(argument); 193 assert_throws_js(TypeError, () => table.get(value)); 194 }, `Getting out-of-range argument: ${format_value(value)}`); 195 196 test(() => { 197 const argument = { "element": "anyfunc", "initial": 1 }; 198 const table = new WebAssembly.Table(argument); 199 assert_throws_js(TypeError, () => table.set(value, null)); 200 }, `Setting out-of-range argument: ${format_value(value)}`); 201} 202 203test(() => { 204 const argument = { "element": "anyfunc", "initial": 1 }; 205 const table = new WebAssembly.Table(argument); 206 let called = 0; 207 const value = { 208 valueOf() { 209 called++; 210 return 0; 211 }, 212 }; 213 assert_throws_js(TypeError, () => table.set(value, {})); 214 assert_equals(called, 1); 215}, "Order of argument conversion"); 216 217test(() => { 218 const {fn} = functions; 219 const argument = { "element": "anyfunc", "initial": 1 }; 220 const table = new WebAssembly.Table(argument); 221 222 assert_equals(table.get(0, {}), null); 223 assert_equals(table.set(0, fn, {}), undefined); 224}, "Stray argument"); 225 226test(() => { 227 const builder = new WasmModuleBuilder(); 228 builder 229 .addFunction("fn", kSig_v_v) 230 .addBody([]) 231 .exportFunc(); 232 const bin = builder.toBuffer(); 233 const fn = new WebAssembly.Instance(new WebAssembly.Module(bin)).exports.fn; 234 235 const argument = { "element": "anyfunc", "initial": 1 }; 236 const table = new WebAssembly.Table(argument, fn); 237 238 assert_equals(table.get(0), fn); 239 table.set(0); 240 assert_equals(table.get(0), null); 241 242 table.set(0, fn); 243 assert_equals(table.get(0), fn); 244 245 assert_throws_js(TypeError, () => table.set(0, {})); 246 assert_throws_js(TypeError, () => table.set(0, 37)); 247}, "Arguments for anyfunc table set"); 248 249test(() => { 250 const testObject = {}; 251 const argument = { "element": "externref", "initial": 1 }; 252 const table = new WebAssembly.Table(argument, testObject); 253 254 assert_equals(table.get(0), testObject); 255 table.set(0); 256 assert_equals(table.get(0), undefined); 257 258 table.set(0, testObject); 259 assert_equals(table.get(0), testObject); 260 261 table.set(0, 37); 262 assert_equals(table.get(0), 37); 263}, "Arguments for externref table set"); 264