mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 906963 - Detect whether a bytecode offset is within the scope of a catch statement.
This commit is contained in:
parent
f587d1f5aa
commit
5ca960bd08
64
js/src/jit-test/tests/debug/Script-isInCatchScope.js
Normal file
64
js/src/jit-test/tests/debug/Script-isInCatchScope.js
Normal file
@ -0,0 +1,64 @@
|
||||
// Test if isInCatchScope properly detects catch blocks.
|
||||
|
||||
let g = newGlobal('new-compartment');
|
||||
let dbg = new Debugger(g);
|
||||
|
||||
function test(string, mustBeCaught) {
|
||||
let index = 0;
|
||||
dbg.onExceptionUnwind = function (frame) {
|
||||
let willBeCaught = false;
|
||||
do {
|
||||
if (frame.script.isInCatchScope(frame.offset)) {
|
||||
willBeCaught = true;
|
||||
break;
|
||||
}
|
||||
frame = frame.older;
|
||||
} while (frame != null);
|
||||
assertEq(willBeCaught, mustBeCaught[index++]);
|
||||
};
|
||||
|
||||
try {
|
||||
g.eval(string);
|
||||
} catch (ex) {}
|
||||
assertEq(index, mustBeCaught.length);
|
||||
}
|
||||
|
||||
// Should correctly detect catch blocks
|
||||
test("throw new Error();", [false]);
|
||||
test("try { throw new Error(); } catch (e) {}", [true]);
|
||||
test("try { throw new Error(); } finally {}", [false, false]);
|
||||
test("try { throw new Error(); } catch (e) {} finally {}", [true]);
|
||||
|
||||
// Source of the exception shouldn't matter
|
||||
test("(null)();", [false]);
|
||||
test("try { (null)(); } catch (e) {}", [true]);
|
||||
test("try { (null)(); } finally {}", [false, false]);
|
||||
test("try { (null)(); } catch (e) {} finally {}", [true]);
|
||||
|
||||
// Should correctly detect catch blocks in functions
|
||||
test("function f() { throw new Error(); } f();", [false, false]);
|
||||
test("function f() { try { throw new Error(); } catch (e) {} } f();", [true]);
|
||||
test("function f() { try { throw new Error(); } finally {} } f();", [false, false, false]);
|
||||
test("function f() { try { throw new Error(); } catch (e) {} finally {} } f();", [true]);
|
||||
|
||||
// Should correctly detect catch blocks in evals
|
||||
test("eval('throw new Error();')", [false, false]);
|
||||
test("eval('try { throw new Error(); } catch (e) {}');", [true]);
|
||||
test("eval('try { throw new Error(); } finally {}');", [false, false, false]);
|
||||
test("eval('try { throw new Error(); } catch (e) {} finally {}');", [true]);
|
||||
|
||||
// Should correctly detect rethrows
|
||||
test("try { throw new Error(); } catch (e) { throw e; }", [true, false]);
|
||||
test("try { try { throw new Error(); } catch (e) { throw e; } } catch (e) {}", [true, true]);
|
||||
test("try { try { throw new Error(); } finally {} } catch (e) {}", [true, true]);
|
||||
test("function f() { try { throw new Error(); } catch (e) { throw e; } } f();", [true, false, false]);
|
||||
test("function f() { try { try { throw new Error(); } catch (e) { throw e; } } catch (e) {} } f();", [true, true]);
|
||||
test("function f() { try { try { throw new Error(); } finally {} } catch (e) {} } f();", [true, true]);
|
||||
test("eval('try { throw new Error(); } catch (e) { throw e; }')", [true, false, false]);
|
||||
test("eval('try { try { throw new Error(); } catch (e) { throw e; } } catch (e) {}')", [true, true]);
|
||||
|
||||
// Should correctly detect catch blocks across frame boundaries
|
||||
test("function f() { throw new Error(); } try { f(); } catch (e) {}", [true, true]);
|
||||
test("function f() { throw new Error(); } try { f(); } catch (e) { throw e; }", [true, true, false]);
|
||||
test("try { eval('throw new Error()'); } catch (e) {}", [true, true]);
|
||||
test("try { eval('throw new Error()'); } catch (e) { throw e; }", [true, true, false]);
|
@ -3517,6 +3517,39 @@ DebuggerScript_clearAllBreakpoints(JSContext *cx, unsigned argc, Value *vp)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
DebuggerScript_isInCatchScope(JSContext *cx, unsigned argc, Value* vp)
|
||||
{
|
||||
REQUIRE_ARGC("Debugger.Script.isInCatchScope", 1);
|
||||
THIS_DEBUGSCRIPT_SCRIPT(cx, argc, vp, "isInCatchScope", args, obj, script);
|
||||
|
||||
size_t offset;
|
||||
if (!ScriptOffset(cx, script, 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 (offset - tnBegin->start < tnBegin->length &&
|
||||
tnBegin->kind == JSTRY_CATCH)
|
||||
{
|
||||
args.rval().setBoolean(true);
|
||||
break;
|
||||
}
|
||||
++tnBegin;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
DebuggerScript_construct(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
@ -3546,6 +3579,7 @@ static const JSFunctionSpec DebuggerScript_methods[] = {
|
||||
JS_FN("getBreakpoints", DebuggerScript_getBreakpoints, 1, 0),
|
||||
JS_FN("clearBreakpoint", DebuggerScript_clearBreakpoint, 1, 0),
|
||||
JS_FN("clearAllBreakpoints", DebuggerScript_clearAllBreakpoints, 0, 0),
|
||||
JS_FN("isInCatchScope", DebuggerScript_isInCatchScope, 1, 0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user