// |jit-test| test-also=--wasm-compiler=optimizing; error: TestComplete; skip-if: !wasmDebuggingEnabled()
// Tests that wasm module scripts raises onEnterFrame and onLeaveFrame events.
load(libdir + "asserts.js" );
function runWasmWithDebugger(wast, lib, init, done) {
let g = newGlobal({newCompartment: true });
let dbg = new Debugger(g);
g.eval(`
var wasm = wasmTextToBinary('${wast}' );
var lib = ${lib || 'undefined' };
var m = new WebAssembly.Instance(new WebAssembly.Module(wasm), lib);`);
init(dbg, g);
let result = undefined, error = undefined;
try {
result = g.eval("m.exports.test()" );
} catch (ex) {
error = ex;
}
done(dbg, result, error, g);
}
// Checking if onEnterFrame is fired for wasm frames and verifying the content
// of the frame and environment properties.
var onEnterFrameCalled, onLeaveFrameCalled, onExceptionUnwindCalled, testComplete;
runWasmWithDebugger(
'(module (func (result i32) (i32.const 42)) (export "test" (func 0)))' , undefined,
function (dbg) {
var wasmScript = dbg.findScripts().filter(s => s.format == 'wasm' )[0];
assertEq(!!wasmScript, true );
onEnterFrameCalled = 0;
onLeaveFrameCalled = 0;
testComplete = false ;
var evalFrame;
dbg.onEnterFrame = function (frame) {
if (frame.type !== 'wasmcall' ) {
if (frame.type === 'eval' )
evalFrame = frame;
return ;
}
onEnterFrameCalled++;
assertEq(frame.script, wasmScript);
assertEq(frame.older, evalFrame);
assertEq(frame.type, 'wasmcall' );
let env = frame.environment;
assertEq(env instanceof Object, true );
assertEq(env.inspectable, true );
assertEq(env.parent !== null , true );
assertEq(env.type, 'declarative' );
assertEq(env.calleeScript, null );
assertEq(Array.isArray(env.names()), true );
assertEq(env.names().length, 0);
frame.onPop = function () {
onLeaveFrameCalled++;
testComplete = true ;
};
};
},
function (dbg, result, error) {
assertEq(testComplete, true );
assertEq(onEnterFrameCalled, 1);
assertEq(onLeaveFrameCalled, 1);
assertEq(result, 42);
assertEq(error, undefined);
}
);
// Checking the dbg.getNewestFrame() and frame.older.
runWasmWithDebugger(
'(module (import "env" "ex" (func $fn1)) (func $fn2 (call $fn1)) (export "test" (func $fn2)))' ,
'{env: { ex: () => { }}}' ,
function (dbg) {
onEnterFrameCalled = 0;
onLeaveFrameCalled = 0;
testComplete = false ;
var evalFrame, wasmFrame;
dbg.onEnterFrame = function (frame) {
onEnterFrameCalled++;
assertEq(dbg.getNewestFrame(), frame);
switch (frame.type) {
case 'eval' :
evalFrame = frame;
break ;
case 'wasmcall' :
wasmFrame = frame;
break ;
case 'call' :
assertEq(frame.older, wasmFrame);
assertEq(frame.older.older, evalFrame);
assertEq(frame.older.older.older, null );
testComplete = true ;
break ;
}
frame.onPop = function () {
onLeaveFrameCalled++;
};
};
},
function (dbg, result, error) {
assertEq(testComplete, true );
assertEq(onEnterFrameCalled, 3);
assertEq(onLeaveFrameCalled, 3);
assertEq(error, undefined);
}
);
// Checking if we can enumerate frames and find 'wasmcall' one.
runWasmWithDebugger(
'(module (import "env" "ex" (func $fn1)) (func $fn2 (call $fn1)) (export "test" (func $fn2)))' ,
'{env: { ex: () => { debugger; }}}' ,
function (dbg) {
testComplete = false ;
dbg.onDebuggerStatement = function (frame) {
assertEq(frame.type, 'call' );
assertEq(frame.older.type, 'wasmcall' );
assertEq(frame.older.older.type, 'eval' );
assertEq(frame.older.older.older, null );
testComplete = true ;
}
},
function (dbg, result, error) {
assertEq(testComplete, true );
assertEq(error, undefined);
}
);
// Checking if onPop works without onEnterFrame handler.
runWasmWithDebugger(
'(module (import "env" "ex" (func $fn1)) (func $fn2 (call $fn1)) (export "test" (func $fn2)))' ,
'{env: { ex: () => { debugger; }}}' ,
function (dbg) {
onLeaveFrameCalled = 0;
dbg.onDebuggerStatement = function (frame) {
if (!frame.older || frame.older.type != 'wasmcall' )
return ;
frame.older.onPop = function () {
onLeaveFrameCalled++;
};
}
},
function (dbg, result, error) {
assertEq(onLeaveFrameCalled, 1);
assertEq(error, undefined);
}
);
// Checking if function return values are not changed.
runWasmWithDebugger(
'(module (func (result f64) (f64.const 0.42)) (export "test" (func 0)))' , undefined,
function (dbg) {
dbg.onEnterFrame = function (frame) {
dbg.onPop = function () {};
};
},
function (dbg, result, error) {
assertEq(result, 0.42);
assertEq(error, undefined);
}
);
runWasmWithDebugger(
'(module (func (result f32) (f32.const 4.25)) (export "test" (func 0)))' , undefined,
function (dbg) {
dbg.onEnterFrame = function (frame) {
dbg.onPop = function () {};
};
},
function (dbg, result, error) {
assertEq(result, 4.25);
assertEq(error, undefined);
}
);
// Checking if onEnterFrame/onExceptionUnwind work during exceptions --
// `unreachable` causes wasm to throw WebAssembly.RuntimeError exception.
runWasmWithDebugger(
'(module (func (unreachable)) (export "test" (func 0)))' , undefined,
function (dbg) {
onEnterFrameCalled = 0;
onLeaveFrameCalled = 0;
onExceptionUnwindCalled = 0;
dbg.onEnterFrame = function (frame) {
if (frame.type !== "wasmcall" ) return ;
onEnterFrameCalled++;
frame.onPop = function () {
onLeaveFrameCalled++;
};
};
dbg.onExceptionUnwind = function (frame) {
if (frame.type !== "wasmcall" ) return ;
onExceptionUnwindCalled++;
};
},
function (dbg, result, error, g) {
assertEq(onEnterFrameCalled, 1);
assertEq(onLeaveFrameCalled, 1);
assertEq(onExceptionUnwindCalled, 1);
assertEq(error instanceof g.WebAssembly.RuntimeError, true );
}
);
// Checking if onEnterFrame/onExceptionUnwind work during exceptions
// originated in the JavaScript import call.
runWasmWithDebugger(
'(module (import "env" "ex" (func $fn1)) (func $fn2 (call $fn1)) (export "test" (func $fn2)))' ,
'{env: { ex: () => { throw new Error(); }}}' ,
function (dbg) {
onEnterFrameCalled = 0;
onLeaveFrameCalled = 0;
onExceptionUnwindCalled = 0;
dbg.onEnterFrame = function (frame) {
if (frame.type !== "wasmcall" ) return ;
onEnterFrameCalled++;
frame.onPop = function () {
onLeaveFrameCalled++;
};
};
dbg.onExceptionUnwind = function (frame) {
if (frame.type !== "wasmcall" ) return ;
onExceptionUnwindCalled++;
};
},
function (dbg, result, error, g) {
assertEq(onEnterFrameCalled, 1);
assertEq(onLeaveFrameCalled, 1);
assertEq(onExceptionUnwindCalled, 1);
assertEq(error instanceof g.Error, true );
}
);
// Checking throwing in the handler.
runWasmWithDebugger(
'(module (func (unreachable)) (export "test" (func 0)))' , undefined,
function (dbg) {
dbg.uncaughtExceptionHook = function (value) {
assertEq(value instanceof Error, true );
return {throw : 'test' };
};
dbg.onEnterFrame = function (frame) {
if (frame.type !== "wasmcall" ) return ;
throw new Error();
};
},
function (dbg, result, error) {
assertEq(error, 'test' );
}
);
runWasmWithDebugger(
'(module (func (unreachable)) (export "test" (func 0)))' , undefined,
function (dbg) {
dbg.uncaughtExceptionHook = function (value) {
assertEq(value instanceof Error, true );
return {throw : 'test' };
};
dbg.onEnterFrame = function (frame) {
if (frame.type !== "wasmcall" ) return ;
frame.onPop = function () {
throw new Error();
}
};
},
function (dbg, result, error) {
assertEq(error, 'test' );
}
);
// Checking resumption values for JS_THROW.
runWasmWithDebugger(
'(module (func (nop)) (export "test" (func 0)))' , undefined,
function (dbg, g) {
dbg.onEnterFrame = function (frame) {
if (frame.type !== "wasmcall" ) return ;
return {throw : 'test' };
};
},
function (dbg, result, error, g) {
assertEq(error, 'test' );
}
);
runWasmWithDebugger(
'(module (func (nop)) (export "test" (func 0)))' , undefined,
function (dbg, g) {
dbg.onEnterFrame = function (frame) {
if (frame.type !== "wasmcall" ) return ;
frame.onPop = function () {
return {throw : 'test' };
}
};
},
function (dbg, result, error, g) {
assertEq(error, 'test' );
}
);
// Checking resumption values for JS_RETURN (not implemented by wasm baseline).
runWasmWithDebugger(
'(module (func (unreachable)) (export "test" (func 0)))' , undefined,
function (dbg) {
dbg.onEnterFrame = function (frame) {
if (frame.type !== "wasmcall" ) return ;
return {return : 2};
};
},
function (dbg, result, error) {
assertEq(result, undefined, 'NYI: result == 2, if JS_RETURN is implemented' );
assertEq(error != undefined, true , 'NYI: error == undefined, if JS_RETURN is implemented' );
}
);
runWasmWithDebugger(
'(module (func (unreachable)) (export "test" (func 0)))' , undefined,
function (dbg) {
dbg.onEnterFrame = function (frame) {
if (frame.type !== "wasmcall" ) return ;
frame.onPop = function () {
return {return : 2};
}
};
},
function (dbg, result, error) {
assertEq(result, undefined, 'NYI: result == 2, if JS_RETURN is implemented' );
assertEq(error != undefined, true , 'NYI: error == undefined, if JS_RETURN is implemented' );
}
);
throw "TestComplete" ;
Messung V0.5 C=96 H=96 G=95
¤ Dauer der Verarbeitung: 0.10 Sekunden
(vorverarbeitet)
¤
*© Formatika GbR, Deutschland