tor-browser

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

control-flow.js (27516B)


      1 const RuntimeError = WebAssembly.RuntimeError;
      2 
      3 // ----------------------------------------------------------------------------
      4 // if
      5 
      6 // Condition is an int32
      7 wasmFailValidateText('(module (func (local f32) (if (local.get 0) (then (i32.const 1)))))', mismatchError("f32", "i32"));
      8 wasmFailValidateText('(module (func (local f32) (if (local.get 0) (then (i32.const 1)) (else (i32.const 0)))))', mismatchError("f32", "i32"));
      9 wasmFailValidateText('(module (func (local f64) (if (local.get 0) (then (i32.const 1)) (else (i32.const 0)))))', mismatchError("f64", "i32"));
     10 wasmEvalText('(module (func (local i32) (if (local.get 0) (then (nop)))) (export "" (func 0)))');
     11 wasmEvalText('(module (func (local i32) (if (local.get 0) (then (nop)) (else (nop)))) (export "" (func 0)))');
     12 
     13 // Expression values types are consistent
     14 // Also test that we support (result t) for `if`
     15 wasmFailValidateText('(module (func (result i32) (local f32) (if (result f32) (i32.const 42) (then (local.get 0)) (else (i32.const 0)))))', mismatchError("i32", "f32"));
     16 wasmFailValidateText('(module (func (result i32) (local f64) (if (result i32) (i32.const 42) (then (i32.const 0)) (else (local.get 0)))))', mismatchError("f64", "i32"));
     17 wasmFailValidateText('(module (func (result i64) (if (result i64) (i32.const 0) (then (i32.const 1)) (else (i32.const 2)))))', mismatchError("i32", "i64"));
     18 assertEq(wasmEvalText('(module (func (result i32) (if (result i32) (i32.const 42) (then (i32.const 1)) (else (i32.const 2)))) (export "" (func 0)))').exports[""](), 1);
     19 assertEq(wasmEvalText('(module (func (result i32) (if (result i32) (i32.const 0) (then (i32.const 1)) (else (i32.const 2)))) (export "" (func 0)))').exports[""](), 2);
     20 
     21 // Even if we don't yield, sub expressions types still have to match.
     22 wasmFailValidateText('(module (func (param f32) (if (result i32) (i32.const 42) (then (i32.const 1)) (else (local.get 0)))) (export "" (func 0)))', mismatchError('f32', 'i32'));
     23 wasmFailValidateText('(module (func (if (result i32) (i32.const 42) (then (i32.const 1)) (else (i32.const 0)))) (export "" (func 0)))', /(unused values not explicitly dropped by end of block)|(values remaining on stack at end of block)/);
     24 wasmFullPass('(module (func (drop (if (result i32) (i32.const 42) (then (i32.const 1)) (else (i32.const 0))))) (export "run" (func 0)))', undefined);
     25 wasmFullPass('(module (func (param f32) (if (i32.const 42) (then (drop (i32.const 1))) (else (drop (local.get 0))))) (export "run" (func 0)))', undefined, {}, 13.37);
     26 
     27 // Sub-expression values are returned
     28 // Also test that we support (result t) for `block`
     29 wasmFullPass(`(module
     30    (func
     31        (result i32)
     32        (if (result i32)
     33            (i32.const 42)
     34            (then
     35              (block (result i32)
     36                (if (result i32)
     37                    (block (result i32)
     38                        (drop (i32.const 3))
     39                        (drop (i32.const 5))
     40                        (i32.const 0)
     41                    )
     42                    (then (i32.const 1))
     43                    (else (i32.const 2))
     44                )
     45              )
     46            )
     47            (else (i32.const 0))
     48        )
     49    )
     50    (export "run" (func 0))
     51 )`, 2);
     52 
     53 // The if (resp. else) branch is taken iff the condition is true (resp. false)
     54 counter = 0;
     55 var imports = { "":{inc() { counter++ }} };
     56 wasmFullPass(`(module
     57    (import "" "inc" (func (result i32)))
     58    (func
     59        (result i32)
     60        (if (result i32)
     61            (i32.const 42)
     62            (then (i32.const 1))
     63            (else (call 0))
     64        )
     65    )
     66    (export "run" (func 1))
     67 )`, 1, imports);
     68 assertEq(counter, 0);
     69 
     70 wasmFullPass(`(module
     71    (import "" "inc" (func (result i32)))
     72    (func
     73        (result i32)
     74        (if (result i32)
     75            (i32.const 0)
     76            (then (call 0))
     77            (else (i32.const 1))
     78        )
     79    )
     80    (export "run" (func 1))
     81 )`, 1, imports);
     82 assertEq(counter, 0);
     83 
     84 wasmFullPass(`(module
     85    (import "" "inc" (func (result i32)))
     86    (func
     87        (if
     88            (i32.const 0)
     89            (then (drop (call 0)))
     90        )
     91    )
     92    (export "run" (func 1))
     93 )`, undefined, imports);
     94 assertEq(counter, 0);
     95 
     96 assertEq(wasmEvalText(`(module
     97    (import "" "inc" (func (result i32)))
     98    (func
     99        (if
    100            (i32.const 1)
    101            (then (drop (call 0)))
    102        )
    103    )
    104    (export "" (func 1))
    105 )`, imports).exports[""](), undefined);
    106 assertEq(counter, 1);
    107 
    108 wasmFullPass(`(module
    109    (func
    110        (result i32)
    111        (if (result i32)
    112            (i32.const 0)
    113            (then (br 0 (i32.const 0)))
    114            (else (br 0 (i32.const 1)))
    115        )
    116    )
    117    (export "run" (func 0))
    118 )`, 1);
    119 assertEq(counter, 1);
    120 
    121 wasmFullPass(`(module
    122    (func
    123        (if
    124            (i32.const 1)
    125            (then (br 0))
    126        )
    127    )
    128    (export "run" (func 0))
    129 )`, undefined);
    130 assertEq(counter, 1);
    131 
    132 // One can chain if with if/if
    133 counter = 0;
    134 wasmFullPass(`(module
    135  (import "" "inc" (func (result i32)))
    136  (func
    137      (result i32)
    138      (if (result i32)
    139          (i32.const 1)
    140          (then
    141              (if (result i32)
    142                  (i32.const 2)
    143                  (then
    144                      (if (result i32)
    145                          (i32.const 3)
    146                          (then
    147                              (if (result i32)
    148                                  (i32.const 0)
    149                                  (then (call 0))
    150                                  (else (i32.const 42))
    151                              )
    152                          )
    153                          (else (call 0))
    154                      )
    155                  )
    156                  (else (call 0))
    157              )
    158          )
    159          (else (call 0))
    160      )
    161  )
    162  (export "run" (func 1))
    163 )`, 42, imports);
    164 assertEq(counter, 0);
    165 
    166 // "if" doesn't return an expression value
    167 wasmFailValidateText('(module (func (result i32) (if (result i32) (i32.const 42) (then (i32.const 0)))))', /(if without an else.*compatible)|(type mismatch: expected i32 but nothing on stack)/);
    168 wasmFailValidateText('(module (func (result i32) (if (result i32) (i32.const 42) (then (drop (i32.const 0))))))', emptyStackError);
    169 wasmFailValidateText('(module (func (result i32) (if (result i32) (i32.const 1) (then (i32.const 0)) (else (if (result i32) (i32.const 1) (then (i32.const 1)))))))', /(if without an else.*compatible)|(type mismatch: expected i32 but nothing on stack)/);
    170 wasmFailValidateText('(module (func (result i32) (if (result i32) (i32.const 1) (then (drop (i32.const 0))) (else (if (i32.const 1) (then (drop (i32.const 1))))))))', emptyStackError);
    171 wasmFailValidateText('(module (func (if (result i32) (i32.const 1) (then (i32.const 0)) (else (if (result i32) (i32.const 1) (then (i32.const 1)))))))', /(if without an else.*compatible)|(type mismatch: expected i32 but nothing on stack)/);
    172 wasmFailValidateText('(module (func (if (result i32) (i32.const 1) (then (i32.const 0)) (else (if (i32.const 1) (then (drop (i32.const 1))))))))', emptyStackError);
    173 wasmFailValidateText('(module (func (if (i32.const 1) (then (drop (i32.const 0))) (else (if (result i32) (i32.const 1) (then (i32.const 1)))))))', /(if without an else.*compatible)|(type mismatch: expected i32 but nothing on stack)/);
    174 wasmEvalText('(module (func (if (i32.const 1) (then (drop (i32.const 0))) (else (if (i32.const 1) (then (drop (i32.const 1))))))))');
    175 
    176 // ----------------------------------------------------------------------------
    177 // return
    178 
    179 wasmFullPass('(module (func (return)) (export "run" (func 0)))', undefined);
    180 wasmFullPass('(module (func (result i32) (return (i32.const 1))) (export "run" (func 0)))', 1);
    181 wasmFailValidateText('(module (func (if (return) (then (i32.const 0)))) (export "run" (func 0)))', unusedValuesError);
    182 wasmFailValidateText('(module (func (result i32) (return)) (export "" (func 0)))', emptyStackError);
    183 wasmFullPass('(module (func (return (i32.const 1))) (export "run" (func 0)))', undefined);
    184 wasmFailValidateText('(module (func (result f32) (return (i32.const 1))) (export "" (func 0)))', mismatchError("i32", "f32"));
    185 wasmFailValidateText('(module (func (result i32) (return)) (export "" (func 0)))', emptyStackError);
    186 
    187 // ----------------------------------------------------------------------------
    188 // br / br_if
    189 
    190 wasmFailValidateText('(module (func (result i32) (block (br 0))) (export "" (func 0)))', emptyStackError);
    191 wasmFailValidateText('(module (func (result i32) (br 0)) (export "" (func 0)))', emptyStackError);
    192 wasmFailValidateText('(module (func (result i32) (block (br_if 0 (i32.const 0)))) (export "" (func 0)))', emptyStackError);
    193 
    194 const DEPTH_OUT_OF_BOUNDS = /(branch depth exceeds current nesting level)|(branch depth too large)/;
    195 
    196 wasmFailValidateText('(module (func (br 1)))', DEPTH_OUT_OF_BOUNDS);
    197 wasmFailValidateText('(module (func (block (br 2))))', DEPTH_OUT_OF_BOUNDS);
    198 wasmFailValidateText('(module (func (loop (br 2))))', DEPTH_OUT_OF_BOUNDS);
    199 wasmFailValidateText('(module (func (if (i32.const 0) (then (br 2)))))', DEPTH_OUT_OF_BOUNDS);
    200 wasmFailValidateText('(module (func (if (i32.const 0) (then (br 1)) (else (br 2)))))', DEPTH_OUT_OF_BOUNDS);
    201 wasmFailValidateText('(module (func (if (i32.const 0) (then (br 2)) (else (br 1)))))', DEPTH_OUT_OF_BOUNDS);
    202 
    203 wasmFailValidateText('(module (func (br_if 1 (i32.const 0))))', DEPTH_OUT_OF_BOUNDS);
    204 wasmFailValidateText('(module (func (block (br_if 2 (i32.const 0)))))', DEPTH_OUT_OF_BOUNDS);
    205 wasmFailValidateText('(module (func (loop (br_if 2 (i32.const 0)))))', DEPTH_OUT_OF_BOUNDS);
    206 
    207 wasmFailValidateText(`(module (func (result i32)
    208  block
    209    br 0
    210    if
    211      i32.const 0
    212      i32.const 2
    213    end
    214  end
    215 ) (export "" (func 0)))`, unusedValuesError);
    216 
    217 wasmFullPass(`(module (func (block $out (br_if $out (br 0)))) (export "run" (func 0)))`, undefined);
    218 
    219 wasmFullPass('(module (func (br 0)) (export "run" (func 0)))', undefined);
    220 wasmFullPass('(module (func (block (br 0))) (export "run" (func 0)))', undefined);
    221 wasmFullPass('(module (func (block $l (br $l))) (export "run" (func 0)))', undefined);
    222 
    223 wasmFullPass('(module (func (block (block (br 1)))) (export "run" (func 0)))', undefined);
    224 wasmFullPass('(module (func (block $l (block (br $l)))) (export "run" (func 0)))', undefined);
    225 
    226 wasmFullPass('(module (func (block $l (block $m (br $l)))) (export "run" (func 0)))', undefined);
    227 wasmFullPass('(module (func (block $l (block $m (br $m)))) (export "run" (func 0)))', undefined);
    228 
    229 wasmFullPass(`(module (func (result i32)
    230  (block
    231    (br 0)
    232    (return (i32.const 0))
    233  )
    234  (return (i32.const 1))
    235 ) (export "run" (func 0)))`, 1);
    236 
    237 wasmFullPass(`(module (func (result i32)
    238  (block
    239    (block
    240      (br 0)
    241      (return (i32.const 0))
    242    )
    243    (return (i32.const 1))
    244  )
    245  (return (i32.const 2))
    246 ) (export "run" (func 0)))`, 1);
    247 
    248 wasmFullPass(`(module (func (result i32)
    249  (block $outer
    250    (block $inner
    251      (br $inner)
    252      (return (i32.const 0))
    253    )
    254    (return (i32.const 1))
    255  )
    256  (return (i32.const 2))
    257 ) (export "run" (func 0)))`, 1);
    258 
    259 var notcalled = false;
    260 var called = false;
    261 var imports = {"": {
    262    notcalled() {notcalled = true},
    263    called() {called = true}
    264 }};
    265 wasmFullPass(`(module
    266 (import "" "notcalled" (func))
    267 (import "" "called" (func))
    268 (func
    269  (block
    270    (return (br 0))
    271    (call 0)
    272  )
    273  (call 1)
    274 ) (export "run" (func 2)))`, undefined, imports);
    275 assertEq(notcalled, false);
    276 assertEq(called, true);
    277 
    278 wasmFullPass(`(module (func
    279  (block
    280    (i32.add
    281      (i32.const 0)
    282      (return (br 0))
    283    )
    284    drop
    285  )
    286  (return)
    287 ) (export "run" (func 0)))`, undefined);
    288 
    289 wasmFullPass(`(module (func (result i32)
    290  (block
    291    (if
    292      (i32.const 1)
    293      (then (br 0))
    294      (else (return (i32.const 0)))
    295    )
    296  )
    297  (return (i32.const 1))
    298 ) (export "run" (func 0)))`, 1);
    299 
    300 wasmFullPass('(module (func (br_if 0 (i32.const 1))) (export "run" (func 0)))', undefined);
    301 wasmFullPass('(module (func (br_if 0 (i32.const 0))) (export "run" (func 0)))', undefined);
    302 wasmFullPass('(module (func (block (br_if 0 (i32.const 1)))) (export "run" (func 0)))', undefined);
    303 wasmFullPass('(module (func (block (br_if 0 (i32.const 0)))) (export "run" (func 0)))', undefined);
    304 wasmFullPass('(module (func (block $l (br_if $l (i32.const 1)))) (export "run" (func 0)))', undefined);
    305 
    306 var isNonZero = wasmEvalText(`(module (func (param i32) (result i32)
    307  (block
    308    (br_if 0 (local.get 0))
    309    (return (i32.const 0))
    310  )
    311  (return (i32.const 1))
    312 ) (export "" (func 0)))`).exports[""];
    313 
    314 assertEq(isNonZero(0), 0);
    315 assertEq(isNonZero(1), 1);
    316 assertEq(isNonZero(-1), 1);
    317 
    318 // branches with values
    319 // br/br_if and block
    320 wasmFailValidateText('(module (func (result i32) (br 0)))', emptyStackError);
    321 wasmFailValidateText('(module (func (result i32) (br 0 (f32.const 42))))', mismatchError("f32", "i32"));
    322 wasmFailValidateText('(module (func (result i32) (block (br 0))))', emptyStackError);
    323 wasmFailValidateText('(module (func (result i32) (block (result f32) (br 0 (f32.const 42)))))', mismatchError("f32", "i32"));
    324 
    325 wasmFailValidateText(`(module (func (param i32) (result i32) (block (if (result i32) (local.get 0) (then (br 0 (i32.const 42)))))) (export "" (func 0)))`, /(if without an else.*compatible)|(type mismatch: expected i32 but nothing on stack)/);
    326 wasmFailValidateText(`(module (func (param i32) (result i32) (block (result i32) (if (local.get 0) (then (drop (i32.const 42)))) (else (br 0 (f32.const 42))))) (export "" (func 0)))`, mismatchError("f32", "i32"));
    327 
    328 wasmFullPass('(module (func (result i32) (br 0 (i32.const 42)) (i32.const 13)) (export "run" (func 0)))', 42);
    329 wasmFullPass('(module (func (result i32) (block (result i32) (br 0 (i32.const 42)) (i32.const 13))) (export "run" (func 0)))', 42);
    330 
    331 wasmFailValidateText('(module (func) (func (block (result i32) (br 0 (call 0)) (i32.const 13))) (export "" (func 0)))', emptyStackError);
    332 wasmFailValidateText('(module (func) (func (block (result i32) (br_if 0 (call 0) (i32.const 1)) (i32.const 13))) (export "" (func 0)))', emptyStackError);
    333 
    334 var f = wasmEvalText(`(module (func (param i32) (result i32) (block (result i32) (if (local.get 0) (then (drop (i32.const 42)))) (i32.const 43))) (export "" (func 0)))`).exports[""];
    335 assertEq(f(0), 43);
    336 assertEq(f(1), 43);
    337 
    338 wasmFailValidateText(`(module (func (param i32) (result i32) (block (result i32) (if (result i32) (local.get 0) (then (br 0 (i32.const 42)))) (i32.const 43))) (export "" (func 0)))`, /(if without an else.*compatible)|(type mismatch: expected i32 but nothing on stack)/);
    339 
    340 var f = wasmEvalText(`(module (func (param i32) (result i32) (block (result i32) (if (local.get 0) (then (br 1 (i32.const 42)))) (i32.const 43))) (export "" (func 0)))`).exports[""];
    341 assertEq(f(0), 43);
    342 assertEq(f(1), 42);
    343 
    344 wasmFailValidateText(`(module (func (param i32) (result i32) (block (br_if 0 (i32.const 42) (local.get 0)) (i32.const 43))) (export "" (func 0)))`, /(unused values not explicitly dropped by end of block)|(values remaining on stack at end of block)/);
    345 
    346 var f = wasmEvalText(`(module (func (param i32) (result i32) (block (result i32) (drop (br_if 0 (i32.const 42) (local.get 0))) (i32.const 43))) (export "" (func 0)))`).exports[""];
    347 assertEq(f(0), 43);
    348 assertEq(f(1), 42);
    349 
    350 var f = wasmEvalText(`(module (func (param i32) (result i32) (block (result i32) (if (local.get 0) (then (drop (i32.const 42)))) (br 0 (i32.const 43)))) (export "" (func 0)))`).exports[""];
    351 assertEq(f(0), 43);
    352 assertEq(f(1), 43);
    353 
    354 wasmFailValidateText(`(module (func (param i32) (result i32) (block (result i32) (if (result i32) (local.get 0) (then (br 0 (i32.const 42)))) (br 0 (i32.const 43)))) (export "" (func 0)))`, /(if without an else.*compatible)|(type mismatch: expected i32 but nothing on stack)/);
    355 
    356 var f = wasmEvalText(`(module (func (param i32) (result i32) (if (local.get 0) (then (br 1 (i32.const 42)))) (br 0 (i32.const 43))) (export "" (func 0)))`).exports[""];
    357 assertEq(f(0), 43);
    358 assertEq(f(1), 42);
    359 
    360 var f = wasmEvalText(`(module (func (param i32) (result i32) (block (result i32) (if (local.get 0) (then (br 1 (i32.const 42)))) (br 0 (i32.const 43)))) (export "" (func 0)))`).exports[""];
    361 assertEq(f(0), 43);
    362 assertEq(f(1), 42);
    363 
    364 var f = wasmEvalText(`(module (func (param i32) (result i32) (br_if 0 (i32.const 42) (local.get 0)) (br 0 (i32.const 43))) (export "" (func 0)))`).exports[""];
    365 assertEq(f(0), 43);
    366 assertEq(f(1), 42);
    367 
    368 var f = wasmEvalText(`(module (func (param i32) (result i32) (block (result i32) (br_if 0 (i32.const 42) (local.get 0)) (br 0 (i32.const 43)))) (export "" (func 0)))`).exports[""];
    369 assertEq(f(0), 43);
    370 assertEq(f(1), 42);
    371 
    372 var f = wasmEvalText(`(module (func (param i32) (result i32) (i32.add (i32.const 1) (block (result i32) (if (local.get 0) (then (drop (i32.const 99)))) (i32.const -1)))) (export "" (func 0)))`).exports[""];
    373 assertEq(f(0), 0);
    374 assertEq(f(1), 0);
    375 
    376 wasmFailValidateText(`(module (func (param i32) (result i32) (i32.add (i32.const 1) (block (result i32) (if (result i32) (local.get 0) (then (br 0 (i32.const 99)))) (i32.const -1)))) (export "" (func 0)))`, /(if without an else.*compatible)|(type mismatch: expected i32 but nothing on stack)/);
    377 
    378 var f = wasmEvalText(`(module (func (param i32) (result i32) (i32.add (i32.const 1) (block (result i32) (if (local.get 0) (then (br 1 (i32.const 99)))) (i32.const -1)))) (export "" (func 0)))`).exports[""];
    379 assertEq(f(0), 0);
    380 assertEq(f(1), 100);
    381 
    382 wasmFailValidateText(`(module (func (param i32) (result i32) (i32.add (i32.const 1) (block (br_if 0 (i32.const 99) (local.get 0)) (i32.const -1)))) (export "" (func 0)))`, /(unused values not explicitly dropped by end of block)|(values remaining on stack at end of block)/);
    383 
    384 var f = wasmEvalText(`(module (func (param i32) (result i32) (i32.add (i32.const 1) (block (result i32) (drop (br_if 0 (i32.const 99) (local.get 0))) (i32.const -1)))) (export "" (func 0)))`).exports[""];
    385 assertEq(f(0), 0);
    386 assertEq(f(1), 100);
    387 
    388 wasmFullPass(`(module (func (result i32) (block (result i32) (br 0 (return (i32.const 42))) (i32.const 0))) (export "run" (func 0)))`, 42);
    389 wasmFullPass(`(module (func (result i32) (block (result i32) (return (br 0 (i32.const 42))))) (export "run" (func 0)))`, 42);
    390 wasmFullPass(`(module (func (result i32) (block (result i32) (return (br 0 (i32.const 42))) (i32.const 0))) (export "run" (func 0)))`, 42);
    391 
    392 wasmFullPass(`(module (func (result f32) (drop (block (result i32) (br 0 (i32.const 0)))) (block (result f32) (br 0 (f32.const 42)))) (export "run" (func 0)))`, 42);
    393 
    394 var called = 0;
    395 var imports = {
    396    sideEffects: {
    397        ifTrue(x) {assertEq(x, 13); called++;},
    398        ifFalse(x) {assertEq(x, 37); called--;}
    399    }
    400 }
    401 var f = wasmEvalText(`(module
    402 (import "sideEffects" "ifTrue" (func (param i32)))
    403 (import "sideEffects" "ifFalse" (func (param i32)))
    404 (func
    405  (param i32) (result i32)
    406  (block $outer
    407   (if
    408    (local.get 0)
    409    (then (block (call 0 (i32.const 13)) (br $outer)))
    410   )
    411   (if
    412    (i32.eqz (local.get 0))
    413    (then (block (call 1 (i32.const 37)) (br $outer)))
    414   )
    415  )
    416  (i32.const 42)
    417 )
    418 (export "" (func 2)))`, imports).exports[""];
    419 assertEq(f(0), 42);
    420 assertEq(called, -1);
    421 assertEq(f(1), 42);
    422 assertEq(called, 0);
    423 
    424 // br/br_if and loop
    425 wasmFullPass(`(module (func (param i32) (result i32) (block $out (result i32) (loop $in (result i32) (br $out (local.get 0))))) (export "run" (func 0)))`, 1, {}, 1);
    426 wasmFullPass(`(module (func (param i32) (result i32) (loop $in (result i32) (br 1 (local.get 0)))) (export "run" (func 0)))`, 1, {}, 1);
    427 wasmFullPass(`(module (func (param i32) (result i32) (block $out (result i32) (loop $in (result i32) (br $out (local.get 0))))) (export "run" (func 0)))`, 1, {}, 1);
    428 
    429 wasmFailValidateText(`(module (func (param i32) (result i32)
    430  (block $out
    431   (loop $in
    432    (if (local.get 0) (then (br $in (i32.const 1))))
    433    (if (local.get 0) (then (br $in (f32.const 2))))
    434    (if (local.get 0) (then (br $in (f64.const 3))))
    435    (if (local.get 0) (then (br $in)))
    436    (i32.const 7)
    437   )
    438  )
    439 ) (export "" (func 0)))`, /(unused values not explicitly dropped by end of block)|(values remaining on stack at end of block)/);
    440 
    441 wasmFullPass(`(module
    442 (func
    443  (result i32)
    444  (local i32)
    445  (block $out (result i32)
    446    (loop $in (result i32)
    447     (local.set 0 (i32.add (local.get 0) (i32.const 1)))
    448     (if
    449        (i32.ge_s (local.get 0) (i32.const 7))
    450        (then (br $out (local.get 0)))
    451     )
    452     (br $in)
    453    )
    454  )
    455 )
    456 (export "run" (func 0)))`, 7);
    457 
    458 wasmFullPass(`(module
    459 (func
    460  (result i32)
    461  (local i32)
    462  (block $out (result i32)
    463   (loop $in (result i32)
    464    (local.set 0 (i32.add (local.get 0) (i32.const 1)))
    465    (br_if $out (local.get 0) (i32.ge_s (local.get 0) (i32.const 7)))
    466    (br $in)
    467   )
    468  )
    469 )
    470 (export "run" (func 0)))`, 7);
    471 
    472 // ----------------------------------------------------------------------------
    473 // loop
    474 
    475 wasmFailValidateText('(module (func (loop (br 2))))', DEPTH_OUT_OF_BOUNDS);
    476 
    477 wasmFailValidateText('(module (func (result i32) (drop (loop (i32.const 2))) (i32.const 1)) (export "" (func 0)))', /(unused values not explicitly dropped by end of block)|(values remaining on stack at end of block)/);
    478 wasmFullPass('(module (func (loop)) (export "run" (func 0)))', undefined);
    479 wasmFullPass('(module (func (result i32) (loop (drop (i32.const 2))) (i32.const 1)) (export "run" (func 0)))', 1);
    480 
    481 wasmFullPass('(module (func (loop (br 1))) (export "run" (func 0)))', undefined);
    482 wasmFullPass('(module (func (loop $a (br 1))) (export "run" (func 0)))', undefined);
    483 wasmFullPass('(module (func (loop $a (br_if $a (i32.const 0)))) (export "run" (func 0)))', undefined);
    484 wasmFullPass('(module (func (block $a (loop $b (br $a)))) (export "run" (func 0)))', undefined);
    485 wasmFullPass('(module (func (result i32) (loop (result i32) (i32.const 1))) (export "run" (func 0)))', 1);
    486 
    487 wasmFullPass(`(module (func (result i32) (local i32)
    488  (block
    489    $break
    490    (loop
    491      $continue
    492      (if
    493        (i32.gt_u (local.get 0) (i32.const 5))
    494        (then (br $break))
    495      )
    496      (local.set 0 (i32.add (local.get 0) (i32.const 1)))
    497      (br $continue)
    498    )
    499  )
    500  (return (local.get 0))
    501 ) (export "run" (func 0)))`, 6);
    502 
    503 wasmFullPass(`(module (func (result i32) (local i32)
    504  (block
    505    $break
    506    (loop
    507      $continue
    508      (br_if
    509        $break
    510        (i32.gt_u (local.get 0) (i32.const 5))
    511      )
    512      (local.set 0 (i32.add (local.get 0) (i32.const 1)))
    513      (br $continue)
    514    )
    515  )
    516  (return (local.get 0))
    517 ) (export "run" (func 0)))`, 6);
    518 
    519 wasmFullPass(`(module (func (result i32) (local i32)
    520  (block
    521    $break
    522    (loop
    523      $continue
    524      (local.set 0 (i32.add (local.get 0) (i32.const 1)))
    525      (br_if
    526        $continue
    527        (i32.le_u (local.get 0) (i32.const 5))
    528      )
    529    )
    530  )
    531  (return (local.get 0))
    532 ) (export "run" (func 0)))`, 6);
    533 
    534 wasmFullPass(`(module (func (result i32) (local i32)
    535  (block
    536    $break
    537    (loop
    538      $continue
    539      (br_if
    540        $break
    541        (i32.gt_u (local.get 0) (i32.const 5))
    542      )
    543      (local.set 0 (i32.add (local.get 0) (i32.const 1)))
    544      (loop
    545        (br $continue)
    546      )
    547      (return (i32.const 42))
    548    )
    549  )
    550  (return (local.get 0))
    551 ) (export "run" (func 0)))`, 6);
    552 
    553 wasmFullPass(`(module (func (result i32) (local i32)
    554  (block
    555    $break
    556    (loop
    557      $continue
    558      (local.set 0 (i32.add (local.get 0) (i32.const 1)))
    559      (loop
    560        (br_if
    561          $continue
    562          (i32.le_u (local.get 0) (i32.const 5))
    563        )
    564      )
    565      (br $break)
    566    )
    567  )
    568  (return (local.get 0))
    569 ) (export "run" (func 0)))`, 6);
    570 
    571 // ----------------------------------------------------------------------------
    572 // br_table
    573 
    574 wasmFailValidateText('(module (func (br_table 1 (i32.const 0))))', DEPTH_OUT_OF_BOUNDS);
    575 wasmFailValidateText('(module (func (br_table 1 0 (i32.const 0))))', DEPTH_OUT_OF_BOUNDS);
    576 wasmFailValidateText('(module (func (br_table 0 1 (i32.const 0))))', DEPTH_OUT_OF_BOUNDS);
    577 wasmFailValidateText('(module (func (block (br_table 2 0 (i32.const 0)))))', DEPTH_OUT_OF_BOUNDS);
    578 wasmFailValidateText('(module (func (block (br_table 0 2 (i32.const 0)))))', DEPTH_OUT_OF_BOUNDS);
    579 wasmFailValidateText('(module (func (block (br_table 0 (f32.const 0)))))', mismatchError("f32", "i32"));
    580 wasmFailValidateText('(module (func (loop (br_table 2 0 (i32.const 0)))))', DEPTH_OUT_OF_BOUNDS);
    581 wasmFailValidateText('(module (func (loop (br_table 0 2 (i32.const 0)))))', DEPTH_OUT_OF_BOUNDS);
    582 wasmFailValidateText('(module (func (loop (br_table 0 (f32.const 0)))))', mismatchError("f32", "i32"));
    583 
    584 wasmFullPass(`(module (func (param i32) (result i32)
    585  (block $default
    586   (br_table $default (local.get 0))
    587   (return (i32.const 0))
    588  )
    589  (return (i32.const 1))
    590 ) (export "run" (func 0)))`, 1);
    591 
    592 wasmFullPass(`(module (func (param i32) (result i32)
    593  (block $default
    594   (br_table $default (return (i32.const 1)))
    595   (return (i32.const 0))
    596  )
    597  (return (i32.const 2))
    598 ) (export "run" (func 0)))`, 1);
    599 
    600 wasmFullPass(`(module (func (param i32) (result i32)
    601  (block $outer
    602   (block $inner
    603    (br_table $inner (local.get 0))
    604    (return (i32.const 0))
    605   )
    606   (return (i32.const 1))
    607  )
    608  (return (i32.const 2))
    609 ) (export "run" (func 0)))`, 1);
    610 
    611 var f = wasmEvalText(`(module (func (param i32) (result i32)
    612  (block $0
    613   (block $1
    614    (block $2
    615     (block $default
    616      (br_table $0 $1 $2 $default (local.get 0))
    617     )
    618     (return (i32.const -1))
    619    )
    620    (return (i32.const 2))
    621   )
    622  )
    623  (return (i32.const 0))
    624 ) (export "" (func 0)))`).exports[""];
    625 
    626 assertEq(f(-2), -1);
    627 assertEq(f(-1), -1);
    628 assertEq(f(0), 0);
    629 assertEq(f(1), 0);
    630 assertEq(f(2), 2);
    631 assertEq(f(3), -1);
    632 
    633 // br_table with values
    634 wasmFailValidateText('(module (func (result i32) (block (result i32) (br_table 0 (i32.const 0)))))', emptyStackError);
    635 wasmFailValidateText('(module (func (result i32) (block (result i32) (br_table 0 (f32.const 0) (i32.const 0)))))', mismatchError("f32", "i32"));
    636 
    637 wasmFailValidateText(`(module
    638 (func
    639  (result i32)
    640  (block $outer (result f32)
    641   (block $inner (result f32)
    642    (br_table $outer $inner (f32.const 13.37) (i32.const 1))
    643   )
    644   (br $outer (i32.const 42))
    645  )
    646 )
    647 (export "" (func 0)))`, mismatchError("i32", "f32"));
    648 
    649 wasmFullPass(`(module (func (result i32) (block $default (result i32) (br_table $default (i32.const 42) (i32.const 1)))) (export "run" (func 0)))`, 42);
    650 
    651 var f = wasmEvalText(`(module (func (param i32) (result i32)
    652  (i32.add
    653   (block $1 (result i32)
    654    (drop (block $0 (result i32)
    655     (drop (block $default (result i32)
    656      (br_table $0 $1 $default (local.get 0) (local.get 0))
    657     ))
    658     (local.tee 0 (i32.mul (i32.const 2) (local.get 0)))
    659    ))
    660    (local.tee 0 (i32.add (i32.const 4) (local.get 0)))
    661   )
    662   (i32.const 1)
    663  )
    664 ) (export "" (func 0)))`).exports[""];
    665 
    666 assertEq(f(0), 5);
    667 assertEq(f(1), 2);
    668 assertEq(f(2), 9);
    669 assertEq(f(3), 11);
    670 assertEq(f(4), 13);
    671 
    672 // ----------------------------------------------------------------------------
    673 // unreachable
    674 
    675 const UNREACHABLE = /unreachable/;
    676 assertErrorMessage(wasmEvalText(`(module (func (unreachable)) (export "" (func 0)))`).exports[""], RuntimeError, UNREACHABLE);
    677 assertErrorMessage(wasmEvalText(`(module (func (if (unreachable) (then (nop)))) (export "" (func 0)))`).exports[""], RuntimeError, UNREACHABLE);
    678 assertErrorMessage(wasmEvalText(`(module (func (block (br_if 0 (unreachable)))) (export "" (func 0)))`).exports[""], RuntimeError, UNREACHABLE);
    679 assertErrorMessage(wasmEvalText(`(module (func (block (br_table 0 (unreachable)))) (export "" (func 0)))`).exports[""], RuntimeError, UNREACHABLE);
    680 assertErrorMessage(wasmEvalText(`(module (func (result i32) (i32.add (i32.const 0) (unreachable))) (export "" (func 0)))`).exports[""], RuntimeError, UNREACHABLE);