diff options
Diffstat (limited to 'js/src/jit-test/tests/debug/wasm-06.js')
-rw-r--r-- | js/src/jit-test/tests/debug/wasm-06.js | 332 |
1 files changed, 332 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/debug/wasm-06.js b/js/src/jit-test/tests/debug/wasm-06.js new file mode 100644 index 0000000000..d8a8aa8b18 --- /dev/null +++ b/js/src/jit-test/tests/debug/wasm-06.js @@ -0,0 +1,332 @@ +// |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"; |