basic.js (19206B)
1 const { LinkError } = WebAssembly; 2 3 // ---------------------------------------------------------------------------- 4 // exports 5 6 var o = wasmEvalText('(module)').exports; 7 assertEq(Object.getOwnPropertyNames(o).length, 0); 8 9 var o = wasmEvalText('(module (func))').exports; 10 assertEq(Object.getOwnPropertyNames(o).length, 0); 11 12 var o = wasmEvalText('(module (func) (export "a" (func 0)))').exports; 13 var names = Object.getOwnPropertyNames(o); 14 assertEq(names.length, 1); 15 assertEq(names[0], 'a'); 16 var desc = Object.getOwnPropertyDescriptor(o, 'a'); 17 assertEq(typeof desc.value, "function"); 18 assertEq(desc.value.name, "0"); 19 assertEq(desc.value.length, 0); 20 assertEq(desc.value(), undefined); 21 assertEq(desc.writable, false); 22 assertEq(desc.enumerable, true); 23 assertEq(desc.configurable, false); 24 assertEq(desc.value(), undefined); 25 26 wasmValidateText('(module (func) (func) (export "a" (func 0)))'); 27 wasmValidateText('(module (func) (func) (export "a" (func 1)))'); 28 wasmValidateText('(module (func $a) (func $b) (export "a" (func $a)) (export "b" (func $b)))'); 29 wasmValidateText('(module (func $a) (func $b) (export "a" (func $a)) (export "b" (func $b)))'); 30 31 wasmFailValidateText('(module (func) (export "a" (func 1)))', /exported function index out of bounds/); 32 wasmFailValidateText('(module (func) (func) (export "a" (func 2)))', /exported function index out of bounds/); 33 34 var o = wasmEvalText('(module (func) (export "a" (func 0)) (export "b" (func 0)))').exports; 35 assertEq(Object.getOwnPropertyNames(o).sort().toString(), "a,b"); 36 assertEq(o.a.name, "0"); 37 assertEq(o.b.name, "0"); 38 assertEq(o.a === o.b, true); 39 40 var o = wasmEvalText('(module (func) (func) (export "a" (func 0)) (export "b" (func 1)))').exports; 41 assertEq(Object.getOwnPropertyNames(o).sort().toString(), "a,b"); 42 assertEq(o.a.name, "0"); 43 assertEq(o.b.name, "1"); 44 assertEq(o.a === o.b, false); 45 46 var o = wasmEvalText('(module (func (result i32) (i32.const 1)) (func (result i32) (i32.const 2)) (export "a" (func 0)) (export "b" (func 1)))').exports; 47 assertEq(o.a(), 1); 48 assertEq(o.b(), 2); 49 var o = wasmEvalText('(module (func (result i32) (i32.const 1)) (func (result i32) (i32.const 2)) (export "a" (func 1)) (export "b" (func 0)))').exports; 50 assertEq(o.a(), 2); 51 assertEq(o.b(), 1); 52 53 wasmFailValidateText('(module (func) (export "a" (func 0)) (export "a" (func 0)))', /duplicate export/); 54 wasmFailValidateText('(module (func) (func) (export "a" (func 0)) (export "a" (func 1)))', /duplicate export/); 55 56 // ---------------------------------------------------------------------------- 57 // signatures 58 59 wasmFailValidateText('(module (func (result i32)))', emptyStackError); 60 wasmFailValidateText('(module (func (result i32) (nop)))', emptyStackError); 61 62 wasmValidateText('(module (func (nop)))'); 63 wasmValidateText('(module (func (result i32) (i32.const 42)))'); 64 wasmValidateText('(module (func (param i32)))'); 65 wasmValidateText('(module (func (param i32) (result i32) (i32.const 42)))'); 66 wasmValidateText('(module (func (param i32) (result i32) (i32.const 42)))'); 67 wasmValidateText('(module (func (param f32)))'); 68 wasmValidateText('(module (func (param f64)))'); 69 70 wasmFullPassI64('(module (func $run (result i64) (i64.const 123)))', 123); 71 wasmFullPassI64('(module (func $run (param i64) (result i64) (local.get 0)))', 72 '0x123400007fffffff', 73 {}, 74 '(i64.const 0x123400007fffffff)'); 75 wasmFullPassI64('(module (func $run (param i64) (result i64) (i64.add (local.get 0) (i64.const 1))))', 76 '0x1234000100000000', 77 {}, 78 '(i64.const 0x12340000ffffffff)'); 79 80 // ---------------------------------------------------------------------------- 81 // imports 82 83 const noImportObj = "second argument must be an object"; 84 85 assertErrorMessage(() => wasmEvalText('(module (import "a" "b" (func)))', 1), TypeError, noImportObj); 86 assertErrorMessage(() => wasmEvalText('(module (import "a" "b" (func)))', null), TypeError, noImportObj); 87 88 const notObject = /import object field '\w*' is not an Object/; 89 const notFunction = /import object field '\w*' is not a Function/; 90 91 var code = '(module (import "a" "b" (func)))'; 92 assertErrorMessage(() => wasmEvalText(code), TypeError, noImportObj); 93 assertErrorMessage(() => wasmEvalText(code, {}), TypeError, notObject); 94 assertErrorMessage(() => wasmEvalText(code, {a:1}), TypeError, notObject); 95 assertErrorMessage(() => wasmEvalText(code, {a:{}}), LinkError, notFunction); 96 assertErrorMessage(() => wasmEvalText(code, {a:{b:1}}), LinkError, notFunction); 97 wasmEvalText(code, {a:{b:()=>{}}}); 98 99 var code = '(module (import "" "b" (func)))'; 100 wasmEvalText(code, {"":{b:()=>{}}}); 101 102 var code = '(module (import "a" "" (func)))'; 103 assertErrorMessage(() => wasmEvalText(code), TypeError, noImportObj); 104 assertErrorMessage(() => wasmEvalText(code, {}), TypeError, notObject); 105 assertErrorMessage(() => wasmEvalText(code, {a:1}), TypeError, notObject); 106 wasmEvalText(code, {a:{"":()=>{}}}); 107 108 var code = '(module (import "a" "" (func)) (import "b" "c" (func)) (import "c" "" (func)))'; 109 assertErrorMessage(() => wasmEvalText(code, {a:()=>{}, b:{c:()=>{}}, c:{}}), LinkError, notFunction); 110 wasmEvalText(code, {a:{"":()=>{}}, b:{c:()=>{}}, c:{"":()=>{}}}); 111 112 wasmEvalText('(module (import "a" "" (func (result i32))))', {a:{"":()=>{}}}); 113 wasmEvalText('(module (import "a" "" (func (result f32))))', {a:{"":()=>{}}}); 114 wasmEvalText('(module (import "a" "" (func (result f64))))', {a:{"":()=>{}}}); 115 wasmEvalText('(module (import "a" "" (func $foo (result f64))))', {a:{"":()=>{}}}); 116 117 // ---------------------------------------------------------------------------- 118 // memory 119 120 wasmValidateText('(module (memory 0))'); 121 wasmValidateText('(module (memory 1))'); 122 123 var buf = wasmEvalText('(module (memory 1) (export "memory" (memory 0)))').exports.memory.buffer; 124 assertEq(buf instanceof ArrayBuffer, true); 125 assertEq(buf.byteLength, 65536); 126 127 var obj = wasmEvalText('(module (memory 1) (func (result i32) (i32.const 42)) (func (nop)) (export "memory" (memory 0)) (export "b" (func 0)) (export "c" (func 1)))').exports; 128 assertEq(obj.memory.buffer instanceof ArrayBuffer, true); 129 assertEq(obj.b instanceof Function, true); 130 assertEq(obj.c instanceof Function, true); 131 assertEq(obj.memory.buffer.byteLength, 65536); 132 assertEq(obj.b(), 42); 133 assertEq(obj.c(), undefined); 134 135 var buf = wasmEvalText('(module (memory 1) (data (i32.const 0) "") (export "memory" (memory 0)))').exports.memory.buffer; 136 assertEq(new Uint8Array(buf)[0], 0); 137 138 var buf = wasmEvalText('(module (memory 1) (data (i32.const 65536) "") (export "memory" (memory 0)))').exports.memory.buffer; 139 assertEq(new Uint8Array(buf)[0], 0); 140 141 var buf = wasmEvalText('(module (memory 1) (data (i32.const 0) "a") (export "memory" (memory 0)))').exports.memory.buffer; 142 assertEq(new Uint8Array(buf)[0], 'a'.charCodeAt(0)); 143 144 var buf = wasmEvalText('(module (memory 1) (data (i32.const 0) "a") (data (i32.const 2) "b") (export "memory" (memory 0)))').exports.memory.buffer; 145 assertEq(new Uint8Array(buf)[0], 'a'.charCodeAt(0)); 146 assertEq(new Uint8Array(buf)[1], 0); 147 assertEq(new Uint8Array(buf)[2], 'b'.charCodeAt(0)); 148 149 var buf = wasmEvalText('(module (memory 1) (data (i32.const 65535) "c") (export "memory" (memory 0)))').exports.memory.buffer; 150 assertEq(new Uint8Array(buf)[0], 0); 151 assertEq(new Uint8Array(buf)[65535], 'c'.charCodeAt(0)); 152 153 // ---------------------------------------------------------------------------- 154 // locals 155 156 assertEq(wasmEvalText('(module (func (param i32) (result i32) (local.get 0)) (export "" (func 0)))').exports[""](), 0); 157 assertEq(wasmEvalText('(module (func (param i32) (result i32) (local.get 0)) (export "" (func 0)))').exports[""](42), 42); 158 assertEq(wasmEvalText('(module (func (param i32) (param i32) (result i32) (local.get 0)) (export "" (func 0)))').exports[""](42, 43), 42); 159 assertEq(wasmEvalText('(module (func (param i32) (param i32) (result i32) (local.get 1)) (export "" (func 0)))').exports[""](42, 43), 43); 160 161 wasmFailValidateText('(module (func (local.get 0)))', /(local.get index out of range)|(local index out of bounds)/); 162 wasmFailValidateText('(module (func (result f32) (local i32) (local.get 0)))', mismatchError("i32", "f32")); 163 wasmFailValidateText('(module (func (result i32) (local f32) (local.get 0)))', mismatchError("f32", "i32")); 164 wasmFailValidateText('(module (func (param i32) (result f32) (local f32) (local.get 0)))', mismatchError("i32", "f32")); 165 wasmFailValidateText('(module (func (param i32) (result i32) (local f32) (local.get 1)))', mismatchError("f32", "i32")); 166 167 wasmValidateText('(module (func (local i32)))'); 168 wasmValidateText('(module (func (local i32) (local f32)))'); 169 170 wasmFullPass('(module (func (result i32) (local i32) (local.get 0)) (export "run" (func 0)))', 0); 171 wasmFullPass('(module (func (param i32) (result i32) (local f32) (local.get 0)) (export "run" (func 0)))', 0); 172 wasmFullPass('(module (func (param i32) (result f32) (local f32) (local.get 1)) (export "run" (func 0)))', 0); 173 174 wasmFailValidateText('(module (func (local.set 0 (i32.const 0))))', /(local.set index out of range)|(local index out of bounds)/); 175 wasmFailValidateText('(module (func (local f32) (local.set 0 (i32.const 0))))', mismatchError("i32", "f32")); 176 wasmFailValidateText('(module (func (local f32) (local.set 0 (nop))))', emptyStackError); 177 wasmFailValidateText('(module (func (local i32) (local f32) (local.set 0 (local.get 1))))', mismatchError("f32", "i32")); 178 wasmFailValidateText('(module (func (local i32) (local f32) (local.set 1 (local.get 0))))', mismatchError("i32", "f32")); 179 180 wasmValidateText('(module (func (local i32) (local.set 0 (i32.const 0))))'); 181 wasmValidateText('(module (func (local i32) (local f32) (local.set 0 (local.get 0))))'); 182 wasmValidateText('(module (func (local i32) (local f32) (local.set 1 (local.get 1))))'); 183 184 wasmFullPass('(module (func (result i32) (local i32) (local.tee 0 (i32.const 42))) (export "run" (func 0)))', 42); 185 wasmFullPass('(module (func (result i32) (local i32) (local.tee 0 (local.get 0))) (export "run" (func 0)))', 0); 186 187 wasmFullPass('(module (func (param $a i32) (result i32) (local.get $a)) (export "run" (func 0)))', 0); 188 wasmFullPass('(module (func (param $a i32) (result i32) (local $b i32) (block (result i32) (local.set $b (local.get $a)) (local.get $b))) (export "run" (func 0)))', 42, {}, 42); 189 190 wasmValidateText('(module (func (local i32) (local $a f32) (local.set 0 (i32.const 1)) (local.set $a (f32.const nan))))'); 191 192 // ---------------------------------------------------------------------------- 193 // blocks 194 195 wasmFullPass('(module (func (block )) (export "run" (func 0)))', undefined); 196 197 wasmFailValidateText('(module (func (result i32) (block )))', emptyStackError); 198 wasmFailValidateText('(module (func (result i32) (block (block ))))', emptyStackError); 199 wasmFailValidateText('(module (func (local i32) (local.set 0 (block ))))', emptyStackError); 200 201 wasmFullPass('(module (func (block (block ))) (export "run" (func 0)))', undefined); 202 wasmFullPass('(module (func (result i32) (block (result i32) (i32.const 42))) (export "run" (func 0)))', 42); 203 wasmFullPass('(module (func (result i32) (block (result i32) (block (result i32) (i32.const 42)))) (export "run" (func 0)))', 42); 204 wasmFailValidateText('(module (func (result f32) (block (result i32) (i32.const 0))))', mismatchError("i32", "f32")); 205 206 wasmFullPass('(module (func (result i32) (block (result i32) (drop (i32.const 13)) (block (result i32) (i32.const 42)))) (export "run" (func 0)))', 42); 207 wasmFailValidateText('(module (func (param f32) (result f32) (block (result i32) (drop (local.get 0)) (i32.const 0))))', mismatchError("i32", "f32")); 208 209 wasmFullPass('(module (func (result i32) (local i32) (local.set 0 (i32.const 42)) (local.get 0)) (export "run" (func 0)))', 42); 210 211 // ---------------------------------------------------------------------------- 212 // calls 213 214 wasmFailValidateText('(module (func (nop)) (func (call 0 (i32.const 0))))', unusedValuesError); 215 216 wasmFailValidateText('(module (func (param i32) (nop)) (func (call 0)))', emptyStackError); 217 wasmFailValidateText('(module (func (param f32) (nop)) (func (call 0 (i32.const 0))))', mismatchError("i32", "f32")); 218 wasmFailValidateText('(module (func (nop)) (func (call 3)))', /(callee index out of range)|(function index out of bounds)/); 219 220 wasmValidateText('(module (func (nop)) (func (call 0)))'); 221 wasmValidateText('(module (func (param i32) (nop)) (func (call 0 (i32.const 0))))'); 222 223 wasmFullPass('(module (func (result i32) (i32.const 42)) (func (result i32) (call 0)) (export "run" (func 1)))', 42); 224 assertThrowsInstanceOf(() => wasmEvalText('(module (func (call 0)) (export "" (func 0)))').exports[""](), InternalError); 225 assertThrowsInstanceOf(() => wasmEvalText('(module (func (call 1)) (func (call 0)) (export "" (func 0)))').exports[""](), InternalError); 226 227 wasmValidateText('(module (func (param i32 f32)) (func (call 0 (i32.const 0) (f32.const nan))))'); 228 wasmFailValidateText('(module (func (param i32 f32)) (func (call 0 (i32.const 0) (i32.const 0))))', mismatchError("i32", "f32")); 229 230 wasmFailValidateText('(module (import "a" "" (func)) (func (call 0 (i32.const 0))))', unusedValuesError); 231 wasmFailValidateText('(module (import "a" "" (func (param i32))) (func (call 0)))', emptyStackError); 232 wasmFailValidateText('(module (import "a" "" (func (param f32))) (func (call 0 (i32.const 0))))', mismatchError("i32", "f32")); 233 234 assertErrorMessage(() => wasmEvalText('(module (import "a" "" (func)) (func (call 1)))'), TypeError, noImportObj); 235 wasmEvalText('(module (import "" "a" (func)) (func (call 0)))', {"":{a:()=>{}}}); 236 wasmEvalText('(module (import "" "a" (func (param i32))) (func (call 0 (i32.const 0))))', {"":{a:()=>{}}}); 237 238 function checkF32CallImport(v) { 239 wasmFullPass('(module (import "" "a" (func (result f32))) (func (result f32) (call 0)) (export "run" (func 1)))', 240 Math.fround(v), 241 {"":{a:()=>{ return v; }}}); 242 wasmFullPass('(module (import "" "a" (func (param f32))) (func (param f32) (call 0 (local.get 0))) (export "run" (func 1)))', 243 undefined, 244 {"":{a:x=>{ assertEq(Math.fround(v), x); }}}, 245 v); 246 } 247 checkF32CallImport(13.37); 248 checkF32CallImport(NaN); 249 checkF32CallImport(-Infinity); 250 checkF32CallImport(-0); 251 checkF32CallImport(Math.pow(2, 32) - 1); 252 253 var counter = 0; 254 var f = wasmEvalText('(module (import "" "inc" (func)) (func (call 0)) (export "" (func 1)))', {"":{inc:()=>counter++}}).exports[""]; 255 var g = wasmEvalText('(module (import "" "f" (func)) (func (block (call 0) (call 0))) (export "" (func 1)))', {"":{f}}).exports[""]; 256 f(); 257 assertEq(counter, 1); 258 g(); 259 assertEq(counter, 3); 260 261 var f = wasmEvalText('(module (import "" "callf" (func)) (func (call 0)) (export "" (func 1)))', {"":{callf:()=>f()}}).exports[""]; 262 assertThrowsInstanceOf(() => f(), InternalError); 263 264 var f = wasmEvalText('(module (import "" "callg" (func)) (func (call 0)) (export "" (func 1)))', {"":{callg:()=>g()}}).exports[""]; 265 var g = wasmEvalText('(module (import "" "callf" (func)) (func (call 0)) (export "" (func 1)))', {"":{callf:()=>f()}}).exports[""]; 266 assertThrowsInstanceOf(() => f(), InternalError); 267 268 var code = '(module (import "" "one" (func (result i32))) (import "" "two" (func (result i32))) (func (result i32) (i32.const 3)) (func (result i32) (i32.const 4)) (func (result i32) BODY) (export "run" (func 4)))'; 269 var imports = {"":{one:()=>1, two:()=>2}}; 270 wasmFullPass(code.replace('BODY', '(call 0)'), 1, imports); 271 wasmFullPass(code.replace('BODY', '(call 1)'), 2, imports); 272 wasmFullPass(code.replace('BODY', '(call 2)'), 3, imports); 273 wasmFullPass(code.replace('BODY', '(call 3)'), 4, imports); 274 275 wasmFullPass(`(module (import "" "evalcx" (func (param i32) (result i32))) (func (result i32) (call 0 (i32.const 0))) (export "run" (func 1)))`, 0, {"":{evalcx}}); 276 277 if (typeof evaluate === 'function') 278 evaluate(`new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary('(module)'))) `, { fileName: null }); 279 280 wasmFailValidateText(`(module (type $t (func)) (func (call_indirect (type $t) (i32.const 0))))`, /(can't call_indirect without a table)|(unknown table)/); 281 282 var {v2i, i2i, i2v} = wasmEvalText(`(module 283 (type (func (result i32))) 284 (type (func (param i32) (result i32))) 285 (type (func (param i32))) 286 (func (type 0) (i32.const 13)) 287 (func (type 0) (i32.const 42)) 288 (func (type 1) (i32.add (local.get 0) (i32.const 1))) 289 (func (type 1) (i32.add (local.get 0) (i32.const 2))) 290 (func (type 1) (i32.add (local.get 0) (i32.const 3))) 291 (func (type 1) (i32.add (local.get 0) (i32.const 4))) 292 (table funcref (elem 0 1 2 3 4 5)) 293 (func (param i32) (result i32) (call_indirect (type 0) (local.get 0))) 294 (func (param i32) (param i32) (result i32) (call_indirect (type 1) (local.get 1) (local.get 0))) 295 (func (param i32) (call_indirect (type 2) (i32.const 0) (local.get 0))) 296 (export "v2i" (func 6)) 297 (export "i2i" (func 7)) 298 (export "i2v" (func 8)) 299 )`).exports; 300 301 const signatureMismatch = /indirect call signature mismatch/; 302 303 assertEq(v2i(0), 13); 304 assertEq(v2i(1), 42); 305 assertErrorMessage(() => v2i(2), Error, signatureMismatch); 306 assertErrorMessage(() => v2i(3), Error, signatureMismatch); 307 assertErrorMessage(() => v2i(4), Error, signatureMismatch); 308 assertErrorMessage(() => v2i(5), Error, signatureMismatch); 309 310 assertErrorMessage(() => i2i(0), Error, signatureMismatch); 311 assertErrorMessage(() => i2i(1), Error, signatureMismatch); 312 assertEq(i2i(2, 100), 101); 313 assertEq(i2i(3, 100), 102); 314 assertEq(i2i(4, 100), 103); 315 assertEq(i2i(5, 100), 104); 316 317 assertErrorMessage(() => i2v(0), Error, signatureMismatch); 318 assertErrorMessage(() => i2v(1), Error, signatureMismatch); 319 assertErrorMessage(() => i2v(2), Error, signatureMismatch); 320 assertErrorMessage(() => i2v(3), Error, signatureMismatch); 321 assertErrorMessage(() => i2v(4), Error, signatureMismatch); 322 assertErrorMessage(() => i2v(5), Error, signatureMismatch); 323 324 { 325 enableGeckoProfiling(); 326 327 var stack; 328 wasmFullPass( 329 `(module 330 (type $v2v (func)) 331 (import "" "f" (func $foo)) 332 (func $a (call $foo)) 333 (func $b (result i32) (i32.const 0)) 334 (table funcref (elem $a $b)) 335 (func $bar (call_indirect (type $v2v) (i32.const 0))) 336 (export "run" (func $bar)) 337 )`, 338 undefined, 339 {"":{f:() => { stack = new Error().stack }}} 340 ); 341 342 disableGeckoProfiling(); 343 344 var inner = stack.indexOf("wasm-function[1]"); 345 var outer = stack.indexOf("wasm-function[3]"); 346 assertEq(inner === -1, false); 347 assertEq(outer === -1, false); 348 assertEq(inner < outer, true); 349 } 350 351 for (bad of [6, 7, 100, Math.pow(2,31)-1, Math.pow(2,31), Math.pow(2,31)+1, Math.pow(2,32)-2, Math.pow(2,32)-1]) { 352 assertThrowsInstanceOf(() => v2i(bad), WebAssembly.RuntimeError); 353 assertThrowsInstanceOf(() => i2i(bad, 0), WebAssembly.RuntimeError); 354 assertThrowsInstanceOf(() => i2v(bad, 0), WebAssembly.RuntimeError); 355 } 356 357 wasmValidateText('(module (func $foo (nop)) (func (call $foo)))'); 358 wasmValidateText('(module (func (call $foo)) (func $foo (nop)))'); 359 wasmValidateText('(module (import "" "a" (func $bar)) (func (call $bar)) (func $foo (nop)))'); 360 361 var exp = wasmEvalText(`(module (func (export "f")))`).exports; 362 assertEq(Object.isFrozen(exp), true);