tor-browser

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

bigint.js (10882B)


      1 // Used to ensure tests will trigger Wasm Jit stub code.
      2 var threshold = 2 * getJitCompilerOptions()["ion.warmup.trigger"] + 10;
      3 function testWithJit(f) {
      4  for (var i = 0; i < threshold; i++) {
      5    f();
      6  }
      7 }
      8 
      9 function testRet() {
     10  var f = wasmEvalText(`(module
     11    (func (export "f") (result i64) (i64.const 66))
     12  )`).exports.f;
     13 
     14  testWithJit(() => {
     15    assertEq(typeof f(), "bigint", "should return a bigint");
     16    assertEq(f(), 66n, "should return the correct value");
     17  });
     18 }
     19 
     20 function testId() {
     21  var exports = wasmEvalText(`(module
     22    (func (export "f") (param i64 i64) (result i64)
     23      (local.get 0)
     24    )
     25    (func (export "f2") (param i64 i64) (result i64)
     26      (local.get 1)
     27    )
     28  )`).exports;
     29  var f = exports.f;
     30  var f2 = exports.f2;
     31 
     32  testWithJit(() => {
     33    assertEq(f(0n, 1n), 0n);
     34    assertEq(f(-0n, 1n), -0n);
     35    assertEq(f(123n, 1n), 123n);
     36    assertEq(f(-123n, 1n), -123n);
     37    assertEq(f(2n ** 63n, 1n), -(2n ** 63n));
     38    assertEq(f(2n ** 64n + 123n, 1n), 123n);
     39    assertEq(f("5", 1n), 5n);
     40    assertEq(f(true, 1n), 1n);
     41    assertEq(f(false, 1n), 0n);
     42    assertEq(f({ toString() { return "5"; }, }, 1n), 5n);
     43    assertEq(f({ valueOf() { return 5n; }, }, 1n), 5n);
     44 
     45    assertEq(f2(1n, 0n), 0n);
     46    assertEq(f2(1n, -0n), -0n);
     47    assertEq(f2(1n, 123n), 123n);
     48    assertEq(f2(1n, -123n), -123n);
     49    assertEq(f2(1n, 2n ** 63n), -(2n ** 63n));
     50    assertEq(f2(1n, 2n ** 64n + 123n), 123n);
     51    assertEq(f2(1n, "5"), 5n);
     52    assertEq(f2(1n, true), 1n);
     53    assertEq(f2(1n, false), 0n);
     54    assertEq(f2(1n, { toString() { return "5"; }, }), 5n);
     55    assertEq(f2(1n, { valueOf() { return 5n; }, }), 5n);
     56  });
     57 }
     58 
     59 function testNonBigIntArgs() {
     60  var f = wasmEvalText(`(module
     61    (func (export "f") (param i64) (result i64)
     62      (local.get 0)
     63    )
     64  )`).exports.f;
     65 
     66  assertErrorMessage(() => f(5), TypeError, "can't convert 5 to BigInt");
     67  assertErrorMessage(() => f({ valueOf() { return 5; }, }),
     68                     TypeError,
     69                     "can't convert 5 to BigInt");
     70  assertErrorMessage(() => f(5.3), TypeError, "can't convert 5.3 to BigInt");
     71  assertErrorMessage(() => f(), TypeError, "can't convert undefined to BigInt");
     72  assertErrorMessage(
     73    () => f(undefined),
     74    TypeError,
     75    "can't convert undefined to BigInt"
     76  );
     77  assertErrorMessage(() => f(null), TypeError, "can't convert null to BigInt");
     78  assertErrorMessage(
     79    () => f(Symbol("foo")),
     80    TypeError,
     81    'can\'t convert Symbol("foo") to BigInt'
     82  );
     83  assertErrorMessage(() => f({}), SyntaxError, "invalid BigInt syntax");
     84  assertErrorMessage(() => f({ valueof() { return "foo"; }, }),
     85                     SyntaxError,
     86                     "invalid BigInt syntax");
     87  assertErrorMessage(() => f("x"), SyntaxError, "invalid BigInt syntax");
     88 }
     89 
     90 function testIdPlus() {
     91  var f = wasmEvalText(`(module
     92    (func (export "f") (param i64) (result i64)
     93      (i64.const 8)
     94      (local.get 0)
     95      (i64.add)
     96    )
     97  )`).exports.f;
     98 
     99  testWithJit(() => {
    100    assertEq(f(0n), 0n + 8n);
    101    assertEq(f(147n), 147n + 8n);
    102  });
    103 }
    104 
    105 // Test functions with many parameters to stress ABI cases. We want to test
    106 // spilled arguments both under and over the Ion call inlining limit.
    107 function testManyArgs() {
    108  var f1 = wasmEvalText(`(module
    109    (func (export "f")
    110      (param i64 i64 i64 i64 i64 i64 i64 i64)
    111      (result i64)
    112      (local.get 0)
    113      (local.get 1)
    114      (local.get 2)
    115      (local.get 3)
    116      (local.get 4)
    117      (local.get 5)
    118      (local.get 6)
    119      (local.get 7)
    120      (i64.add)
    121      (i64.add)
    122      (i64.add)
    123      (i64.add)
    124      (i64.add)
    125      (i64.add)
    126      (i64.add)
    127    )
    128  )`).exports.f;
    129 
    130  var f2 = wasmEvalText(`(module
    131    (func (export "f")
    132      (param i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64)
    133      (result i64)
    134      (local.get 0)
    135      (local.get 1)
    136      (local.get 2)
    137      (local.get 3)
    138      (local.get 4)
    139      (local.get 5)
    140      (local.get 6)
    141      (local.get 7)
    142      (local.get 8)
    143      (local.get 9)
    144      (local.get 10)
    145      (local.get 11)
    146      (local.get 12)
    147      (local.get 13)
    148      (i64.add)
    149      (i64.add)
    150      (i64.add)
    151      (i64.add)
    152      (i64.add)
    153      (i64.add)
    154      (i64.add)
    155      (i64.add)
    156      (i64.add)
    157      (i64.add)
    158      (i64.add)
    159      (i64.add)
    160      (i64.add)
    161    )
    162  )`).exports.f;
    163 
    164  testWithJit(() => {
    165    assertEq(f1(1n, 1n, 1n, 1n, 1n, 1n, 1n, 1n), 8n);
    166    assertEq(f2(1n, 1n, 1n, 1n, 1n, 1n, 1n, 1n, 1n, 1n, 1n, 1n, 1n, 1n), 14n);
    167  });
    168 }
    169 
    170 // Test import and re-export.
    171 function testImportExport() {
    172  var f1 = wasmEvalText(
    173    `(module
    174      (import "i64" "func" (func (param i64)))
    175      (export "f" (func 0))
    176    )`,
    177    {
    178      i64: {
    179        func(b) {
    180          assertEq(b, 42n);
    181        },
    182      },
    183    }
    184  ).exports.f;
    185 
    186  var f2 = wasmEvalText(
    187    `(module
    188      (import "i64" "func" (func (param i64) (result i64)))
    189      (export "f" (func 0))
    190    )`,
    191    {
    192      i64: {
    193        func(n) {
    194          return n + 1n;
    195        },
    196      },
    197    }
    198  ).exports.f;
    199 
    200  var f3 = wasmEvalText(
    201    `(module
    202      (import "" "i64" (func $i64 (param i64) (result i64)))
    203      (func (export "f") (param i64) (result i64)
    204        (local.get 0)
    205        (call $i64))
    206    )`,
    207    {
    208      "": {
    209        i64: n => {
    210          return n + 1n;
    211        },
    212      },
    213    }
    214  ).exports.f;
    215 
    216  var f4 = wasmEvalText(
    217    `(module
    218      (import "i64" "func" (func (result i64)))
    219      (export "f" (func 0))
    220    )`,
    221    { i64: { func() {} } }
    222  ).exports.f;
    223 
    224  testWithJit(() => {
    225    assertEq(f1(42n), undefined);
    226    assertEq(f2(42n), 43n);
    227    assertEq(f3(42n), 43n);
    228    assertErrorMessage(() => f4(42), TypeError, "can't convert undefined to BigInt");
    229  });
    230 }
    231 
    232 // Test that a mixture of I64 and other argument types works.
    233 function testMixedArgs() {
    234  var f = wasmEvalText(`(module
    235    (func (export "f")
    236      (param i64 f32 f64 i32 i64)
    237      (result i64)
    238      (local.get 1)
    239      (i64.trunc_f32_s)
    240      (local.get 2)
    241      (i64.trunc_f64_s)
    242      (i64.add)
    243      (local.get 3)
    244      (i64.extend_i32_u)
    245      (i64.add)
    246      (local.get 0)
    247      (i64.add)
    248      (local.get 4)
    249      (i64.add)
    250    )
    251  )`).exports.f;
    252 
    253  testWithJit(() => {
    254    assertEq(f(1n, 1.3, 1.7, 1, 1n), 5n);
    255  });
    256 }
    257 
    258 function testGlobalImport() {
    259  var exports = wasmEvalText(
    260    `(module
    261      (import "g" "a" (global $a i64))
    262      (import "g" "b" (global $b i64))
    263      (import "g" "c" (global $c i64))
    264 
    265      (export "a" (global $a))
    266      (export "b" (global $b))
    267      (export "c" (global $c))
    268    )`,
    269    { g: { a: 1n, b: 2n ** 63n, c: -100n } }
    270  ).exports;
    271 
    272  testWithJit(() => {
    273    assertEq(exports.a.value, 1n);
    274    assertEq(exports.b.value, -(2n ** 63n));
    275    assertEq(exports.c.value, -100n);
    276  });
    277 }
    278 
    279 function testMutableGlobalImport() {
    280  var exports = wasmEvalText(
    281    `(module
    282      (import "g" "a" (global $a (mut i64)))
    283      (import "g" "b" (global $b (mut i64)))
    284 
    285      (export "a" (global $a))
    286      (export "b" (global $b))
    287    )`,
    288    {
    289      g: {
    290        a: new WebAssembly.Global({ value: "i64", mutable: true }, 1n),
    291        b: new WebAssembly.Global({ value: "i64", mutable: true }, "2"),
    292      },
    293    }
    294  ).exports;
    295 
    296  testWithJit(() => {
    297    assertEq(exports.a.value, 1n);
    298    assertEq(exports.b.value, 2n);
    299  });
    300 }
    301 
    302 function testMutableGlobalImportLiteral() {
    303  assertErrorMessage(
    304    () =>
    305      wasmEvalText(
    306        `(module
    307          (import "g" "a" (global $a (mut i64)))
    308        )`,
    309        { g: { a: 1n } }
    310      ),
    311    WebAssembly.LinkError,
    312    "imported global mutability mismatch"
    313  );
    314 }
    315 
    316 function testGlobalBadImportLiteral() {
    317  assertErrorMessage(
    318    () =>
    319      wasmEvalText(
    320        `(module
    321          (import "g" "a" (global $a i64))
    322          (export "a" (global $a))
    323        )`,
    324        { g: { a: 1 } }
    325      ),
    326    WebAssembly.LinkError,
    327    "import object field 'a' is not a BigInt"
    328  );
    329 
    330  assertErrorMessage(
    331    () =>
    332      wasmEvalText(
    333        `(module
    334          (import "g" "a" (global $a i64))
    335          (export "a" (global $a))
    336        )`,
    337        { g: { a: "foo" } }
    338      ),
    339    WebAssembly.LinkError,
    340    "import object field 'a' is not a BigInt"
    341  );
    342 }
    343 
    344 // This exercises error code paths that were added due to BigInt/I64
    345 // conversion, though the test does not directly deal with I64 types.
    346 function testGlobalBadImportNumber() {
    347  assertErrorMessage(
    348    () =>
    349      wasmEvalText(
    350        `(module
    351          (import "g" "a" (global $a i32))
    352          (export "a" (global $a))
    353        )`,
    354        { g: { a: 1n } }
    355      ),
    356    WebAssembly.LinkError,
    357    "import object field 'a' is not a Number"
    358  );
    359 
    360  assertErrorMessage(
    361    () =>
    362      wasmEvalText(
    363        `(module
    364          (import "g" "a" (global $a i32))
    365          (export "a" (global $a))
    366        )`,
    367        { g: { a: "foo" } }
    368      ),
    369    WebAssembly.LinkError,
    370    "import object field 'a' is not a Number"
    371  );
    372 }
    373 
    374 function testI64Global() {
    375  var global = new WebAssembly.Global({ value: "i64", mutable: true });
    376 
    377  assertEq(global.value, 0n); // initial value
    378 
    379  global.value = 123n;
    380  assertEq(global.value, 123n);
    381 
    382  global.value = 2n ** 63n;
    383  assertEq(global.value, -(2n ** 63n));
    384 
    385  global.value = "123";
    386  assertEq(global.value, 123n);
    387 }
    388 
    389 function testI64GlobalValueOf() {
    390  var argument = { value: "i64" };
    391 
    392  // as literal
    393  var global = new WebAssembly.Global(argument, {
    394    valueOf() {
    395      return 123n;
    396    },
    397  });
    398  assertEq(global.value, 123n);
    399 
    400  // as string
    401  var global2 = new WebAssembly.Global(argument, {
    402    valueOf() {
    403      return "123";
    404    },
    405  });
    406  assertEq(global.value, 123n);
    407 }
    408 
    409 function testGlobalI64ValueWrongType() {
    410  var argument = { value: "i64" };
    411  assertErrorMessage(
    412    () => new WebAssembly.Global(argument, 666),
    413    TypeError,
    414    "can't convert 666 to BigInt"
    415  );
    416  assertErrorMessage(
    417    () => new WebAssembly.Global(argument, "foo"),
    418    SyntaxError,
    419    "invalid BigInt syntax"
    420  );
    421  assertErrorMessage(
    422    () =>
    423      new WebAssembly.Global(argument, {
    424        valueOf() {
    425          return 5;
    426        },
    427      }),
    428    TypeError,
    429    "can't convert 5 to BigInt"
    430  );
    431 }
    432 
    433 function testGlobalI64SetWrongType() {
    434  var global = new WebAssembly.Global({ value: "i64", mutable: true });
    435  assertErrorMessage(() => (global.value = 1), TypeError, "can't convert 1 to BigInt");
    436  assertErrorMessage(
    437    () => (global.value = "foo"),
    438    SyntaxError,
    439    "invalid BigInt syntax"
    440  );
    441  assertErrorMessage(
    442    () =>
    443      (global.value = {
    444        valueOf() {
    445          return 5;
    446        },
    447      }),
    448    TypeError,
    449    "can't convert 5 to BigInt"
    450  );
    451 }
    452 
    453 testRet();
    454 testId();
    455 testIdPlus();
    456 testNonBigIntArgs();
    457 testManyArgs();
    458 testImportExport();
    459 testMixedArgs();
    460 testGlobalImport();
    461 testMutableGlobalImport();
    462 testMutableGlobalImportLiteral();
    463 testGlobalBadImportLiteral();
    464 testGlobalBadImportNumber();
    465 testI64Global();
    466 testI64GlobalValueOf();
    467 testGlobalI64ValueWrongType();
    468 testGlobalI64SetWrongType();