michael@0: // Test if isInCatchScope properly detects catch blocks. michael@0: michael@0: let g = newGlobal(); michael@0: let dbg = new Debugger(g); michael@0: michael@0: function test(string, mustBeCaught) { michael@0: let index = 0; michael@0: dbg.onExceptionUnwind = function (frame) { michael@0: let willBeCaught = false; michael@0: do { michael@0: if (frame.script.isInCatchScope(frame.offset)) { michael@0: willBeCaught = true; michael@0: break; michael@0: } michael@0: frame = frame.older; michael@0: } while (frame != null); michael@0: assertEq(willBeCaught, mustBeCaught[index++]); michael@0: }; michael@0: michael@0: try { michael@0: g.eval(string); michael@0: } catch (ex) {} michael@0: assertEq(index, mustBeCaught.length); michael@0: } michael@0: michael@0: // Should correctly detect catch blocks michael@0: test("throw new Error();", [false]); michael@0: test("try { throw new Error(); } catch (e) {}", [true]); michael@0: test("try { throw new Error(); } finally {}", [false, false]); michael@0: test("try { throw new Error(); } catch (e) {} finally {}", [true]); michael@0: michael@0: // Source of the exception shouldn't matter michael@0: test("(null)();", [false]); michael@0: test("try { (null)(); } catch (e) {}", [true]); michael@0: test("try { (null)(); } finally {}", [false, false]); michael@0: test("try { (null)(); } catch (e) {} finally {}", [true]); michael@0: michael@0: // Should correctly detect catch blocks in functions michael@0: test("function f() { throw new Error(); } f();", [false, false]); michael@0: test("function f() { try { throw new Error(); } catch (e) {} } f();", [true]); michael@0: test("function f() { try { throw new Error(); } finally {} } f();", [false, false, false]); michael@0: test("function f() { try { throw new Error(); } catch (e) {} finally {} } f();", [true]); michael@0: michael@0: // Should correctly detect catch blocks in evals michael@0: test("eval('throw new Error();')", [false, false]); michael@0: test("eval('try { throw new Error(); } catch (e) {}');", [true]); michael@0: test("eval('try { throw new Error(); } finally {}');", [false, false, false]); michael@0: test("eval('try { throw new Error(); } catch (e) {} finally {}');", [true]); michael@0: michael@0: // Should correctly detect rethrows michael@0: test("try { throw new Error(); } catch (e) { throw e; }", [true, false]); michael@0: test("try { try { throw new Error(); } catch (e) { throw e; } } catch (e) {}", [true, true]); michael@0: test("try { try { throw new Error(); } finally {} } catch (e) {}", [true, true]); michael@0: test("function f() { try { throw new Error(); } catch (e) { throw e; } } f();", [true, false, false]); michael@0: test("function f() { try { try { throw new Error(); } catch (e) { throw e; } } catch (e) {} } f();", [true, true]); michael@0: test("function f() { try { try { throw new Error(); } finally {} } catch (e) {} } f();", [true, true]); michael@0: test("eval('try { throw new Error(); } catch (e) { throw e; }')", [true, false, false]); michael@0: test("eval('try { try { throw new Error(); } catch (e) { throw e; } } catch (e) {}')", [true, true]); michael@0: michael@0: // Should correctly detect catch blocks across frame boundaries michael@0: test("function f() { throw new Error(); } try { f(); } catch (e) {}", [true, true]); michael@0: test("function f() { throw new Error(); } try { f(); } catch (e) { throw e; }", [true, true, false]); michael@0: test("try { eval('throw new Error()'); } catch (e) {}", [true, true]); michael@0: test("try { eval('throw new Error()'); } catch (e) { throw e; }", [true, true, false]); michael@0: michael@0: // Should correctly detect catch blocks just before and just after throws michael@0: test("throw new Error; try {} catch (e) {}", [false]); michael@0: test("try {} catch (e) {} throw new Error();", [false]);