tor-browser

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

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);