From 5cb89346cc970c75cea65603810d1ba211e52dc9 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Thu, 2 Mar 2017 22:28:01 -0600 Subject: [PATCH] Bug 1343579 - Implements Debugger.Script.isInCatchScope for wasm scripts. r=shu MozReview-Commit-ID: 29wj8APhtXW --HG-- extra : rebase_source : f386750b18ffea1101fa709c3d73a538dd52e909 --- js/src/jit-test/tests/debug/bug1343579.js | 26 ++++++ js/src/jit-test/tests/debug/wasm-04.js | 1 - js/src/vm/Debugger.cpp | 105 ++++++++++++---------- 3 files changed, 86 insertions(+), 46 deletions(-) create mode 100644 js/src/jit-test/tests/debug/bug1343579.js diff --git a/js/src/jit-test/tests/debug/bug1343579.js b/js/src/jit-test/tests/debug/bug1343579.js new file mode 100644 index 000000000000..61c69ed50955 --- /dev/null +++ b/js/src/jit-test/tests/debug/bug1343579.js @@ -0,0 +1,26 @@ +// |jit-test| test-also-wasm-baseline +// Checking if Debugger.Script.isInCatchScope return false for wasm. + +load(libdir + "wasm.js"); + +var results; +wasmRunWithDebugger( + '(module (memory 1) ' + + '(func $func0 i32.const 1000000 i32.load drop) ' + + '(func (export "test") call $func0))', + undefined, + function ({dbg, wasmScript}) { + results = []; + dbg.onExceptionUnwind = function (frame, value) { + if (frame.type != 'wasmcall') return; + var result = wasmScript.isInCatchScope(frame.offset); + results.push(result); + }; + }, + function ({error}) { + assertEq(error !== undefined, true); + assertEq(results.length, 2); + assertEq(results[0], false); + assertEq(results[1], false); + } +); diff --git a/js/src/jit-test/tests/debug/wasm-04.js b/js/src/jit-test/tests/debug/wasm-04.js index 88dca886e01e..a8ed8e261840 100644 --- a/js/src/jit-test/tests/debug/wasm-04.js +++ b/js/src/jit-test/tests/debug/wasm-04.js @@ -25,5 +25,4 @@ assertThrowsInstanceOf(() => s.getChildScripts(), Error); assertThrowsInstanceOf(() => s.getAllOffsets(), Error); assertThrowsInstanceOf(() => s.getAllColumnOffsets(), Error); assertThrowsInstanceOf(() => s.getBreakpoint(0), Error); -assertThrowsInstanceOf(() => s.isInCatchScope(0), Error); assertThrowsInstanceOf(() => s.getOffsetsCoverage(), Error); diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index f44e1e9da53f..8bb44714a4c2 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -5859,22 +5859,12 @@ ScriptOffset(JSContext* cx, const Value& v, size_t* offsetp) } static bool -ScriptOffset(JSContext* cx, JSScript* script, const Value& v, size_t* offsetp) +EnsureScriptOffsetIsValid(JSContext* cx, JSScript* script, size_t offset) { - double d; - size_t off; - - bool ok = v.isNumber(); - if (ok) { - d = v.toNumber(); - off = size_t(d); - } - if (!ok || off != d || !IsValidBytecodeOffset(cx, script, off)) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DEBUG_BAD_OFFSET); - return false; - } - *offsetp = off; - return true; + if (IsValidBytecodeOffset(cx, script, offset)) + return true; + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DEBUG_BAD_OFFSET); + return false; } namespace { @@ -6179,10 +6169,8 @@ class DebuggerScriptGetOffsetLocationMatcher : cx_(cx), offset_(offset), result_(result) { } using ReturnType = bool; ReturnType match(HandleScript script) { - if (!IsValidBytecodeOffset(cx_, script, offset_)) { - JS_ReportErrorNumberASCII(cx_, GetErrorMessage, nullptr, JSMSG_DEBUG_BAD_OFFSET); + if (!EnsureScriptOffsetIsValid(cx_, script, offset_)) return false; - } FlowGraphSummary flowData(cx_); if (!flowData.populate(cx_, script)) @@ -6741,10 +6729,8 @@ struct DebuggerScriptSetBreakpointMatcher return false; } - if (!IsValidBytecodeOffset(cx_, script, offset_)) { - JS_ReportErrorNumberASCII(cx_, GetErrorMessage, nullptr, JSMSG_DEBUG_BAD_OFFSET); + if (!EnsureScriptOffsetIsValid(cx_, script, offset_)) return false; - } // Ensure observability *before* setting the breakpoint. If the script is // not already a debuggee, trying to ensure observability after setting @@ -6815,7 +6801,7 @@ DebuggerScript_getBreakpoints(JSContext* cx, unsigned argc, Value* vp) jsbytecode* pc; if (args.length() > 0) { size_t offset; - if (!ScriptOffset(cx, script, args[0], &offset)) + if (!ScriptOffset(cx, args[0], &offset) || !EnsureScriptOffsetIsValid(cx, script, offset)) return false; pc = script->offsetToPC(offset); } else { @@ -6898,38 +6884,67 @@ DebuggerScript_clearAllBreakpoints(JSContext* cx, unsigned argc, Value* vp) return true; } +class DebuggerScriptIsInCatchScopeMatcher +{ + JSContext* cx_; + size_t offset_; + bool isInCatch_; + + public: + explicit DebuggerScriptIsInCatchScopeMatcher(JSContext* cx, size_t offset) : cx_(cx), offset_(offset) { } + using ReturnType = bool; + + inline bool isInCatch() const { return isInCatch_; } + + ReturnType match(HandleScript script) { + if (!EnsureScriptOffsetIsValid(cx_, script, offset_)) + return false; + + /* + * Try note ranges are relative to the mainOffset of the script, so adjust + * offset accordingly. + */ + size_t offset = offset_ - script->mainOffset(); + + if (script->hasTrynotes()) { + JSTryNote* tnBegin = script->trynotes()->vector; + JSTryNote* tnEnd = tnBegin + script->trynotes()->length; + while (tnBegin != tnEnd) { + if (tnBegin->start <= offset && + offset <= tnBegin->start + tnBegin->length && + tnBegin->kind == JSTRY_CATCH) + { + isInCatch_ = true; + return true; + } + ++tnBegin; + } + } + isInCatch_ = false; + return true; + } + + ReturnType match(Handle instance) { + isInCatch_ = false; + return true; + } +}; + static bool DebuggerScript_isInCatchScope(JSContext* cx, unsigned argc, Value* vp) { - THIS_DEBUGSCRIPT_SCRIPT(cx, argc, vp, "isInCatchScope", args, obj, script); + THIS_DEBUGSCRIPT_REFERENT(cx, argc, vp, "isInCatchScope", args, obj, referent); if (!args.requireAtLeast(cx, "Debugger.Script.isInCatchScope", 1)) return false; size_t offset; - if (!ScriptOffset(cx, script, args[0], &offset)) + if (!ScriptOffset(cx, args[0], &offset)) return false; - /* - * Try note ranges are relative to the mainOffset of the script, so adjust - * offset accordingly. - */ - offset -= script->mainOffset(); - - args.rval().setBoolean(false); - if (script->hasTrynotes()) { - JSTryNote* tnBegin = script->trynotes()->vector; - JSTryNote* tnEnd = tnBegin + script->trynotes()->length; - while (tnBegin != tnEnd) { - if (tnBegin->start <= offset && - offset <= tnBegin->start + tnBegin->length && - tnBegin->kind == JSTRY_CATCH) - { - args.rval().setBoolean(true); - break; - } - ++tnBegin; - } - } + DebuggerScriptIsInCatchScopeMatcher matcher(cx, offset); + if (!referent.match(matcher)) + return false; + args.rval().setBoolean(matcher.isInCatch()); return true; }