summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/debug/wasm-06.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit-test/tests/debug/wasm-06.js')
-rw-r--r--js/src/jit-test/tests/debug/wasm-06.js332
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";