tor-browser

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

js-api.js (12134B)


      1 // Tests for wasm exception proposal JS API features.
      2 
      3 load(libdir + "eqArrayHelper.js");
      4 
      5 // WebAssembly.Tag tests.
      6 assertErrorMessage(
      7  () => WebAssembly.Tag(),
      8  TypeError,
      9  /calling a builtin Tag constructor without new is forbidden/
     10 );
     11 
     12 assertErrorMessage(
     13  () => new WebAssembly.Tag(),
     14  TypeError,
     15  /At least 1 argument required/
     16 );
     17 
     18 assertErrorMessage(
     19  () => new WebAssembly.Tag(3),
     20  TypeError,
     21  /first argument must be a tag descriptor/
     22 );
     23 
     24 assertErrorMessage(
     25  () => new WebAssembly.Tag({ parameters: ["foobar"] }),
     26  TypeError,
     27  /bad value type/
     28 );
     29 
     30 new WebAssembly.Tag({ parameters: [] });
     31 new WebAssembly.Tag({ parameters: ["i32"] });
     32 new WebAssembly.Tag({ parameters: ["i32", "externref"] });
     33 
     34 wasmEvalText(`(module (import "m" "e" (tag)))`, {
     35  m: { e: new WebAssembly.Tag({ parameters: [] }) },
     36 });
     37 
     38 wasmEvalText(`(module (import "m" "e" (tag (param i32))))`, {
     39  m: { e: new WebAssembly.Tag({ parameters: ["i32"] }) },
     40 });
     41 
     42 wasmEvalText(`(module (import "m" "e" (tag (param i32 i64))))`, {
     43  m: { e: new WebAssembly.Tag({ parameters: ["i32", "i64"] }) },
     44 });
     45 
     46 assertErrorMessage(
     47  () =>
     48    wasmEvalText(`(module (import "m" "e" (tag (param i32))))`, {
     49      m: { e: new WebAssembly.Tag({ parameters: [] }) },
     50    }),
     51  WebAssembly.LinkError,
     52  /imported tag 'm.e' signature mismatch/
     53 );
     54 
     55 assertErrorMessage(
     56  () =>
     57    wasmEvalText(`(module (import "m" "e" (tag (param))))`, {
     58      m: { e: new WebAssembly.Tag({ parameters: ["i32"] }) },
     59    }),
     60  WebAssembly.LinkError,
     61  /imported tag 'm.e' signature mismatch/
     62 );
     63 
     64 // Test WebAssembly.Tag methods.
     65 // TODO: add runtime detection for js-types
     66 // {
     67 //   let params = [
     68 //     [],
     69 //     ["i32"],
     70 //     ["i32", "i64"],
     71 //     ["f32", "externref"],
     72 //     ["i32", "i64", "f32", "f64"],
     73 //   ];
     74 
     75 //   for (const arg of params) {
     76 //     const tag = new WebAssembly.Tag({ parameters: arg });
     77 //     assertEqArray(tag.type().parameters, arg);
     78 //   }
     79 // }
     80 
     81 // WebAssembly.Exception tests.
     82 assertErrorMessage(
     83  () => WebAssembly.Exception(),
     84  TypeError,
     85  /calling a builtin Exception constructor without new is forbidden/
     86 );
     87 
     88 assertErrorMessage(
     89  () => new WebAssembly.Exception(),
     90  TypeError,
     91  /At least 2 arguments required/
     92 );
     93 
     94 assertErrorMessage(
     95  () => new WebAssembly.Exception(3, []),
     96  TypeError,
     97  /first argument must be a WebAssembly.Tag/
     98 );
     99 
    100 const { tag1, tag2, tag3, tag4, tag5, tag6, tag7, tag8, tag9 } = wasmEvalText(
    101  `(module
    102     (tag (export "tag1") (param))
    103     (tag (export "tag2") (param i32))
    104     (tag (export "tag3") (param i32 f32))
    105     (tag (export "tag4") (param i32 externref i32))
    106     (tag (export "tag5") (param i32 externref i32 externref))
    107     (tag (export "tag6") (param funcref))
    108     (tag (export "tag7") (param i64))
    109     (tag (export "tag8") (param i32 f64))
    110     (tag (export "tag9") (param externref funcref)))`
    111 ).exports;
    112 
    113 new WebAssembly.Exception(tag1, []);
    114 new WebAssembly.Exception(tag2, [3]);
    115 new WebAssembly.Exception(tag3, [3, 5.5]);
    116 new WebAssembly.Exception(tag4, [3, "foo", 4]);
    117 new WebAssembly.Exception(tag5, [3, "foo", 4, "bar"]);
    118 
    119 assertErrorMessage(
    120  () => new WebAssembly.Exception(tag2, []),
    121  TypeError,
    122  /expected 1 values but got 0/
    123 );
    124 
    125 assertErrorMessage(
    126  () => new WebAssembly.Exception(tag2, [3n]),
    127  TypeError,
    128  /can't convert BigInt to number/
    129 );
    130 
    131 assertErrorMessage(
    132  () => new WebAssembly.Exception(tag6, [undefined]),
    133  TypeError,
    134  /can only pass WebAssembly exported functions to funcref/
    135 );
    136 
    137 assertErrorMessage(
    138  () => new WebAssembly.Exception(tag7, [undefined]),
    139  TypeError,
    140  /can't convert undefined to BigInt/
    141 );
    142 
    143 assertErrorMessage(
    144  () => new WebAssembly.Exception(tag7, {}),
    145  TypeError,
    146  /\({}\) is not iterable/
    147 );
    148 
    149 assertErrorMessage(
    150  () => new WebAssembly.Exception(tag7, 1),
    151  TypeError,
    152  /second argument must be an object/
    153 );
    154 
    155 // Exnref cannot cross the JS/wasm boundary as a function parameter.
    156 var inst = wasmEvalText(`
    157 (module
    158  (func (export "f") (result nullexnref)
    159    unreachable
    160  )
    161 )`);
    162 assertErrorMessage(() => inst.exports.f(), TypeError, /cannot pass value to or from JS/);
    163 
    164 inst = wasmEvalText(`
    165 (module
    166  (func (export "f") (result exnref)
    167    unreachable
    168  )
    169 )`);
    170 assertErrorMessage(() => inst.exports.f(), TypeError, /cannot pass value to or from JS/);
    171 
    172 inst = wasmEvalText(`
    173 (module
    174  (func (export "f") (result (ref exn))
    175    unreachable
    176  )
    177 )`);
    178 assertErrorMessage(() => inst.exports.f(), TypeError, /cannot pass value to or from JS/);
    179 
    180 inst = wasmEvalText(`
    181 (module
    182  (func (export "f") (result (ref noexn))
    183    unreachable
    184  )
    185 )`);
    186 assertErrorMessage(() => inst.exports.f(), TypeError, /cannot pass value to or from JS/);
    187 
    188 // Test Exception methods.
    189 {
    190  const exn1 = new WebAssembly.Exception(tag1, []);
    191  assertEq(exn1.is(tag1), true);
    192  assertEq(exn1.is(tag2), false);
    193  assertErrorMessage(
    194    () => exn1.is(),
    195    TypeError,
    196    /At least 1 argument required/
    197  );
    198  assertErrorMessage(
    199    () => exn1.is(5),
    200    TypeError,
    201    /first argument must be a WebAssembly.Tag/
    202  );
    203 
    204  const exn2 = new WebAssembly.Exception(tag2, [3]);
    205  assertEq(exn2.getArg(tag2, 0), 3);
    206 
    207  assertEq(new WebAssembly.Exception(tag2, [undefined]).getArg(tag2, 0), 0);
    208 
    209  const exn4 = new WebAssembly.Exception(tag4, [3, "foo", 4]);
    210  assertEq(exn4.getArg(tag4, 0), 3);
    211  assertEq(exn4.getArg(tag4, 1), "foo");
    212  assertEq(exn4.getArg(tag4, 2), 4);
    213 
    214  const exn5 = new WebAssembly.Exception(tag5, [3, "foo", 4, "bar"]);
    215  assertEq(exn5.getArg(tag5, 3), "bar");
    216 
    217  const { funcref } = wasmEvalText(
    218    `(module (func (export "funcref")))`
    219  ).exports;
    220  const exn9 = new WebAssembly.Exception(tag9, ["foo", funcref]);
    221  assertEq(exn9.getArg(tag9, 0), "foo");
    222  assertEq(exn9.getArg(tag9, 1), funcref);
    223 
    224  assertErrorMessage(
    225    () => exn2.getArg(),
    226    TypeError,
    227    /At least 2 arguments required/
    228  );
    229  assertErrorMessage(
    230    () => exn2.getArg(5, 0),
    231    TypeError,
    232    /first argument must be a WebAssembly.Tag/
    233  );
    234  assertErrorMessage(
    235    () => exn2.getArg(tag2, "foo"),
    236    TypeError,
    237    /bad Exception getArg index/
    238  );
    239  assertErrorMessage(
    240    () => exn2.getArg(tag2, 10),
    241    RangeError,
    242    /bad Exception getArg index/
    243  );
    244 }
    245 
    246 // Test throwing a JS constructed exception to Wasm.
    247 assertEq(
    248  wasmEvalText(
    249    `(module
    250       (import "m" "exn" (tag $exn (param i32)))
    251       (import "m" "f" (func $f))
    252       (func (export "f") (result i32)
    253         try (result i32)
    254           call $f
    255           (i32.const 0)
    256         catch $exn
    257         end))`,
    258    {
    259      m: {
    260        exn: tag2,
    261        f: () => {
    262          throw new WebAssembly.Exception(tag2, [42]);
    263        },
    264      },
    265    }
    266  ).exports.f(),
    267  42
    268 );
    269 
    270 assertEqArray(
    271  wasmEvalText(
    272    `(module
    273       (import "m" "exn" (tag $exn (param i32 f32)))
    274       (import "m" "f" (func $f))
    275       (func (export "f") (result i32 f32)
    276         try (result i32 f32)
    277           call $f
    278           (i32.const 0)
    279           (f32.const 0)
    280         catch $exn
    281         end))`,
    282    {
    283      m: {
    284        exn: tag3,
    285        f: () => {
    286          throw new WebAssembly.Exception(tag3, [42, 5.5]);
    287        },
    288      },
    289    }
    290  ).exports.f(),
    291  [42, 5.5]
    292 );
    293 
    294 assertEqArray(
    295  wasmEvalText(
    296    `(module
    297       (import "m" "exn" (tag $exn (param i32 f64)))
    298       (import "m" "f" (func $f))
    299       (func (export "f") (result i32 f64)
    300         try (result i32 f64)
    301           call $f
    302           (i32.const 0)
    303           (f64.const 0)
    304         catch $exn
    305         end))`,
    306    {
    307      m: {
    308        exn: tag8,
    309        f: () => {
    310          throw new WebAssembly.Exception(tag8, [9999, 9999]);
    311        },
    312      },
    313    }
    314  ).exports.f(),
    315  [9999, 9999]
    316 );
    317 
    318 assertEqArray(
    319  wasmEvalText(
    320    `(module
    321       (import "m" "exn" (tag $exn (param i32 externref i32)))
    322       (import "m" "f" (func $f))
    323       (func (export "f") (result i32 externref i32)
    324         try (result i32 externref i32)
    325           call $f
    326           (i32.const 0)
    327           (ref.null extern)
    328           (i32.const 0)
    329         catch $exn
    330         end))`,
    331    {
    332      m: {
    333        exn: tag4,
    334        f: () => {
    335          throw new WebAssembly.Exception(tag4, [42, "foo", 42]);
    336        },
    337      },
    338    }
    339  ).exports.f(),
    340  [42, "foo", 42]
    341 );
    342 
    343 assertEqArray(
    344  wasmEvalText(
    345    `(module
    346       (import "m" "exn" (tag $exn (param i32 externref i32 externref)))
    347       (import "m" "f" (func $f))
    348       (func (export "f") (result i32 externref i32 externref)
    349         try (result i32 externref i32 externref)
    350           call $f
    351           (i32.const 0)
    352           (ref.null extern)
    353           (i32.const 0)
    354           (ref.null extern)
    355         catch $exn
    356         end))`,
    357    {
    358      m: {
    359        exn: tag5,
    360        f: () => {
    361          throw new WebAssembly.Exception(tag5, [42, "foo", 42, "bar"]);
    362        },
    363      },
    364    }
    365  ).exports.f(),
    366  [42, "foo", 42, "bar"]
    367 );
    368 
    369 {
    370  const { funcref } = wasmEvalText(
    371    `(module (func (export "funcref")))`
    372  ).exports;
    373  assertEqArray(
    374    wasmEvalText(
    375      `(module
    376         (import "m" "exn" (tag $exn (param externref funcref)))
    377         (import "m" "f" (func $f))
    378         (func (export "f") (result externref funcref)
    379           try (result externref funcref)
    380             call $f
    381             (ref.null extern)
    382             (ref.null func)
    383           catch $exn
    384           end))`,
    385      {
    386        m: {
    387          exn: tag9,
    388          f: () => {
    389            throw new WebAssembly.Exception(tag9, ["foo", funcref]);
    390          },
    391        },
    392      }
    393    ).exports.f(),
    394    ["foo", funcref]
    395  );
    396 }
    397 
    398 assertEq(
    399  wasmEvalText(
    400    `(module
    401       (import "m" "exn" (tag $exn))
    402       (import "m" "f" (func $f))
    403       (func (export "f") (result i32)
    404         try (result i32)
    405           call $f
    406           (i32.const 0)
    407         catch $exn
    408           (i32.const 0)
    409         catch_all
    410           (i32.const 1)
    411         end))`,
    412    {
    413      m: {
    414        exn: tag1,
    415        f: () => {
    416          throw new WebAssembly.Exception(tag2, [42]);
    417        },
    418      },
    419    }
    420  ).exports.f(),
    421  1
    422 );
    423 
    424 {
    425  const exn = new WebAssembly.Tag({ parameters: ["i32"] });
    426  assertEq(
    427    wasmEvalText(
    428      `(module
    429         (import "m" "exn" (tag $exn (param i32)))
    430         (import "m" "f" (func $f))
    431         (func (export "f") (result i32)
    432           try (result i32)
    433             call $f
    434             (i32.const 0)
    435           catch $exn
    436           end))`,
    437      {
    438        m: {
    439          exn,
    440          f: () => {
    441            throw new WebAssembly.Exception(exn, [42]);
    442          },
    443        },
    444      }
    445    ).exports.f(),
    446    42
    447  );
    448 }
    449 
    450 {
    451  const exn1 = new WebAssembly.Tag({ parameters: ["i32"] });
    452  const exn2 = new WebAssembly.Tag({ parameters: ["i32"] });
    453  assertEq(
    454    wasmEvalText(
    455      `(module
    456         (import "m" "exn" (tag $exn (param i32)))
    457         (import "m" "f" (func $f))
    458         (func (export "f") (result i32)
    459           try (result i32)
    460             call $f
    461             (i32.const 0)
    462           catch $exn
    463           catch_all
    464             (i32.const 1)
    465           end))`,
    466      {
    467        m: {
    468          exn: exn1,
    469          f: () => {
    470            throw new WebAssembly.Exception(exn2, [42]);
    471          },
    472        },
    473      }
    474    ).exports.f(),
    475    1
    476  );
    477 }
    478 
    479 // Test `getArg` on a Wasm-thrown exception.
    480 assertEq(
    481  (() => {
    482    try {
    483      wasmEvalText(
    484        `(module
    485           (import "m" "exn" (tag $exn (param i32 f64)))
    486           (func (export "f")
    487             (i32.const 9999)
    488             (f64.const 9999)
    489             throw $exn))`,
    490        { m: { exn: tag8 } }
    491      ).exports.f();
    492    } catch (exn) {
    493      return exn.getArg(tag8, 1);
    494    }
    495  })(),
    496  9999
    497 );
    498 
    499 assertEqArray(
    500  (() => {
    501    try {
    502      wasmEvalText(
    503        `(module
    504           (import "m" "exn" (tag $exn (param i32 externref i32 externref)))
    505           (func (export "f") (param externref externref)
    506             (i32.const 1)
    507             (local.get 0)
    508             (i32.const 2)
    509             (local.get 1)
    510             throw $exn))`,
    511        { m: { exn: tag5 } }
    512      ).exports.f("foo", "bar");
    513    } catch (exn) {
    514      return [
    515        exn.getArg(tag5, 0),
    516        exn.getArg(tag5, 1),
    517        exn.getArg(tag5, 2),
    518        exn.getArg(tag5, 3),
    519      ];
    520    }
    521  })(),
    522  [1, "foo", 2, "bar"]
    523 );