tor-browser

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

wasm-06.js (10818B)


      1 // |jit-test| test-also=--wasm-compiler=optimizing; error: TestComplete; skip-if: !wasmDebuggingEnabled()
      2 // Tests that wasm module scripts raises onEnterFrame and onLeaveFrame events.
      3 
      4 load(libdir + "asserts.js");
      5 
      6 function runWasmWithDebugger(wast, lib, init, done) {
      7    let g = newGlobal({newCompartment: true});
      8    let dbg = new Debugger(g);
      9 
     10    g.eval(`
     11 var wasm = wasmTextToBinary('${wast}');
     12 var lib = ${lib || 'undefined'};
     13 var m = new WebAssembly.Instance(new WebAssembly.Module(wasm), lib);`);
     14 
     15    init(dbg, g);
     16    let result = undefined, error = undefined;
     17    try {
     18        result = g.eval("m.exports.test()");
     19    } catch (ex) {
     20        error = ex;
     21    }
     22    done(dbg, result, error, g);
     23 }
     24 
     25 // Checking if onEnterFrame is fired for wasm frames and verifying the content
     26 // of the frame and environment properties.
     27 var onEnterFrameCalled, onLeaveFrameCalled, onExceptionUnwindCalled, testComplete;
     28 runWasmWithDebugger(
     29    '(module (func (result i32) (i32.const 42)) (export "test" (func 0)))', undefined,
     30    function (dbg) {
     31        var wasmScript = dbg.findScripts().filter(s => s.format == 'wasm')[0];
     32        assertEq(!!wasmScript, true);
     33        onEnterFrameCalled = 0;
     34        onLeaveFrameCalled = 0;
     35        testComplete = false;
     36        var evalFrame;
     37        dbg.onEnterFrame = function (frame) {
     38            if (frame.type !== 'wasmcall') {
     39                if (frame.type === 'eval')
     40                    evalFrame = frame;
     41                return;
     42            }
     43 
     44            onEnterFrameCalled++;
     45 
     46            assertEq(frame.script, wasmScript);
     47            assertEq(frame.older, evalFrame);
     48            assertEq(frame.type, 'wasmcall');
     49 
     50            let env = frame.environment;
     51            assertEq(env instanceof Object, true);
     52            assertEq(env.inspectable, true);
     53            assertEq(env.parent !== null, true);
     54            assertEq(env.type, 'declarative');
     55            assertEq(env.calleeScript, null);
     56            assertEq(Array.isArray(env.names()), true);
     57            assertEq(env.names().length, 0);
     58 
     59            frame.onPop = function() {
     60                onLeaveFrameCalled++;
     61                testComplete = true;
     62            };
     63       };
     64    },
     65    function (dbg, result, error) {
     66        assertEq(testComplete, true);
     67        assertEq(onEnterFrameCalled, 1);
     68        assertEq(onLeaveFrameCalled, 1);
     69        assertEq(result, 42);
     70        assertEq(error, undefined);
     71    }
     72 );
     73 
     74 // Checking the dbg.getNewestFrame() and frame.older.
     75 runWasmWithDebugger(
     76    '(module (import "env" "ex" (func $fn1)) (func $fn2 (call $fn1)) (export "test" (func $fn2)))',
     77    '{env: { ex: () => { }}}',
     78    function (dbg) {
     79        onEnterFrameCalled = 0;
     80        onLeaveFrameCalled = 0;
     81        testComplete = false;
     82        var evalFrame, wasmFrame;
     83        dbg.onEnterFrame = function (frame) {
     84            onEnterFrameCalled++;
     85 
     86            assertEq(dbg.getNewestFrame(), frame);
     87 
     88            switch (frame.type) {
     89              case 'eval':
     90                evalFrame = frame;
     91                break;
     92              case 'wasmcall':
     93                wasmFrame = frame;
     94                break;
     95              case 'call':
     96                assertEq(frame.older, wasmFrame);
     97                assertEq(frame.older.older, evalFrame);
     98                assertEq(frame.older.older.older, null);
     99                testComplete = true;
    100                break;
    101            }
    102 
    103            frame.onPop = function() {
    104                onLeaveFrameCalled++;
    105            };
    106        };
    107    },
    108    function (dbg, result, error) {
    109        assertEq(testComplete, true);
    110        assertEq(onEnterFrameCalled, 3);
    111        assertEq(onLeaveFrameCalled, 3);
    112        assertEq(error, undefined);
    113    }
    114 );
    115 
    116 // Checking if we can enumerate frames and find 'wasmcall' one.
    117 runWasmWithDebugger(
    118    '(module (import "env" "ex" (func $fn1)) (func $fn2 (call $fn1)) (export "test" (func $fn2)))',
    119    '{env: { ex: () => { debugger; }}}',
    120    function (dbg) {
    121        testComplete = false;
    122        dbg.onDebuggerStatement = function (frame) {
    123            assertEq(frame.type, 'call');
    124            assertEq(frame.older.type, 'wasmcall');
    125            assertEq(frame.older.older.type, 'eval');
    126            assertEq(frame.older.older.older, null);
    127            testComplete = true;
    128        }
    129    },
    130    function (dbg, result, error) {
    131        assertEq(testComplete, true);
    132        assertEq(error, undefined);
    133    }
    134 );
    135 
    136 // Checking if onPop works without onEnterFrame handler.
    137 runWasmWithDebugger(
    138    '(module (import "env" "ex" (func $fn1)) (func $fn2 (call $fn1)) (export "test" (func $fn2)))',
    139    '{env: { ex: () => { debugger; }}}',
    140    function (dbg) {
    141        onLeaveFrameCalled = 0;
    142        dbg.onDebuggerStatement = function (frame) {
    143            if (!frame.older || frame.older.type != 'wasmcall')
    144                return;
    145            frame.older.onPop = function () {
    146                onLeaveFrameCalled++;
    147            };
    148        }
    149    },
    150    function (dbg, result, error) {
    151        assertEq(onLeaveFrameCalled, 1);
    152        assertEq(error, undefined);
    153    }
    154 );
    155 
    156 // Checking if function return values are not changed.
    157 runWasmWithDebugger(
    158    '(module (func (result f64) (f64.const 0.42)) (export "test" (func 0)))', undefined,
    159    function (dbg) {
    160        dbg.onEnterFrame = function (frame) {
    161            dbg.onPop = function () {};
    162        };
    163    },
    164    function (dbg, result, error) {
    165        assertEq(result, 0.42);
    166        assertEq(error, undefined);
    167    }
    168 );
    169 runWasmWithDebugger(
    170    '(module (func (result f32) (f32.const 4.25)) (export "test" (func 0)))', undefined,
    171    function (dbg) {
    172        dbg.onEnterFrame = function (frame) {
    173            dbg.onPop = function () {};
    174        };
    175    },
    176    function (dbg, result, error) {
    177        assertEq(result, 4.25);
    178        assertEq(error, undefined);
    179    }
    180 );
    181 
    182 // Checking if onEnterFrame/onExceptionUnwind work during exceptions --
    183 // `unreachable` causes wasm to throw WebAssembly.RuntimeError exception.
    184 runWasmWithDebugger(
    185    '(module (func (unreachable)) (export "test" (func 0)))', undefined,
    186    function (dbg) {
    187       onEnterFrameCalled = 0;
    188       onLeaveFrameCalled = 0;
    189       onExceptionUnwindCalled = 0;
    190       dbg.onEnterFrame = function (frame) {
    191            if (frame.type !== "wasmcall") return;
    192            onEnterFrameCalled++;
    193            frame.onPop = function() {
    194                onLeaveFrameCalled++;
    195            };
    196       };
    197       dbg.onExceptionUnwind = function (frame) {
    198         if (frame.type !== "wasmcall") return;
    199         onExceptionUnwindCalled++;
    200       };
    201    },
    202    function (dbg, result, error, g) {
    203        assertEq(onEnterFrameCalled, 1);
    204        assertEq(onLeaveFrameCalled, 1);
    205        assertEq(onExceptionUnwindCalled, 1);
    206        assertEq(error instanceof g.WebAssembly.RuntimeError, true);
    207    }
    208 );
    209 
    210 // Checking if onEnterFrame/onExceptionUnwind work during exceptions
    211 // originated in the JavaScript import call.
    212 runWasmWithDebugger(
    213    '(module (import "env" "ex" (func $fn1)) (func $fn2 (call $fn1)) (export "test" (func $fn2)))',
    214    '{env: { ex: () => { throw new Error(); }}}',
    215    function (dbg) {
    216       onEnterFrameCalled = 0;
    217       onLeaveFrameCalled = 0;
    218       onExceptionUnwindCalled = 0;
    219       dbg.onEnterFrame = function (frame) {
    220            if (frame.type !== "wasmcall") return;
    221            onEnterFrameCalled++;
    222            frame.onPop = function() {
    223                onLeaveFrameCalled++;
    224            };
    225       };
    226       dbg.onExceptionUnwind = function (frame) {
    227         if (frame.type !== "wasmcall") return;
    228         onExceptionUnwindCalled++;
    229       };
    230    },
    231    function (dbg, result, error, g) {
    232        assertEq(onEnterFrameCalled, 1);
    233        assertEq(onLeaveFrameCalled, 1);
    234        assertEq(onExceptionUnwindCalled, 1);
    235        assertEq(error instanceof g.Error, true);
    236    }
    237 );
    238 
    239 // Checking throwing in the handler.
    240 runWasmWithDebugger(
    241    '(module (func (unreachable)) (export "test" (func 0)))', undefined,
    242    function (dbg) {
    243        dbg.uncaughtExceptionHook = function (value) {
    244            assertEq(value instanceof Error, true);
    245            return {throw: 'test'};
    246        };
    247        dbg.onEnterFrame = function (frame) {
    248           if (frame.type !== "wasmcall") return;
    249           throw new Error();
    250        };
    251    },
    252    function (dbg, result, error) {
    253        assertEq(error, 'test');
    254    }
    255 );
    256 runWasmWithDebugger(
    257    '(module (func (unreachable)) (export "test" (func 0)))', undefined,
    258    function (dbg) {
    259        dbg.uncaughtExceptionHook = function (value) {
    260            assertEq(value instanceof Error, true);
    261            return {throw: 'test'};
    262        };
    263        dbg.onEnterFrame = function (frame) {
    264            if (frame.type !== "wasmcall") return;
    265            frame.onPop = function () {
    266                throw new Error();
    267            }
    268        };
    269    },
    270    function (dbg, result, error) {
    271        assertEq(error, 'test');
    272    }
    273 );
    274 
    275 // Checking resumption values for JS_THROW.
    276 runWasmWithDebugger(
    277    '(module (func (nop)) (export "test" (func 0)))', undefined,
    278    function (dbg, g) {
    279        dbg.onEnterFrame = function (frame) {
    280            if (frame.type !== "wasmcall") return;
    281            return {throw: 'test'};
    282        };
    283    },
    284    function (dbg, result, error, g) {
    285        assertEq(error, 'test');
    286    }
    287 );
    288 runWasmWithDebugger(
    289    '(module (func (nop)) (export "test" (func 0)))', undefined,
    290    function (dbg, g) {
    291        dbg.onEnterFrame = function (frame) {
    292            if (frame.type !== "wasmcall") return;
    293            frame.onPop = function () {
    294                return {throw: 'test'};
    295            }
    296        };
    297    },
    298    function (dbg, result, error, g) {
    299        assertEq(error, 'test');
    300    }
    301 );
    302 
    303 // Checking resumption values for JS_RETURN (not implemented by wasm baseline).
    304 runWasmWithDebugger(
    305    '(module (func (unreachable)) (export "test" (func 0)))', undefined,
    306    function (dbg) {
    307        dbg.onEnterFrame = function (frame) {
    308            if (frame.type !== "wasmcall") return;
    309            return {return: 2};
    310        };
    311    },
    312    function (dbg, result, error) {
    313        assertEq(result, undefined, 'NYI: result == 2, if JS_RETURN is implemented');
    314        assertEq(error != undefined, true, 'NYI: error == undefined, if JS_RETURN is implemented');
    315    }
    316 );
    317 runWasmWithDebugger(
    318    '(module (func (unreachable)) (export "test" (func 0)))', undefined,
    319    function (dbg) {
    320        dbg.onEnterFrame = function (frame) {
    321            if (frame.type !== "wasmcall") return;
    322            frame.onPop = function () {
    323                return {return: 2};
    324            }
    325        };
    326    },
    327    function (dbg, result, error) {
    328        assertEq(result, undefined, 'NYI: result == 2, if JS_RETURN is implemented');
    329        assertEq(error != undefined, true, 'NYI: error == undefined, if JS_RETURN is implemented');
    330    }
    331 );
    332 throw "TestComplete";