tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

import-export.js (32264B)


      1 const { Module, Instance, Memory, Table, LinkError, RuntimeError } = WebAssembly;
      2 
      3 const mem1Page = new Memory({initial:1});
      4 const mem1PageMax1 = new Memory({initial:1, maximum: 1});
      5 const mem2Page = new Memory({initial:2});
      6 const mem2PageMax2 = new Memory({initial:2, maximum: 2});
      7 const mem2PageMax3 = new Memory({initial:2, maximum: 3});
      8 const mem2PageMax4 = new Memory({initial:2, maximum: 4});
      9 const mem3Page = new Memory({initial:3});
     10 const mem3PageMax3 = new Memory({initial:3, maximum: 3});
     11 const mem4Page = new Memory({initial:4});
     12 const mem4PageMax4 = new Memory({initial:4, maximum: 4});
     13 const tab1Elem = new Table({initial:1, element:"anyfunc"});
     14 const tab2Elem = new Table({initial:2, element:"anyfunc"});
     15 const tab3Elem = new Table({initial:3, element:"anyfunc"});
     16 const tab4Elem = new Table({initial:4, element:"anyfunc"});
     17 
     18 function assertSegmentFitError(f) {
     19    assertErrorMessage(f, RuntimeError, /out of bounds/);
     20 }
     21 
     22 const m1 = new Module(wasmTextToBinary('(module (import "foo" "bar" (func)) (import "baz" "quux" (func)))'));
     23 assertErrorMessage(() => new Instance(m1), TypeError, /second argument must be an object/);
     24 assertErrorMessage(() => new Instance(m1, {foo:null}), TypeError, /import object field 'foo' is not an Object/);
     25 assertErrorMessage(() => new Instance(m1, {foo:{bar:{}}}), LinkError, /import object field 'bar' is not a Function/);
     26 assertErrorMessage(() => new Instance(m1, {foo:{bar:()=>{}}, baz:null}), TypeError, /import object field 'baz' is not an Object/);
     27 assertErrorMessage(() => new Instance(m1, {foo:{bar:()=>{}}, baz:{}}), LinkError, /import object field 'quux' is not a Function/);
     28 assertEq(new Instance(m1, {foo:{bar:()=>{}}, baz:{quux:()=>{}}}) instanceof Instance, true);
     29 
     30 const m2 = new Module(wasmTextToBinary('(module (import "x" "y" (memory 2 3)))'));
     31 assertErrorMessage(() => new Instance(m2), TypeError, /second argument must be an object/);
     32 assertErrorMessage(() => new Instance(m2, {x:null}), TypeError, /import object field 'x' is not an Object/);
     33 assertErrorMessage(() => new Instance(m2, {x:{y:{}}}), LinkError, /import object field 'y' is not a Memory/);
     34 assertErrorMessage(() => new Instance(m2, {x:{y:mem1Page}}), LinkError, /imported Memory with incompatible size/);
     35 assertErrorMessage(() => new Instance(m2, {x:{y:mem1PageMax1}}), LinkError, /imported Memory with incompatible size/);
     36 assertErrorMessage(() => new Instance(m2, {x:{y:mem4Page}}), LinkError, /imported Memory with incompatible size/);
     37 assertErrorMessage(() => new Instance(m2, {x:{y:mem4PageMax4}}), LinkError, /imported Memory with incompatible size/);
     38 assertErrorMessage(() => new Instance(m2, {x:{y:mem2Page}}), LinkError, /imported Memory with incompatible maximum size/);
     39 assertEq(new Instance(m2, {x:{y:mem2PageMax2}}) instanceof Instance, true);
     40 assertErrorMessage(() => new Instance(m2, {x:{y:mem3Page}}), LinkError, /imported Memory with incompatible maximum size/);
     41 assertEq(new Instance(m2, {x:{y:mem3PageMax3}}) instanceof Instance, true);
     42 assertEq(new Instance(m2, {x:{y:mem2PageMax3}}) instanceof Instance, true);
     43 assertErrorMessage(() => new Instance(m2, {x:{y:mem2PageMax4}}), LinkError, /imported Memory with incompatible maximum size/);
     44 
     45 const m3 = new Module(wasmTextToBinary('(module (import "foo" "bar" (memory 1 1)) (import "baz" "quux" (func)))'));
     46 assertErrorMessage(() => new Instance(m3), TypeError, /second argument must be an object/);
     47 assertErrorMessage(() => new Instance(m3, {foo:null}), TypeError, /import object field 'foo' is not an Object/);
     48 assertErrorMessage(() => new Instance(m3, {foo:{bar:{}}}), LinkError, /import object field 'bar' is not a Memory/);
     49 assertErrorMessage(() => new Instance(m3, {foo:{bar:mem1Page}, baz:null}), TypeError, /import object field 'baz' is not an Object/);
     50 assertErrorMessage(() => new Instance(m3, {foo:{bar:mem1Page}, baz:{quux:mem1Page}}), LinkError, /import object field 'quux' is not a Function/);
     51 assertErrorMessage(() => new Instance(m3, {foo:{bar:mem1Page}, baz:{quux:()=>{}}}), LinkError, /imported Memory with incompatible maximum size/);
     52 assertEq(new Instance(m3, {foo:{bar:mem1PageMax1}, baz:{quux:()=>{}}}) instanceof Instance, true);
     53 
     54 const m4 = new Module(wasmTextToBinary('(module (import "baz" "quux" (func)) (import "foo" "bar" (memory 1 1)))'));
     55 assertErrorMessage(() => new Instance(m4), TypeError, /second argument must be an object/);
     56 assertErrorMessage(() => new Instance(m4, {baz:null}), TypeError, /import object field 'baz' is not an Object/);
     57 assertErrorMessage(() => new Instance(m4, {baz:{quux:{}}}), LinkError, /import object field 'quux' is not a Function/);
     58 assertErrorMessage(() => new Instance(m4, {baz:{quux:()=>{}}, foo:null}), TypeError, /import object field 'foo' is not an Object/);
     59 assertErrorMessage(() => new Instance(m4, {baz:{quux:()=>{}}, foo:{bar:()=>{}}}), LinkError, /import object field 'bar' is not a Memory/);
     60 assertErrorMessage(() => new Instance(m4, {baz:{quux:()=>{}}, foo:{bar:mem1Page}}), LinkError, /imported Memory with incompatible maximum size/);
     61 assertEq(new Instance(m3, {baz:{quux:()=>{}}, foo:{bar:mem1PageMax1}}) instanceof Instance, true);
     62 
     63 const m5 = new Module(wasmTextToBinary('(module (import "a" "b" (memory 2)))'));
     64 assertErrorMessage(() => new Instance(m5, {a:{b:mem1Page}}), LinkError, /imported Memory with incompatible size/);
     65 assertEq(new Instance(m5, {a:{b:mem2Page}}) instanceof Instance, true);
     66 assertEq(new Instance(m5, {a:{b:mem3Page}}) instanceof Instance, true);
     67 assertEq(new Instance(m5, {a:{b:mem4Page}}) instanceof Instance, true);
     68 
     69 const m6 = new Module(wasmTextToBinary('(module (import "a" "b" (table 2 funcref)))'));
     70 assertErrorMessage(() => new Instance(m6, {a:{b:tab1Elem}}), LinkError, /imported Table with incompatible size/);
     71 assertEq(new Instance(m6, {a:{b:tab2Elem}}) instanceof Instance, true);
     72 assertEq(new Instance(m6, {a:{b:tab3Elem}}) instanceof Instance, true);
     73 assertEq(new Instance(m6, {a:{b:tab4Elem}}) instanceof Instance, true);
     74 
     75 const m7 = new Module(wasmTextToBinary('(module (import "a" "b" (table 2 3 funcref)))'));
     76 assertErrorMessage(() => new Instance(m7, {a:{b:tab1Elem}}), LinkError, /imported Table with incompatible size/);
     77 assertErrorMessage(() => new Instance(m7, {a:{b:tab2Elem}}), LinkError, /imported Table with incompatible maximum size/);
     78 assertErrorMessage(() => new Instance(m7, {a:{b:tab3Elem}}), LinkError, /imported Table with incompatible maximum size/);
     79 assertErrorMessage(() => new Instance(m7, {a:{b:tab4Elem}}), LinkError, /imported Table with incompatible size/);
     80 
     81 wasmFailValidateText('(module (memory 2 1))', /maximum length 1 is less than initial length 2/);
     82 wasmFailValidateText('(module (import "a" "b" (memory 2 1)))', /maximum length 1 is less than initial length 2/);
     83 wasmFailValidateText('(module (table 2 1 funcref))', /maximum length 1 is less than initial length 2/);
     84 wasmFailValidateText('(module (import "a" "b" (table 2 1 funcref)))', /maximum length 1 is less than initial length 2/);
     85 
     86 // Import wasm-wasm type mismatch
     87 
     88 var e = wasmEvalText('(module (func $i2v (param i32)) (export "i2v" (func $i2v)) (func $f2v (param f32)) (export "f2v" (func $f2v)))').exports;
     89 var i2vm = new Module(wasmTextToBinary('(module (import "a" "b" (func (param i32))))'));
     90 var f2vm = new Module(wasmTextToBinary('(module (import "a" "b" (func (param f32))))'));
     91 assertEq(new Instance(i2vm, {a:{b:e.i2v}}) instanceof Instance, true);
     92 assertErrorMessage(() => new Instance(i2vm, {a:{b:e.f2v}}), LinkError, /imported function 'a.b' signature mismatch/);
     93 assertErrorMessage(() => new Instance(f2vm, {a:{b:e.i2v}}), LinkError, /imported function 'a.b' signature mismatch/);
     94 assertEq(new Instance(f2vm, {a:{b:e.f2v}}) instanceof Instance, true);
     95 var l2vm = new Module(wasmTextToBinary('(module (import "x" "y" (memory 1)) (import "c" "d" (func (param i64))))'));
     96 assertErrorMessage(() => new Instance(l2vm, {x:{y:mem1Page}, c:{d:e.i2v}}), LinkError, /imported function 'c.d' signature mismatch/);
     97 
     98 // Import order:
     99 
    100 var arr = [];
    101 var importObj = {
    102    get foo() { arr.push("foo") },
    103    get baz() { arr.push("bad") },
    104 };
    105 assertErrorMessage(() => new Instance(m1, importObj), TypeError, /import object field 'foo' is not an Object/);
    106 assertEq(arr.join(), "foo");
    107 
    108 var arr = [];
    109 var importObj = {
    110    get foo() {
    111        arr.push("foo");
    112        return { get bar() { arr.push("bar"); return null } }
    113    },
    114    get baz() { arr.push("bad") },
    115 };
    116 assertErrorMessage(() => new Instance(m1, importObj), LinkError, /import object field 'bar' is not a Function/);
    117 assertEq(arr.join(), "foo,bar");
    118 
    119 var arr = [];
    120 var importObj = {
    121    get foo() {
    122        arr.push("foo");
    123        return { get bar() { arr.push("bar"); return () => arr.push("bad") } }
    124    },
    125    get baz() {
    126        arr.push("baz");
    127        return { get quux() { arr.push("quux"); return () => arr.push("bad") } }
    128    }
    129 };
    130 assertEq(new Instance(m1, importObj) instanceof Instance, true);
    131 assertEq(arr.join(), "foo,bar,baz,quux");
    132 
    133 var arr = [];
    134 var importObj = {
    135    get foo() {
    136        arr.push("foo");
    137        return { get bar() { arr.push("bar"); return new WebAssembly.Memory({initial:1, maximum:1}) } }
    138    },
    139    get baz() {
    140        arr.push("baz");
    141        return { get quux() { arr.push("quux"); return () => arr.push("bad") } }
    142    }
    143 };
    144 assertEq(new Instance(m3, importObj) instanceof Instance, true);
    145 assertEq(arr.join(), "foo,bar,baz,quux");
    146 arr = [];
    147 assertEq(new Instance(m4, importObj) instanceof Instance, true);
    148 assertEq(arr.join(), "baz,quux,foo,bar");
    149 
    150 // Export key order:
    151 
    152 var code = wasmTextToBinary('(module)');
    153 var e = new Instance(new Module(code)).exports;
    154 assertEq(Object.keys(e).length, 0);
    155 
    156 var code = wasmTextToBinary('(module (func) (export "foo" (func 0)))');
    157 var e = new Instance(new Module(code)).exports;
    158 assertEq(Object.keys(e).join(), "foo");
    159 assertEq(e.foo(), undefined);
    160 
    161 var code = wasmTextToBinary('(module (func) (export "foo" (func 0)) (export "bar" (func 0)))');
    162 var e = new Instance(new Module(code)).exports;
    163 assertEq(Object.keys(e).join(), "foo,bar");
    164 assertEq(e.foo(), undefined);
    165 assertEq(e.bar(), undefined);
    166 assertEq(e.foo, e.bar);
    167 
    168 var code = wasmTextToBinary('(module (memory 1 1) (export "memory" (memory 0)))');
    169 var e = new Instance(new Module(code)).exports;
    170 assertEq(Object.keys(e).join(), "memory");
    171 
    172 var code = wasmTextToBinary('(module (memory 1 1) (export "foo" (memory 0)) (export "bar" (memory 0)))');
    173 var e = new Instance(new Module(code)).exports;
    174 assertEq(Object.keys(e).join(), "foo,bar");
    175 assertEq(e.foo, e.bar);
    176 assertEq(e.foo instanceof Memory, true);
    177 assertEq(e.foo.buffer.byteLength, 64*1024);
    178 
    179 var code = wasmTextToBinary('(module (memory 1 1) (func) (export "foo" (func 0)) (export "bar" (memory 0)))');
    180 var e = new Instance(new Module(code)).exports;
    181 assertEq(Object.keys(e).join(), "foo,bar");
    182 assertEq(e.foo(), undefined);
    183 assertEq(e.bar instanceof Memory, true);
    184 assertEq(e.bar instanceof Memory, true);
    185 assertEq(e.bar.buffer.byteLength, 64*1024);
    186 
    187 var code = wasmTextToBinary('(module (memory 1 1) (func) (export "bar" (memory 0)) (export "foo" (func 0)))');
    188 var e = new Instance(new Module(code)).exports;
    189 assertEq(Object.keys(e).join(), "bar,foo");
    190 assertEq(e.foo(), undefined);
    191 assertEq(e.bar.buffer.byteLength, 64*1024);
    192 
    193 var code = wasmTextToBinary('(module (memory 1 1) (export "" (memory 0)))');
    194 var e = new Instance(new Module(code)).exports;
    195 assertEq(Object.keys(e).length, 1);
    196 assertEq(String(Object.keys(e)), "");
    197 assertEq(e[""] instanceof Memory, true);
    198 
    199 var code = wasmTextToBinary('(module (table 0 funcref) (export "tbl" (table 0)))');
    200 var e = new Instance(new Module(code)).exports;
    201 assertEq(Object.keys(e).join(), "tbl");
    202 assertEq(e.tbl instanceof Table, true);
    203 assertEq(e.tbl.length, 0);
    204 
    205 var code = wasmTextToBinary('(module (table 2 funcref) (export "t1" (table 0)) (export "t2" (table 0)))');
    206 var e = new Instance(new Module(code)).exports;
    207 assertEq(Object.keys(e).join(), "t1,t2");
    208 assertEq(e.t1 instanceof Table, true);
    209 assertEq(e.t2 instanceof Table, true);
    210 assertEq(e.t1, e.t2);
    211 assertEq(e.t1.length, 2);
    212 
    213 var code = wasmTextToBinary('(module (table 2 funcref) (memory 1 1) (func) (export "t" (table 0)) (export "m" (memory 0)) (export "f" (func 0)))');
    214 var e = new Instance(new Module(code)).exports;
    215 assertEq(Object.keys(e).join(), "t,m,f");
    216 assertEq(e.f(), undefined);
    217 assertEq(e.t instanceof Table, true);
    218 assertEq(e.m instanceof Memory, true);
    219 assertEq(e.t.length, 2);
    220 
    221 var code = wasmTextToBinary('(module (table 1 funcref) (memory 1 1) (func) (export "m" (memory 0)) (export "f" (func 0)) (export "t" (table 0)))');
    222 var e = new Instance(new Module(code)).exports;
    223 assertEq(Object.keys(e).join(), "m,f,t");
    224 assertEq(e.f(), undefined);
    225 assertEq(e.t instanceof Table, true);
    226 assertEq(e.m instanceof Memory, true);
    227 +assertEq(e.t.length, 1);
    228 
    229 var code = wasmTextToBinary('(module (table 0 funcref) (export "" (table 0)))');
    230 var e = new Instance(new Module(code)).exports;
    231 assertEq(Object.keys(e).length, 1);
    232 assertEq(String(Object.keys(e)), "");
    233 assertEq(e[""] instanceof Table, true);
    234 +assertEq(e[""].length, 0);
    235 
    236 // Table export function identity
    237 
    238 var text = `(module
    239    (func $f (result i32) (i32.const 1))
    240    (func $g (result i32) (i32.const 2))
    241    (func $h (result i32) (i32.const 3))
    242    (table 4 funcref)
    243    (elem (i32.const 0) $f)
    244    (elem (i32.const 2) $g)
    245    (export "f1" (func $f))
    246    (export "tbl1" (table 0))
    247    (export "f2" (func $f))
    248    (export "tbl2" (table 0))
    249    (export "f3" (func $h))
    250    (func (export "run") (result i32) (call_indirect (type 0) (i32.const 2)))
    251 )`;
    252 wasmFullPass(text, 2);
    253 var e = new Instance(new Module(wasmTextToBinary(text))).exports;
    254 assertEq(String(Object.keys(e)), "f1,tbl1,f2,tbl2,f3,run");
    255 assertEq(e.f1, e.f2);
    256 assertEq(e.f1(), 1);
    257 assertEq(e.f3(), 3);
    258 assertEq(e.tbl1, e.tbl2);
    259 assertEq(e.tbl1.get(0), e.f1);
    260 assertEq(e.tbl1.get(0), e.tbl1.get(0));
    261 assertEq(e.tbl1.get(0)(), 1);
    262 assertEq(e.tbl1.get(1), null);
    263 assertEq(e.tbl1.get(2), e.tbl1.get(2));
    264 assertEq(e.tbl1.get(2)(), 2);
    265 assertEq(e.tbl1.get(3), null);
    266 assertErrorMessage(() => e.tbl1.get(4), RangeError, /bad Table get address/);
    267 assertEq(e.tbl1.get(1), null);
    268 e.tbl1.set(1, e.f3);
    269 assertEq(e.tbl1.get(1), e.f3);
    270 e.tbl1.set(1, null);
    271 assertEq(e.tbl1.get(1), null);
    272 e.tbl1.set(3, e.f1);
    273 assertEq(e.tbl1.get(0), e.tbl1.get(3));
    274 
    275 // JS re-exports
    276 
    277 var args;
    278 var m = new Module(wasmTextToBinary(`(module
    279    (export "a" (func $a)) (import "" "a" (func $a (param f32)))
    280    (export "b" (func $b)) (import "" "b" (func $b (param i32) (result i32)))
    281    (export "c" (func $c)) (import "" "c" (func $c (result i32)))
    282    (export "d" (func $d)) (import "" "d" (func $d))
    283 )`));
    284 var js = function() { args = arguments; return 42 }
    285 var e = new Instance(m, {"":{a:js, b:js, c:js, d:js}}).exports;
    286 assertEq(e.a.length, 1);
    287 assertEq(e.a(), undefined);
    288 assertEq(args.length, 1);
    289 assertEq(args[0], NaN);
    290 assertEq(e.a(99.5), undefined);
    291 assertEq(args.length, 1);
    292 assertEq(args[0], 99.5);
    293 assertEq(e.b.length, 1);
    294 assertEq(e.b(), 42);
    295 assertEq(args.length, 1);
    296 assertEq(args[0], 0);
    297 assertEq(e.b(99.5), 42);
    298 assertEq(args.length, 1);
    299 assertEq(args[0], 99);
    300 assertEq(e.c.length, 0);
    301 assertEq(e.c(), 42);
    302 assertEq(args.length, 0);
    303 assertEq(e.c(99), 42);
    304 assertEq(args.length, 0);
    305 assertEq(e.d.length, 0);
    306 assertEq(e.d(), undefined);
    307 assertEq(args.length, 0);
    308 assertEq(e.d(99), undefined);
    309 assertEq(args.length, 0);
    310 
    311 // Re-exports and Identity:
    312 
    313 var code = wasmTextToBinary('(module (import "a" "b" (memory 1 1)) (export "foo" (memory 0)) (export "bar" (memory 0)))');
    314 var mem = new Memory({initial:1, maximum:1});
    315 var e = new Instance(new Module(code), {a:{b:mem}}).exports;
    316 assertEq(mem, e.foo);
    317 assertEq(mem, e.bar);
    318 
    319 var code = wasmTextToBinary('(module (import "a" "b" (table 1 1 funcref)) (export "foo" (table 0)) (export "bar" (table 0)))');
    320 var tbl = new Table({initial:1, maximum:1, element:"anyfunc"});
    321 var e = new Instance(new Module(code), {a:{b:tbl}}).exports;
    322 assertEq(tbl, e.foo);
    323 assertEq(tbl, e.bar);
    324 
    325 var code = wasmTextToBinary('(module (import "a" "b" (table 2 2 funcref)) (func $foo) (elem (i32.const 0) $foo) (export "foo" (func $foo)))');
    326 var tbl = new Table({initial:2, maximum:2, element:"anyfunc"});
    327 var e1 = new Instance(new Module(code), {a:{b:tbl}}).exports;
    328 assertEq(e1.foo, tbl.get(0));
    329 tbl.set(1, e1.foo);
    330 assertEq(e1.foo, tbl.get(1));
    331 var e2 = new Instance(new Module(code), {a:{b:tbl}}).exports;
    332 assertEq(e2.foo, tbl.get(0));
    333 assertEq(e1.foo, tbl.get(1));
    334 assertEq(tbl.get(0) === e1.foo, false);
    335 assertEq(e1.foo === e2.foo, false);
    336 
    337 var m = new Module(wasmTextToBinary(`(module
    338    (import "" "foo" (func $foo (result i32)))
    339    (import "" "bar" (func $bar (result i32)))
    340    (table 3 funcref)
    341    (func $baz (result i32) (i32.const 13))
    342    (elem (i32.const 0) $foo $bar $baz)
    343    (export "foo" (func $foo))
    344    (export "bar" (func $bar))
    345    (export "baz" (func $baz))
    346    (export "tbl" (table 0))
    347 )`));
    348 var jsFun = () => 83;
    349 var wasmFun = new Instance(new Module(wasmTextToBinary('(module (func (result i32) (i32.const 42)) (export "foo" (func 0)))'))).exports.foo;
    350 var e1 = new Instance(m, {"":{foo:jsFun, bar:wasmFun}}).exports;
    351 assertEq(jsFun === e1.foo, false);
    352 assertEq(wasmFun, e1.bar);
    353 assertEq(e1.foo, e1.tbl.get(0));
    354 assertEq(e1.bar, e1.tbl.get(1));
    355 assertEq(e1.baz, e1.tbl.get(2));
    356 assertEq(e1.tbl.get(0)(), 83);
    357 assertEq(e1.tbl.get(1)(), 42);
    358 assertEq(e1.tbl.get(2)(), 13);
    359 var e2 = new Instance(m, {"":{foo:jsFun, bar:jsFun}}).exports;
    360 assertEq(jsFun === e2.foo, false);
    361 assertEq(jsFun === e2.bar, false);
    362 assertEq(e2.foo === e1.foo, false);
    363 assertEq(e2.bar === e1.bar, false);
    364 assertEq(e2.baz === e1.baz, false);
    365 assertEq(e2.tbl === e1.tbl, false);
    366 assertEq(e2.foo, e2.tbl.get(0));
    367 assertEq(e2.bar, e2.tbl.get(1));
    368 assertEq(e2.baz, e2.tbl.get(2));
    369 var e3 = new Instance(m, {"":{foo:wasmFun, bar:wasmFun}}).exports;
    370 assertEq(wasmFun, e3.foo);
    371 assertEq(wasmFun, e3.bar);
    372 assertEq(e3.baz === e3.foo, false);
    373 assertEq(e3.baz === e1.baz, false);
    374 assertEq(e3.tbl === e1.tbl, false);
    375 assertEq(e3.foo, e3.tbl.get(0));
    376 assertEq(e3.bar, e3.tbl.get(1));
    377 assertEq(e3.baz, e3.tbl.get(2));
    378 var e4 = new Instance(m, {"":{foo:e1.foo, bar:e1.foo}}).exports;
    379 assertEq(e4.foo, e1.foo);
    380 assertEq(e4.bar, e1.foo);
    381 assertEq(e4.baz === e4.foo, false);
    382 assertEq(e4.baz === e1.baz, false);
    383 assertEq(e4.tbl === e1.tbl, false);
    384 assertEq(e4.foo, e4.tbl.get(0));
    385 assertEq(e4.foo, e4.tbl.get(1));
    386 assertEq(e4.baz, e4.tbl.get(2));
    387 
    388 // i64 is fully allowed for imported wasm functions
    389 
    390 var code1 = wasmTextToBinary('(module (func $exp (param i64) (result i64) (i64.add (local.get 0) (i64.const 10))) (export "exp" (func $exp)))');
    391 var e1 = new Instance(new Module(code1)).exports;
    392 var code2 = wasmTextToBinary('(module (import "a" "b" (func $i (param i64) (result i64))) (func $f (result i32) (i32.wrap_i64 (call $i (i64.const 42)))) (export "f" (func $f)))');
    393 var e2 = new Instance(new Module(code2), {a:{b:e1.exp}}).exports;
    394 assertEq(e2.f(), 52);
    395 
    396 // Non-existent export errors
    397 
    398 wasmFailValidateText('(module (export "a" (func 0)))', /exported function index out of bounds/);
    399 wasmFailValidateText('(module (export "a" (global 0)))', /exported global index out of bounds/);
    400 wasmFailValidateText('(module (export "a" (memory 0)))', /exported memory index out of bounds/);
    401 wasmFailValidateText('(module (export "a" (table 0)))', /exported table index out of bounds/);
    402 
    403 // Data segments on imports
    404 
    405 var m = new Module(wasmTextToBinary(`
    406    (module
    407        (import "a" "b" (memory 1 1))
    408        (data (i32.const 0) "\\0a\\0b")
    409        (data (i32.const 100) "\\0c\\0d")
    410        (func $get (param $p i32) (result i32)
    411            (i32.load8_u (local.get $p)))
    412        (export "get" (func $get)))
    413 `));
    414 var mem = new Memory({initial:1, maximum:1});
    415 var {get} = new Instance(m, {a:{b:mem}}).exports;
    416 assertEq(get(0), 0xa);
    417 assertEq(get(1), 0xb);
    418 assertEq(get(2), 0x0);
    419 assertEq(get(100), 0xc);
    420 assertEq(get(101), 0xd);
    421 assertEq(get(102), 0x0);
    422 var i8 = new Uint8Array(mem.buffer);
    423 assertEq(i8[0], 0xa);
    424 assertEq(i8[1], 0xb);
    425 assertEq(i8[2], 0x0);
    426 assertEq(i8[100], 0xc);
    427 assertEq(i8[101], 0xd);
    428 assertEq(i8[102], 0x0);
    429 
    430 // Data segments with imported offsets
    431 
    432 var m = new Module(wasmTextToBinary(`
    433    (module
    434        (import "glob" "a" (global i32))
    435        (memory 1)
    436        (data (global.get 0) "\\0a\\0b"))
    437 `));
    438 assertEq(new Instance(m, {glob:{a:0}}) instanceof Instance, true);
    439 assertEq(new Instance(m, {glob:{a:(64*1024 - 2)}}) instanceof Instance, true);
    440 assertSegmentFitError(() => new Instance(m, {glob:{a:(64*1024 - 1)}}));
    441 assertSegmentFitError(() => new Instance(m, {glob:{a:64*1024}}));
    442 
    443 var m = new Module(wasmTextToBinary(`
    444    (module
    445        (memory 1)
    446        (data (i32.const 0x10001) "\\0a\\0b"))
    447 `));
    448 assertSegmentFitError(() => new Instance(m));
    449 
    450 var m = new Module(wasmTextToBinary(`
    451    (module
    452        (memory 0)
    453        (data (i32.const 0x10001) ""))
    454 `));
    455 assertSegmentFitError(() => new Instance(m));
    456 
    457 // Errors during segment initialization do not have observable effects
    458 // and are checked against the actual memory/table length, not the declared
    459 // initial length.
    460 
    461 var m = new Module(wasmTextToBinary(`
    462    (module
    463        (import "a" "mem" (memory 1))
    464        (import "a" "tbl" (table 1 funcref))
    465        (import "a" "memOff" (global $memOff i32))
    466        (import "a" "tblOff" (global $tblOff i32))
    467        (func $f)
    468        (func $g)
    469        (data (i32.const 0) "\\01")
    470        (elem (i32.const 0) $f)
    471        (data (global.get $memOff) "\\02")
    472        (elem (global.get $tblOff) $g)
    473        (export "f" (func $f))
    474        (export "g" (func $g)))
    475 `));
    476 
    477 // Active segments are applied in order (this is observable if they overlap).
    478 //
    479 // Without bulk memory, all range checking for tables and memory happens before
    480 // any writes happen, and any OOB will force no writing to happen at all.
    481 //
    482 // With bulk memory, active segments are applied first for tables and then for
    483 // memories.  Bounds checking happens for each byte or table element written.
    484 // The first OOB aborts the initialization process, leaving written data in
    485 // place.  Notably, any OOB in table initialization will prevent any memory
    486 // initialization from happening at all.
    487 
    488 var npages = 2;
    489 var mem = new Memory({initial:npages});
    490 var mem8 = new Uint8Array(mem.buffer);
    491 var tbl = new Table({initial:2, element:"anyfunc"});
    492 
    493 assertSegmentFitError(() => new Instance(m, {a:{mem, tbl, memOff:1, tblOff:2}}));
    494 // The first active element segment is applied, but the second active
    495 // element segment is completely OOB.
    496 assertEq(typeof tbl.get(0), "function");
    497 assertEq(tbl.get(1), null);
    498 
    499 assertEq(mem8[0], 0);
    500 assertEq(mem8[1], 0);
    501 
    502 tbl.set(0, null);
    503 tbl.set(1, null);
    504 
    505 assertSegmentFitError(() => new Instance(m, {a:{mem, tbl, memOff:npages*64*1024, tblOff:1}}));
    506 // The first and second active element segments are applied fully.  The
    507 // first active data segment applies, but the second one is completely OOB.
    508 assertEq(typeof tbl.get(0), "function");
    509 assertEq(typeof tbl.get(1), "function");
    510 assertEq(mem8[0], 1);
    511 
    512 tbl.set(0, null);
    513 tbl.set(1, null);
    514 mem8[0] = 0;
    515 
    516 // Both element and data segments apply successfully without OOB
    517 
    518 var i = new Instance(m, {a:{mem, tbl, memOff:npages*64*1024-1, tblOff:1}});
    519 assertEq(mem8[0], 1);
    520 assertEq(mem8[npages*64*1024-1], 2);
    521 assertEq(tbl.get(0), i.exports.f);
    522 assertEq(tbl.get(1), i.exports.g);
    523 
    524 // Element segment doesn't apply and prevents subsequent elem segment and
    525 // data segment from being applied.
    526 
    527 var m = new Module(wasmTextToBinary(
    528    `(module
    529       (import "" "mem" (memory 1))
    530       (import "" "tbl" (table 3 funcref))
    531       (elem (i32.const 1) $f $g $h) ;; fails after $f and $g
    532       (elem (i32.const 0) $f)       ;; is not applied
    533       (data (i32.const 0) "\\01")   ;; is not applied
    534       (func $f)
    535       (func $g)
    536       (func $h))`));
    537 var mem = new Memory({initial:1});
    538 var tbl = new Table({initial:3, element:"anyfunc"});
    539 assertSegmentFitError(() => new Instance(m, {"":{mem, tbl}}));
    540 assertEq(tbl.get(0), null);
    541 assertEq(tbl.get(1), null);
    542 assertEq(tbl.get(2), null);
    543 var v = new Uint8Array(mem.buffer);
    544 assertEq(v[0], 0);
    545 
    546 // Data segment doesn't apply and prevents subsequent data segment from
    547 // being applied.
    548 
    549 var m = new Module(wasmTextToBinary(
    550    `(module
    551       (import "" "mem" (memory 1))
    552       (data (i32.const 65534) "\\01\\02\\03") ;; fails after 1 and 2
    553       (data (i32.const 0) "\\04")             ;; is not applied
    554     )`));
    555 var mem = new Memory({initial:1});
    556 assertSegmentFitError(() => new Instance(m, {"":{mem}}));
    557 var v = new Uint8Array(mem.buffer);
    558 assertEq(v[65534], 0);
    559 assertEq(v[65535], 0);
    560 assertEq(v[0], 0);
    561 
    562 // Elem segments on imported tables
    563 
    564 var m = new Module(wasmTextToBinary(`
    565    (module
    566        (import "a" "b" (table 10 funcref))
    567        (elem (i32.const 0) $one $two)
    568        (elem (i32.const 3) $three $four)
    569        (func $one (result i32) (i32.const 1))
    570        (func $two (result i32) (i32.const 2))
    571        (func $three (result i32) (i32.const 3))
    572        (func $four (result i32) (i32.const 4)))
    573 `));
    574 var tbl = new Table({initial:10, element:"anyfunc"});
    575 new Instance(m, {a:{b:tbl}});
    576 assertEq(tbl.get(0)(), 1);
    577 assertEq(tbl.get(1)(), 2);
    578 assertEq(tbl.get(2), null);
    579 assertEq(tbl.get(3)(), 3);
    580 assertEq(tbl.get(4)(), 4);
    581 for (var i = 5; i < 10; i++)
    582    assertEq(tbl.get(i), null);
    583 
    584 var m = new Module(wasmTextToBinary(`
    585    (module
    586        (func $their1 (import "" "func") (result i32))
    587        (func $their2 (import "" "func"))
    588        (table (import "" "table") 4 funcref)
    589        (func $my (result i32) i32.const 13)
    590        (elem (i32.const 1) $my)
    591        (elem (i32.const 2) $their1)
    592        (elem (i32.const 3) $their2)
    593    )
    594 `));
    595 var tbl = new Table({initial:4, element:"anyfunc"});
    596 var f = () => 42;
    597 new Instance(m, { "": { table: tbl, func: f} });
    598 assertEq(tbl.get(0), null);
    599 assertEq(tbl.get(1)(), 13);
    600 assertEq(tbl.get(2)(), 42);
    601 assertEq(tbl.get(3)(), undefined);
    602 
    603 // Cross-instance calls
    604 
    605 var i1 = new Instance(new Module(wasmTextToBinary(`(module (func) (func (param i32) (result i32) (i32.add (local.get 0) (i32.const 1))) (func) (export "f" (func 1)))`)));
    606 var i2 = new Instance(new Module(wasmTextToBinary(`(module (import "a" "b" (func $imp (param i32) (result i32))) (func $g (result i32) (call $imp (i32.const 13))) (export "g" (func $g)))`)), {a:{b:i1.exports.f}});
    607 assertEq(i2.exports.g(), 14);
    608 
    609 var i1 = new Instance(new Module(wasmTextToBinary(`(module
    610    (memory 1 1)
    611    (data (i32.const 0) "\\42")
    612    (func $f (result i32) (i32.load (i32.const 0)))
    613    (export "f" (func $f))
    614 )`)));
    615 var i2 = new Instance(new Module(wasmTextToBinary(`(module
    616    (import "a" "b" (func $imp (result i32)))
    617    (memory 1 1)
    618    (data (i32.const 0) "\\13")
    619    (table 2 2 funcref)
    620    (elem (i32.const 0) $imp $def)
    621    (func $def (result i32) (i32.load (i32.const 0)))
    622    (type $v2i (func (result i32)))
    623    (func $call (param i32) (result i32) (call_indirect (type $v2i) (local.get 0)))
    624    (export "call" (func $call))
    625 )`)), {a:{b:i1.exports.f}});
    626 assertEq(i2.exports.call(0), 0x42);
    627 assertEq(i2.exports.call(1), 0x13);
    628 
    629 var m = new Module(wasmTextToBinary(`(module
    630    (import "a" "val" (global $val i32))
    631    (import "a" "next" (func $next (result i32)))
    632    (memory 1)
    633    (func $start (i32.store (i32.const 0) (global.get $val)))
    634    (start $start)
    635    (func $call (result i32)
    636        (i32.add
    637            (global.get $val)
    638            (i32.add
    639                (i32.load (i32.const 0))
    640                (call $next))))
    641    (export "call" (func $call))
    642 )`));
    643 var e = {call:() => 1000};
    644 for (var i = 0; i < 10; i++)
    645    e = new Instance(m, {a:{val:i, next:e.call}}).exports;
    646 assertEq(e.call(), 1090);
    647 
    648 (function testImportJitExit() {
    649    let options = getJitCompilerOptions();
    650    if (!options['baseline.enable'])
    651        return;
    652 
    653    let baselineTrigger = options['baseline.warmup.trigger'];
    654 
    655    let valueToConvert = 0;
    656    function ffi(n) { if (n == 1337) { return valueToConvert }; return 42; }
    657 
    658    function sum(a, b, c) {
    659        if (a === 1337)
    660            return valueToConvert;
    661        return (a|0) + (b|0) + (c|0) | 0;
    662    }
    663 
    664    // Baseline compile ffis.
    665    for (let i = baselineTrigger + 1; i --> 0;) {
    666        ffi(i);
    667        sum((i%2)?i:undefined,
    668            (i%3)?i:undefined,
    669            (i%4)?i:undefined);
    670    }
    671 
    672    let imports = {
    673        a: {
    674            ffi,
    675            sum
    676        }
    677    };
    678 
    679    i = wasmEvalText(`(module
    680        (import "a" "ffi" (func $ffi (param i32) (result i32)))
    681 
    682        (import "a" "sum" (func $missingOneArg (param i32) (param i32) (result i32)))
    683        (import "a" "sum" (func $missingTwoArgs (param i32) (result i32)))
    684        (import "a" "sum" (func $missingThreeArgs (result i32)))
    685 
    686        (func (export "foo") (param i32) (result i32)
    687         local.get 0
    688         call $ffi
    689        )
    690 
    691        (func (export "missThree") (result i32)
    692         call $missingThreeArgs
    693        )
    694 
    695        (func (export "missTwo") (param i32) (result i32)
    696         local.get 0
    697         call $missingTwoArgs
    698        )
    699 
    700        (func (export "missOne") (param i32) (param i32) (result i32)
    701         local.get 0
    702         local.get 1
    703         call $missingOneArg
    704        )
    705    )`, imports).exports;
    706 
    707    // Enable the jit exit for each JS callee.
    708    assertEq(i.foo(0), 42);
    709 
    710    assertEq(i.missThree(), 0);
    711    assertEq(i.missTwo(42), 42);
    712    assertEq(i.missOne(13, 37), 50);
    713 
    714    // Test the jit exit under normal conditions.
    715    assertEq(i.foo(0), 42);
    716    assertEq(i.foo(1337), 0);
    717 
    718    // Test the arguments rectifier.
    719    assertEq(i.missThree(), 0);
    720    assertEq(i.missTwo(-1), -1);
    721    assertEq(i.missOne(23, 10), 33);
    722 
    723    // Test OOL coercion.
    724    valueToConvert = 2**31;
    725    assertEq(i.foo(1337), -(2**31));
    726 
    727    // Test OOL error path.
    728    valueToConvert = { valueOf() { throw new Error('make ffi great again'); } }
    729    assertErrorMessage(() => i.foo(1337), Error, "make ffi great again");
    730 
    731    valueToConvert = { toString() { throw new Error('a FFI to believe in'); } }
    732    assertErrorMessage(() => i.foo(1337), Error, "a FFI to believe in");
    733 
    734    // Test the error path in the arguments rectifier.
    735    assertErrorMessage(() => i.missTwo(1337), Error, "a FFI to believe in");
    736 })();
    737 
    738 (function testCrossRealmImport() {
    739    var g = newGlobal({sameCompartmentAs: this});
    740    g.evaluate("function f1() { assertCorrectRealm(); return 123; }");
    741    g.mem = new Memory({initial:8});
    742 
    743    // The memory.size builtin asserts cx->realm matches instance->realm so
    744    // we call it here.
    745    var i1 = new Instance(new Module(wasmTextToBinary(`
    746        (module
    747            (import "a" "f1" (func $imp1 (result i32)))
    748            (import "a" "f2" (func $imp2 (result i32)))
    749            (import "a" "m" (memory 1))
    750            (func $test (result i32)
    751                (i32.add
    752                    (i32.add
    753                        (i32.add (memory.size) (call $imp1))
    754                        (memory.size))
    755                    (call $imp2)))
    756            (export "impstub" (func $imp1))
    757            (export "test" (func $test)))
    758    `)), {a:{m:g.mem, f1:g.f1, f2:g.Math.abs}});
    759 
    760    for (var i = 0; i < 20; i++) {
    761        assertEq(i1.exports.impstub(), 123);
    762        assertEq(i1.exports.test(), 139);
    763    }
    764 
    765    // Inter-module/inter-realm wasm => wasm calls.
    766    var src = `
    767        (module
    768            (import "a" "othertest" (func $imp (result i32)))
    769            (import "a" "m" (memory 1))
    770            (func (result i32) (i32.add (call $imp) (memory.size)))
    771            (export "test" (func 1)))
    772    `;
    773    g.i1 = i1;
    774    g.evaluate("i2 = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(`" + src + "`)), {a:{m:mem,othertest:i1.exports.test}})");
    775    for (var i = 0; i < 20; i++)
    776        assertEq(g.i2.exports.test(), 147);
    777 })();
    778 
    779 // The name presented in toString and as the fn.name property is the index of the
    780 // function within the module.  See bug 1714505 for analysis.
    781 
    782 var ins = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(`
    783 (module
    784  (func (export "myfunc") (result i32)
    785    (i32.const 1337))
    786  (func $hi (result i32)
    787    (i32.const 3))
    788  (func $abracadabra (export "bletch") (result i32)
    789    (i32.const -1)))`)))
    790 assertEq(String(ins.exports.myfunc), "function 0() {\n    [native code]\n}")
    791 assertEq(ins.exports.myfunc.name, "0");
    792 assertEq(String(ins.exports.bletch), "function 2() {\n    [native code]\n}")
    793 assertEq(ins.exports.bletch.name, "2")