tor-browser

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

try-table.js (11064B)


      1 // A try_table acts like a block label, with results
      2 {
      3  let maxResults1 = Array.from(Array(1000).keys());
      4  let maxResults2 = maxResults1.map((x) => x - 1);
      5  const TESTS = [
      6    ['i32', 'i32.const', [0], [1]],
      7    ['i32 '.repeat(1000), 'i32.const', maxResults1, maxResults2],
      8    ['i64', 'i64.const', [0], [1]],
      9    ['i64 '.repeat(1000), 'i64.const', maxResults1, maxResults2],
     10    ['f32', 'f32.const', [0], [1]],
     11    ['f32 '.repeat(1000), 'f32.const', maxResults1, maxResults2],
     12    ['f64', 'f64.const', [0], [1]],
     13    ['f64 '.repeat(1000), 'f64.const', maxResults1, maxResults2],
     14  ];
     15  for (let [types, constructor, values1, values2] of TESTS) {
     16    let {test} = wasmEvalText(`(module
     17      (func (export "test") (param $shouldBranch i32) (result ${types})
     18        try_table (result ${types})
     19          ${values2.map((x) => `${constructor} ${x}`).join(" ")}
     20          (br_if 1 local.get $shouldBranch)
     21          ${values1.map((x) => `${constructor} ${x}`).join(" ")}
     22          br 0
     23        end
     24      )
     25    )`).exports;
     26    assertEqResults(test(0), values1);
     27    assertEqResults(test(1), values2);
     28  }
     29 }
     30 
     31 // A try_table can have params
     32 {
     33  let maxParams1 = Array.from(Array(1000).keys());
     34  const TESTS = [
     35    ['i32', 'i32.const', [0]],
     36    ['i32 '.repeat(1000), 'i32.const', maxParams1],
     37    ['i64', 'i64.const', [0]],
     38    ['i64 '.repeat(1000), 'i64.const', maxParams1],
     39    ['f32', 'f32.const', [0]],
     40    ['f32 '.repeat(1000), 'f32.const', maxParams1],
     41    ['f64', 'f64.const', [0]],
     42    ['f64 '.repeat(1000), 'f64.const', maxParams1],
     43  ];
     44  for (let [types, constructor, params] of TESTS) {
     45    let {test} = wasmEvalText(`(module
     46      (func (export "test") (result ${types})
     47        ${params.map((x) => `${constructor} ${x}`).join(" ")}
     48        try_table (param ${types})
     49          return
     50        end
     51        unreachable
     52      )
     53    )`).exports;
     54    assertEqResults(test(), params);
     55  }
     56 }
     57 
     58 // Test try_table catching exceptions
     59 {
     60  let {test} = wasmEvalText(`(module
     61    (tag $A (param i32))
     62    (tag $B (param i32))
     63    (tag $C)
     64 
     65    (table funcref (elem $throwA $throwB $throwC $doNothing))
     66 
     67    (type $empty (func))
     68    (func $throwA
     69      i32.const 1
     70      throw $A
     71    )
     72    (func $throwB
     73      i32.const 2
     74      throw $B
     75    )
     76    (func $throwC
     77      throw $C
     78    )
     79    (func $doNothing)
     80 
     81    (func (export "test") (param i32) (result i32)
     82      block $handleA (result i32 (ref exn))
     83        block $handleB (result i32 (ref exn))
     84          block $handleUnknown (result (ref exn))
     85            try_table
     86              (catch_ref $A $handleA)
     87              (catch_ref $B $handleB)
     88              (catch_all_ref $handleUnknown)
     89 
     90              (call_indirect (type $empty)
     91                local.get 0)
     92            end
     93            (; nothing threw ;)
     94            i32.const -1
     95            return
     96          end
     97          (; $handleUnknown ;)
     98          drop
     99          i32.const 3
    100          return
    101        end
    102         (; $handleB ;)
    103        drop
    104        return
    105      end
    106      (; $handleA ;)
    107      drop
    108      return
    109    )
    110  )`).exports;
    111  // Throwing A results in 1 from the payload from the catch
    112  assertEq(test(0), 1);
    113  // Throwing B results in 2 from the payload from the catch
    114  assertEq(test(1), 2);
    115  // Throwing C results in 3 from the constant in the catch_all
    116  assertEq(test(2), 3);
    117  // Not throwing anything gets -1 from the fallthrough
    118  assertEq(test(3), -1);
    119 }
    120 
    121 // Test try_table catching exceptions without capturing the exnref
    122 {
    123  let {test} = wasmEvalText(`(module
    124    (tag $A (param i32))
    125    (tag $B (param i32))
    126    (tag $C)
    127 
    128    (table funcref (elem $throwA $throwB $throwC $doNothing))
    129 
    130    (type $empty (func))
    131    (func $throwA
    132      i32.const 1
    133      throw $A
    134    )
    135    (func $throwB
    136      i32.const 2
    137      throw $B
    138    )
    139    (func $throwC
    140      throw $C
    141    )
    142    (func $doNothing)
    143 
    144    (func (export "test") (param i32) (result i32)
    145      block $handleA (result i32)
    146        block $handleB (result i32)
    147          block $handleUnknown
    148            try_table
    149              (catch $A $handleA)
    150              (catch $B $handleB)
    151              (catch_all $handleUnknown)
    152 
    153              (call_indirect (type $empty)
    154                local.get 0)
    155            end
    156            (; nothing threw ;)
    157            i32.const -1
    158            return
    159          end
    160          (; $handleUnknown ;)
    161          i32.const 3
    162          return
    163        end
    164         (; $handleB ;)
    165        return
    166      end
    167      (; $handleA ;)
    168      return
    169    )
    170  )`).exports;
    171  // Throwing A results in 1 from the payload from the catch
    172  assertEq(test(0), 1);
    173  // Throwing B results in 2 from the payload from the catch
    174  assertEq(test(1), 2);
    175  // Throwing C results in 3 from the constant in the catch_all
    176  assertEq(test(2), 3);
    177  // Not throwing anything gets -1 from the fallthrough
    178  assertEq(test(3), -1);
    179 }
    180 
    181 // Test try_table catching exceptions with various payloads
    182 {
    183  let maxResults1 = Array.from(Array(999).keys());
    184  const TESTS = [
    185    ['i32', 'i32.const', [0]],
    186    ['i32 '.repeat(999), 'i32.const', maxResults1],
    187    ['i64', 'i64.const', [0]],
    188    ['i64 '.repeat(999), 'i64.const', maxResults1],
    189    ['f32', 'f32.const', [0]],
    190    ['f32 '.repeat(999), 'f32.const', maxResults1],
    191    ['f64', 'f64.const', [0]],
    192    ['f64 '.repeat(999), 'f64.const', maxResults1],
    193  ];
    194  for (let [types, constructor, params] of TESTS) {
    195    let {testCatch, testCatchRef} = wasmEvalText(`(module
    196      (tag $E (param ${types}))
    197 
    198      (func (export "testCatch") (result ${types})
    199        try_table (catch $E 0)
    200          ${params.map((x) => `${constructor} ${x}`).join(" ")}
    201          throw $E
    202        end
    203        unreachable
    204      )
    205      (func (export "testCatchRef") (result ${types})
    206        (block (result ${types} exnref)
    207          try_table (catch_ref $E 0)
    208            ${params.map((x) => `${constructor} ${x}`).join(" ")}
    209            throw $E
    210          end
    211          unreachable
    212        )
    213        drop
    214        return
    215      )
    216 
    217    )`).exports;
    218    assertEqResults(testCatch(), params);
    219    assertEqResults(testCatchRef(), params);
    220  }
    221 }
    222 
    223 // Test setting locals in conditional control flow
    224 {
    225  let {test} = wasmEvalText(`(module
    226    (tag $E)
    227 
    228    (func (export "test") (param $shouldThrow i32) (result i32)
    229      (local $result i32)
    230 
    231      (block $join
    232        (block $catch
    233          try_table (catch $E $catch)
    234            local.get $shouldThrow
    235            if
    236              throw $E
    237            end
    238            (local.set $result i32.const 0)
    239            br $join
    240          end
    241        )
    242        (local.set $result i32.const 1)
    243        br $join
    244      )
    245 
    246      local.get $result
    247    )
    248 
    249  )`).exports;
    250  assertEq(test(0), 0);
    251  assertEq(test(1), 1);
    252 }
    253 
    254 // Matching catch clauses is done in order
    255 {
    256  let {testCatch, testCatchRef, testCatchAll, testCatchAllRef} = wasmEvalText(`(module
    257    (tag $E)
    258 
    259    (func (export "testCatch")
    260      (block $good
    261        (block $bad
    262          try_table (catch $E $good) (catch $E $bad) (catch_all $bad)
    263            throw $E
    264          end
    265        )
    266        unreachable
    267      )
    268    )
    269    (func (export "testCatchAll")
    270      (block $good
    271        (block $bad
    272          try_table (catch_all $good) (catch $E $bad) (catch $E $bad)
    273            throw $E
    274          end
    275        )
    276        unreachable
    277      )
    278    )
    279    (func (export "testCatchRef")
    280      (block $good (result (ref exn))
    281        (block $bad (result (ref exn))
    282          try_table (catch_ref $E $good) (catch_ref $E $bad) (catch_all_ref $bad)
    283            throw $E
    284          end
    285          unreachable
    286        )
    287        unreachable
    288      )
    289      drop
    290    )
    291    (func (export "testCatchAllRef")
    292      (block $good (result (ref exn))
    293        (block $bad (result (ref exn))
    294          try_table (catch_all_ref $good) (catch_ref $E $bad) (catch_ref $E $bad)
    295            throw $E
    296          end
    297          unreachable
    298        )
    299        unreachable
    300      )
    301      drop
    302    )
    303  )`).exports;
    304  testCatch();
    305  testCatchAll();
    306  testCatchRef();
    307  testCatchAllRef();
    308 }
    309 
    310 // Test try_table as target of a delegate
    311 {
    312  let {test} = wasmEvalText(`(module
    313    (tag $E)
    314    (func (export "test")
    315      block $good
    316        block $bad
    317          try_table $a (catch_all $good)
    318            try
    319              try
    320                throw $E
    321              delegate $a
    322            catch $E
    323              br $bad
    324            end
    325          end
    326        end
    327        unreachable
    328      end
    329    )
    330  )`).exports;
    331  test();
    332 }
    333 
    334 // Try table cannot be target of rethrow
    335 {
    336  wasmFailValidateText(`(module
    337    (func
    338      try_table (catch_all 0) rethrow 0 end
    339    )
    340  )`, /rethrow target/);
    341 }
    342 
    343 // Test try_table catching and rethrowing JS exceptions
    344 {
    345  let tag = new WebAssembly.Tag({parameters: []});
    346  let exn = new WebAssembly.Exception(tag, []);
    347  let values = [...WasmExternrefValues, exn];
    348  function throwJS(value) {
    349    throw value;
    350  }
    351  let {test} = wasmEvalText(`(module
    352    (import "" "tag" (tag $tag))
    353    (import "" "throwJS" (func $throwJS (param externref)))
    354    (func $innerRethrow (param externref)
    355      (block (result exnref)
    356        try_table (catch_ref $tag 0) (catch_all_ref 0)
    357          local.get 0
    358          call $throwJS
    359        end
    360        return
    361      )
    362      throw_ref
    363    )
    364    (func (export "test") (param externref)
    365      (block (result exnref)
    366        try_table (catch_ref $tag 0) (catch_all_ref 0)
    367          local.get 0
    368          call $innerRethrow
    369        end
    370        return
    371      )
    372      throw_ref
    373    )
    374  )`, {"": {tag, throwJS}}).exports;
    375 
    376  for (let value of values) {
    377    try {
    378      test(value);
    379      assertEq(true, false);
    380    } catch (thrownValue) {
    381      assertEq(thrownValue, value);
    382    }
    383  }
    384 }
    385 
    386 // WebAssembly.JSTag property is read-only and enumerable
    387 WebAssembly.JSTag = null;
    388 assertEq(WebAssembly.JSTag !== null, true);
    389 assertEq(WebAssembly.propertyIsEnumerable('JSTag'), true);
    390 
    391 // Test try_table catching JS exceptions and unpacking them using JSTag
    392 {
    393  let tag = WebAssembly.JSTag;
    394  let values = [...WasmExternrefValues];
    395  function throwJS(value) {
    396    throw value;
    397  }
    398  let {test} = wasmEvalText(`(module
    399    (import "" "tag" (tag $tag (param externref)))
    400    (import "" "throwJS" (func $throwJS (param externref)))
    401    (func (export "test") (param externref) (result externref)
    402      try_table (catch $tag 0)
    403        local.get 0
    404        call $throwJS
    405      end
    406      unreachable
    407    )
    408  )`, {"": {tag, throwJS}}).exports;
    409 
    410  for (let value of values) {
    411    assertEq(value, test(value));
    412  }
    413 }
    414 
    415 // Test try_table catching JS exceptions using JSTag and unpacking them using JSTag
    416 {
    417  let tag = WebAssembly.JSTag;
    418  let values = [...WasmExternrefValues];
    419  function throwJS(value) {
    420    throw new WebAssembly.Exception(tag, [value]);
    421  }
    422  let {test} = wasmEvalText(`(module
    423    (import "" "tag" (tag $tag (param externref)))
    424    (import "" "throwJS" (func $throwJS (param externref)))
    425    (func (export "test") (param externref) (result externref)
    426      try_table (catch $tag 0)
    427        local.get 0
    428        call $throwJS
    429      end
    430      unreachable
    431    )
    432  )`, {"": {tag, throwJS}}).exports;
    433 
    434  for (let value of values) {
    435    assertEq(value, test(value));
    436  }
    437 }