diff --git a/js/src/jit-test/tests/debug/Debug-ctor.js b/js/src/jit-test/tests/debug/Debug-ctor-01.js similarity index 71% rename from js/src/jit-test/tests/debug/Debug-ctor.js rename to js/src/jit-test/tests/debug/Debug-ctor-01.js index 6d07a045858..cd95aad4790 100644 --- a/js/src/jit-test/tests/debug/Debug-ctor.js +++ b/js/src/jit-test/tests/debug/Debug-ctor-01.js @@ -1,5 +1,3 @@ -// |jit-test| debug - load(libdir + 'asserts.js'); // Debug rejects arguments that aren't cross-compartment wrappers. @@ -21,14 +19,3 @@ var g = newGlobal('new-compartment'); var dbg = new Debug(g); assertEq(dbg instanceof Debug, true); assertEq(Object.getPrototypeOf(dbg), Debug.prototype); - -// The reverse. -var g2 = newGlobal('new-compartment'); -g2.debuggeeGlobal = this; -g2.eval("var dbg = new Debug(debuggeeGlobal);"); -assertEq(g2.eval("dbg instanceof Debug"), true); - -// The Debug constructor from this compartment will not accept as its argument -// an Object from this compartment. Shenanigans won't fool the membrane. -g2.outer = this; -assertThrowsInstanceOf(function () { g2.eval("outer.Debug(outer.Object())"); }, TypeError); diff --git a/js/src/jit-test/tests/debug/Debug-ctor-02.js b/js/src/jit-test/tests/debug/Debug-ctor-02.js new file mode 100644 index 00000000000..eadafd84e04 --- /dev/null +++ b/js/src/jit-test/tests/debug/Debug-ctor-02.js @@ -0,0 +1,17 @@ +// |jit-test| debug +// Test creating a Debug in a sandbox, debugging the initial global. +// +// This requires debug mode to already be on in the initial global, since it's +// always on the stack in the shell. Hence the |jit-test| tag. + +load(libdir + 'asserts.js'); + +var g = newGlobal('new-compartment'); +g.debuggeeGlobal = this; +g.eval("var dbg = new Debug(debuggeeGlobal);"); +assertEq(g.eval("dbg instanceof Debug"), true); + +// The Debug constructor from this compartment will not accept as its argument +// an Object from this compartment. Shenanigans won't fool the membrane. +g.parent = this; +assertThrowsInstanceOf(function () { g.eval("parent.Debug(parent.Object())"); }, TypeError); diff --git a/js/src/jit-test/tests/debug/Debug-ctor-03.js b/js/src/jit-test/tests/debug/Debug-ctor-03.js new file mode 100644 index 00000000000..0b4d1e9aecb --- /dev/null +++ b/js/src/jit-test/tests/debug/Debug-ctor-03.js @@ -0,0 +1,6 @@ +// If the debuggee cannot be put into debug mode, throw. +var g = newGlobal('new-compartment'); +g.libdir = libdir; +g.eval("load(libdir + 'asserts.js');"); +g.parent = this; +g.eval("assertThrowsInstanceOf(function () { new Debug(parent); }, Error);"); diff --git a/js/src/jit-test/tests/debug/Debug-debuggees-01.js b/js/src/jit-test/tests/debug/Debug-debuggees-01.js index f2a2893898e..770d2e35992 100644 --- a/js/src/jit-test/tests/debug/Debug-debuggees-01.js +++ b/js/src/jit-test/tests/debug/Debug-debuggees-01.js @@ -1,4 +1,3 @@ -// |jit-test| debug // A Debug object created with no argument initially has no debuggees. var dbg = new Debug; var debuggees = dbg.getDebuggees(); diff --git a/js/src/jit-test/tests/debug/Debug-debuggees-02.js b/js/src/jit-test/tests/debug/Debug-debuggees-02.js index 3a4d5ea200e..a606625bab0 100644 --- a/js/src/jit-test/tests/debug/Debug-debuggees-02.js +++ b/js/src/jit-test/tests/debug/Debug-debuggees-02.js @@ -1,5 +1,4 @@ -// |jit-test| debug -// The array returned by getDebuggees is just a snapshot, not live +// The array returned by getDebuggees is just a snapshot, not live. var dbg = new Debug; var a1 = dbg.getDebuggees(); var g = newGlobal('new-compartment'); diff --git a/js/src/jit-test/tests/debug/Debug-debuggees-03.js b/js/src/jit-test/tests/debug/Debug-debuggees-03.js index 36b931a8fd2..12e3857dcc2 100644 --- a/js/src/jit-test/tests/debug/Debug-debuggees-03.js +++ b/js/src/jit-test/tests/debug/Debug-debuggees-03.js @@ -1,4 +1,3 @@ -// |jit-test| debug // Debug hooks fire based on debuggees. var g1 = newGlobal('new-compartment'); diff --git a/js/src/jit-test/tests/debug/Debug-debuggees-04.js b/js/src/jit-test/tests/debug/Debug-debuggees-04.js index 725422452e5..5f78d264c13 100644 --- a/js/src/jit-test/tests/debug/Debug-debuggees-04.js +++ b/js/src/jit-test/tests/debug/Debug-debuggees-04.js @@ -1,4 +1,3 @@ -// |jit-test| debug // hasDebuggee tests. var g1 = newGlobal('new-compartment'), g1w; diff --git a/js/src/jit-test/tests/debug/Debug-debuggees-05.js b/js/src/jit-test/tests/debug/Debug-debuggees-05.js index 7599e25b382..f8aa79cf882 100644 --- a/js/src/jit-test/tests/debug/Debug-debuggees-05.js +++ b/js/src/jit-test/tests/debug/Debug-debuggees-05.js @@ -1,4 +1,3 @@ -// |jit-test| debug // addDebuggee returns different Debug.Object wrappers for different Debug objects. var g = newGlobal('new-compartment'); diff --git a/js/src/jit-test/tests/debug/Debug-debuggees-06.js b/js/src/jit-test/tests/debug/Debug-debuggees-06.js index ccc2614f99a..13a82dc8503 100644 --- a/js/src/jit-test/tests/debug/Debug-debuggees-06.js +++ b/js/src/jit-test/tests/debug/Debug-debuggees-06.js @@ -1,4 +1,3 @@ -// |jit-test| debug // {has,add,remove}Debuggee throw a TypeError if the argument is invalid. load(libdir + "asserts.js"); diff --git a/js/src/jit-test/tests/debug/Debug-debuggees-07.js b/js/src/jit-test/tests/debug/Debug-debuggees-07.js index 691dc991a4e..6d38a878819 100644 --- a/js/src/jit-test/tests/debug/Debug-debuggees-07.js +++ b/js/src/jit-test/tests/debug/Debug-debuggees-07.js @@ -1,4 +1,3 @@ -// |jit-test| debug // Handle proto-less objects passed to addDebuggee. var g = newGlobal('new-compartment'); diff --git a/js/src/jit-test/tests/debug/Debug-debuggees-08.js b/js/src/jit-test/tests/debug/Debug-debuggees-08.js index a81e9fa4d9d..facf01abe42 100644 --- a/js/src/jit-test/tests/debug/Debug-debuggees-08.js +++ b/js/src/jit-test/tests/debug/Debug-debuggees-08.js @@ -1,4 +1,3 @@ -// |jit-test| debug // addDebuggee(obj), where obj is not global, adds obj's global. // Adding a debuggee more than once is redundant. diff --git a/js/src/jit-test/tests/debug/Debug-debuggees-10.js b/js/src/jit-test/tests/debug/Debug-debuggees-10.js index 4c3038ffd42..8dcaa1aa02a 100644 --- a/js/src/jit-test/tests/debug/Debug-debuggees-10.js +++ b/js/src/jit-test/tests/debug/Debug-debuggees-10.js @@ -1,6 +1,4 @@ -// |jit-test| debug // Allow diamonds in the graph of the compartment "debugs" relation. - var program = newGlobal('new-compartment'); var d1 = newGlobal('new-compartment'); d1.top = this; diff --git a/js/src/jit-test/tests/debug/Debug-debuggees-12.js b/js/src/jit-test/tests/debug/Debug-debuggees-12.js index 5e9be612871..944aa854927 100644 --- a/js/src/jit-test/tests/debug/Debug-debuggees-12.js +++ b/js/src/jit-test/tests/debug/Debug-debuggees-12.js @@ -1,6 +1,4 @@ -// |jit-test| debug // Events in a non-debuggee are ignored, even if a debuggee is in the same compartment. - var g1 = newGlobal('new-compartment'); var g2 = g1.eval("newGlobal('same-compartment')"); var dbg = new Debug(g1); diff --git a/js/src/jit-test/tests/debug/Debug-debuggees-13.js b/js/src/jit-test/tests/debug/Debug-debuggees-13.js index c71e8978a41..0aed7aa254d 100644 --- a/js/src/jit-test/tests/debug/Debug-debuggees-13.js +++ b/js/src/jit-test/tests/debug/Debug-debuggees-13.js @@ -1,6 +1,4 @@ -// |jit-test| debug // Removing a debuggee does not detach the debugger from a compartment if another debuggee is in it. - var g1 = newGlobal('new-compartment'); var g2 = g1.eval("newGlobal('same-compartment')"); var dbg = new Debug(g1, g2); diff --git a/js/src/jit-test/tests/debug/Debug-debuggees-14.js b/js/src/jit-test/tests/debug/Debug-debuggees-14.js index 6e19e218273..2329bb5641d 100644 --- a/js/src/jit-test/tests/debug/Debug-debuggees-14.js +++ b/js/src/jit-test/tests/debug/Debug-debuggees-14.js @@ -1,11 +1,7 @@ -// Reject non-debug-mode debuggees without asserting. - -load(libdir + "asserts.js"); - -function f() { - var v = new Debug; - var g = newGlobal('new-compartment'); - v.addDebuggee(g); // don't assert -} - -assertThrowsInstanceOf(f, Error); +// Adding a debuggee in a compartment that is already in debug mode works +// even if a script from that compartment is on the stack. +var g = newGlobal('new-compartment'); +var dbg1 = Debug(g); +var dbg2 = Debug(); +g.parent = this; +g.eval("parent.dbg2.addDebuggee(this);"); diff --git a/js/src/jit-test/tests/debug/Debug-enabled-01.js b/js/src/jit-test/tests/debug/Debug-enabled-01.js index e4041379778..9e4ad316961 100644 --- a/js/src/jit-test/tests/debug/Debug-enabled-01.js +++ b/js/src/jit-test/tests/debug/Debug-enabled-01.js @@ -1,5 +1,3 @@ -// |jit-test| debug - var desc = Object.getOwnPropertyDescriptor(Debug.prototype, "enabled"); assertEq(typeof desc.get, 'function'); assertEq(typeof desc.set, 'function'); diff --git a/js/src/jit-test/tests/debug/Debug-getYoungestFrame-01.js b/js/src/jit-test/tests/debug/Debug-getYoungestFrame-01.js index 38d58cc1b6d..4cc56970f02 100644 --- a/js/src/jit-test/tests/debug/Debug-getYoungestFrame-01.js +++ b/js/src/jit-test/tests/debug/Debug-getYoungestFrame-01.js @@ -1,4 +1,3 @@ -// |jit-test| debug // getYoungestFrame basics. load(libdir + "asserts.js"); diff --git a/js/src/jit-test/tests/debug/Debug-getYoungestFrame-02.js b/js/src/jit-test/tests/debug/Debug-getYoungestFrame-02.js index fdffa6aa401..53be1a4e3d7 100644 --- a/js/src/jit-test/tests/debug/Debug-getYoungestFrame-02.js +++ b/js/src/jit-test/tests/debug/Debug-getYoungestFrame-02.js @@ -1,4 +1,3 @@ -// |jit-test| debug // Hooks and Debug.prototype.getYoungestFrame produce the same Frame object. var g = newGlobal('new-compartment'); diff --git a/js/src/jit-test/tests/debug/Debug-multi-01.js b/js/src/jit-test/tests/debug/Debug-multi-01.js index 27ba90a890e..5b9255df418 100644 --- a/js/src/jit-test/tests/debug/Debug-multi-01.js +++ b/js/src/jit-test/tests/debug/Debug-multi-01.js @@ -1,4 +1,3 @@ -// |jit-test| debug // When there are multiple debuggers, their hooks are called in order. var g = newGlobal('new-compartment'); diff --git a/js/src/jit-test/tests/debug/Debug-multi-02.js b/js/src/jit-test/tests/debug/Debug-multi-02.js index 59a448df3f6..a24f86aa3cb 100644 --- a/js/src/jit-test/tests/debug/Debug-multi-02.js +++ b/js/src/jit-test/tests/debug/Debug-multi-02.js @@ -1,4 +1,3 @@ -// |jit-test| debug // Test adding hooks during dispatch. The behavior is deterministic and "nice", // but mainly what we are checking here is that we do not crash due to // modifying a data structure while we're iterating over it. diff --git a/js/src/jit-test/tests/debug/Debug-multi-03.js b/js/src/jit-test/tests/debug/Debug-multi-03.js index 1a495149ed1..ed78138021a 100644 --- a/js/src/jit-test/tests/debug/Debug-multi-03.js +++ b/js/src/jit-test/tests/debug/Debug-multi-03.js @@ -1,4 +1,3 @@ -// |jit-test| debug // Q: But who shall debug the debuggers? A: jimb var log = ''; diff --git a/js/src/jit-test/tests/debug/Frame-01.js b/js/src/jit-test/tests/debug/Frame-01.js index 1ed41e146c7..ee9b502169e 100644 --- a/js/src/jit-test/tests/debug/Frame-01.js +++ b/js/src/jit-test/tests/debug/Frame-01.js @@ -1,70 +1,33 @@ -// |jit-test| debug // Test .type and .generator fields of topmost stack frame passed to debuggerHandler. var g = newGlobal('new-compartment'); -g.debuggeeGlobal = this; -g.eval("var hits;"); -g.eval("(" + function () { - var dbg = Debug(debuggeeGlobal); - dbg.hooks = { - debuggerHandler: function (f) { - // print(uneval(expected)); - assertEq(Object.getPrototypeOf(f), Debug.Frame.prototype); - assertEq(f.type, expected.type); - assertEq(f.generator, expected.generator); - assertEq(f.constructing, expected.constructing); - hits++; - } - }; - } + ")()"); +var dbg = Debug(g); +var expected, hits; +dbg.hooks = { + debuggerHandler: function (f) { + assertEq(Object.getPrototypeOf(f), Debug.Frame.prototype); + assertEq(f.type, expected.type); + assertEq(f.generator, expected.generator); + assertEq(f.constructing, expected.constructing); + hits++; + } +}; -g.expected = { type:"global", generator:false, constructing:false }; -g.hits = 0; -debugger; -assertEq(g.hits, 1); - -g.expected = { type:"call", generator:false, constructing:false }; -g.hits = 0; -(function () { debugger; })(); -assertEq(g.hits, 1); - -g.expected = { type:"call", generator:false, constructing:true }; -g.hits = 0; -new function() { debugger; }; -assertEq(g.hits, 1); - -g.expected = { type:"call", generator:false, constructing:false }; -g.hits = 0; -new function () { - (function() { debugger; })(); - assertEq(g.hits, 1); +function test(code, expectobj, expectedHits) { + expected = expectobj; + hits = 0; + g.evaluate(code); + assertEq(hits, arguments.length < 3 ? 1 : expectedHits); } -g.expected = { type:"eval", generator:false, constructing:false }; -g.hits = 0; -eval("debugger;"); -assertEq(g.hits, 1); - -g.expected = { type:"eval", generator:false, constructing:false }; -g.hits = 0; -this.eval("debugger;"); // indirect eval -assertEq(g.hits, 1); - -g.expected = { type:"eval", generator:false, constructing:false }; -g.hits = 0; -(function () { eval("debugger;"); })(); -assertEq(g.hits, 1); - -g.expected = { type:"eval", generator:false, constructing:false }; -g.hits = 0; -new function () { - eval("debugger"); - assertEq(g.hits, 1); -} - -g.expected = { type:"call", generator:true, constructing:false }; -g.hits = 0; -function gen() { debugger; yield 1; debugger; } -for (var x in gen()) { -} -assertEq(g.hits, 2); +test("debugger;", {type: "global", generator: false, constructing: false}); +test("(function () { debugger; })();", {type: "call", generator: false, constructing: false}); +test("new function() { debugger; };", {type: "call", generator: false, constructing: true}); +test("new function () { (function() { debugger; })(); }", {type: "call", generator: false, constructing: false}); +test("eval('debugger;');", {type: "eval", generator: false, constructing: false}); +test("this.eval('debugger;'); // indirect eval", {type: "eval", generator: false, constructing: false}); +test("(function () { eval('debugger;'); })();", {type: "eval", generator: false, constructing: false}); +test("new function () { eval('debugger'); }", {type: "eval", generator: false, constructing: false}); +test("function gen() { debugger; yield 1; debugger; }\n" + + "for (var x in gen()) {}\n", + {type: "call", generator: true, constructing: false}, 2); diff --git a/js/src/jit-test/tests/debug/Frame-02.js b/js/src/jit-test/tests/debug/Frame-02.js index 0ebad76a26e..99305eee97e 100644 --- a/js/src/jit-test/tests/debug/Frame-02.js +++ b/js/src/jit-test/tests/debug/Frame-02.js @@ -1,35 +1,26 @@ -// |jit-test| debug // When the debugger is triggered twice from the same stack frame, the same // Debug.Frame object must be passed to the hook both times. var g = newGlobal('new-compartment'); -g.debuggeeGlobal = this; -g.eval("var hits, frame;"); -g.eval("(" + function () { - var dbg = Debug(debuggeeGlobal); - dbg.hooks = { - debuggerHandler: function (f) { - if (hits++ == 0) - frame = f; - else - assertEq(f, frame); - } - }; - } + ")()"); +var hits, frame; +var dbg = Debug(g); +dbg.hooks = { + debuggerHandler: function (f) { + if (hits++ == 0) + frame = f; + else + assertEq(f, frame); + } +}; -g.hits = 0; -debugger; -debugger; -assertEq(g.hits, 2); +hits = 0; +g.evaluate("debugger; debugger;"); +assertEq(hits, 2); -g.hits = 0; -function f() { - debugger; - debugger; -} -f(); -assertEq(g.hits, 2); +hits = 0; +g.evaluate("function f() { debugger; debugger; } f();"); +assertEq(hits, 2); -g.hits = 0; -eval("debugger; debugger;"); -assertEq(g.hits, 2); +hits = 0; +g.evaluate("eval('debugger; debugger;');"); +assertEq(hits, 2); diff --git a/js/src/jit-test/tests/debug/Frame-03.js b/js/src/jit-test/tests/debug/Frame-03.js index 55ef8d86e78..3d19ca6e2a7 100644 --- a/js/src/jit-test/tests/debug/Frame-03.js +++ b/js/src/jit-test/tests/debug/Frame-03.js @@ -1,26 +1,21 @@ -// |jit-test| debug // When the debugger is triggered from different stack frames that happen to // occupy the same memory, it must deliver different Debug.Frame objects. var g = newGlobal('new-compartment'); -g.debuggeeGlobal = this; -g.eval("var hits;"); -g.eval("(" + function () { - var a = []; - var dbg = Debug(debuggeeGlobal); - dbg.hooks = { - debuggerHandler: function (frame) { - for (var i = 0; i < a.length; i++) - assertEq(a[i] === frame, false); - a.push(frame); - hits++; - } - }; - } + ")()"); +var dbg = Debug(g); +var hits; +var a = []; +dbg.hooks = { + debuggerHandler: function (frame) { + for (var i = 0; i < a.length; i++) + assertEq(a[i] === frame, false); + a.push(frame); + hits++; + } +}; -function f() { debugger; } -function h() { debugger; f(); } -g.hits = 0; -for (var i = 0; i < 4; i++) - h(); -assertEq(g.hits, 8); +g.eval("function f() { debugger; }"); +g.eval("function h() { debugger; f(); }"); +hits = 0; +g.eval("for (var i = 0; i < 4; i++) h();"); +assertEq(hits, 8); diff --git a/js/src/jit-test/tests/debug/Frame-arguments-01.js b/js/src/jit-test/tests/debug/Frame-arguments-01.js index 7c6099b5b31..b243a94abb7 100644 --- a/js/src/jit-test/tests/debug/Frame-arguments-01.js +++ b/js/src/jit-test/tests/debug/Frame-arguments-01.js @@ -1,4 +1,3 @@ -// |jit-test| debug // Frame.prototype.arguments with primitive values var g = newGlobal('new-compartment'); diff --git a/js/src/jit-test/tests/debug/Frame-arguments-02.js b/js/src/jit-test/tests/debug/Frame-arguments-02.js index 2e1a6418707..ae6deb2a12e 100644 --- a/js/src/jit-test/tests/debug/Frame-arguments-02.js +++ b/js/src/jit-test/tests/debug/Frame-arguments-02.js @@ -1,4 +1,3 @@ -// |jit-test| debug // Object arguments. var g = newGlobal('new-compartment'); diff --git a/js/src/jit-test/tests/debug/Frame-arguments-03.js b/js/src/jit-test/tests/debug/Frame-arguments-03.js index ee7d7a6d4d1..8284ebeb87c 100644 --- a/js/src/jit-test/tests/debug/Frame-arguments-03.js +++ b/js/src/jit-test/tests/debug/Frame-arguments-03.js @@ -1,4 +1,3 @@ -// |jit-test| debug // Destructuring arguments. var g = newGlobal('new-compartment'); diff --git a/js/src/jit-test/tests/debug/Frame-arguments-04.js b/js/src/jit-test/tests/debug/Frame-arguments-04.js index 57b5457149d..c618e6b3e89 100644 --- a/js/src/jit-test/tests/debug/Frame-arguments-04.js +++ b/js/src/jit-test/tests/debug/Frame-arguments-04.js @@ -1,4 +1,3 @@ -// |jit-test| debug // frame.arguments works for all live frames var g = newGlobal('new-compartment'); diff --git a/js/src/jit-test/tests/debug/Frame-arguments-05.js b/js/src/jit-test/tests/debug/Frame-arguments-05.js index 57ee49de83a..ca2b161d924 100644 --- a/js/src/jit-test/tests/debug/Frame-arguments-05.js +++ b/js/src/jit-test/tests/debug/Frame-arguments-05.js @@ -1,4 +1,3 @@ -// |jit-test| debug // frame.arguments is "live" (it reflects assignments to arguments). var g = newGlobal('new-compartment'); diff --git a/js/src/jit-test/tests/debug/Frame-arguments-06.js b/js/src/jit-test/tests/debug/Frame-arguments-06.js index d9cb415ff9c..e8957888b6c 100644 --- a/js/src/jit-test/tests/debug/Frame-arguments-06.js +++ b/js/src/jit-test/tests/debug/Frame-arguments-06.js @@ -1,4 +1,3 @@ -// |jit-test| debug // Test extracting frame.arguments element getters and calling them in // various awkward ways. diff --git a/js/src/jit-test/tests/debug/Frame-eval-01.js b/js/src/jit-test/tests/debug/Frame-eval-01.js index 6d57b1ffb4e..57b6f8c8224 100644 --- a/js/src/jit-test/tests/debug/Frame-eval-01.js +++ b/js/src/jit-test/tests/debug/Frame-eval-01.js @@ -1,4 +1,3 @@ -// |jit-test| debug // simplest possible test of Debug.Frame.prototype.eval var g = newGlobal('new-compartment'); diff --git a/js/src/jit-test/tests/debug/Frame-eval-02.js b/js/src/jit-test/tests/debug/Frame-eval-02.js index 5cf5b04285b..daaacc1afce 100644 --- a/js/src/jit-test/tests/debug/Frame-eval-02.js +++ b/js/src/jit-test/tests/debug/Frame-eval-02.js @@ -1,4 +1,3 @@ -// |jit-test| debug // frame.eval() throws if frame is not live load(libdir + "asserts.js"); diff --git a/js/src/jit-test/tests/debug/Frame-eval-03.js b/js/src/jit-test/tests/debug/Frame-eval-03.js index 51410c382ff..13f1412627b 100644 --- a/js/src/jit-test/tests/debug/Frame-eval-03.js +++ b/js/src/jit-test/tests/debug/Frame-eval-03.js @@ -1,4 +1,3 @@ -// |jit-test| debug // Test eval-ing names in a topmost script frame load(libdir + "asserts.js"); diff --git a/js/src/jit-test/tests/debug/Frame-eval-04.js b/js/src/jit-test/tests/debug/Frame-eval-04.js index 48bb1b05ee3..73017cfe5d7 100644 --- a/js/src/jit-test/tests/debug/Frame-eval-04.js +++ b/js/src/jit-test/tests/debug/Frame-eval-04.js @@ -1,4 +1,3 @@ -// |jit-test| debug // frame.eval SyntaxErrors are reflected, not thrown var g = newGlobal('new-compartment'); diff --git a/js/src/jit-test/tests/debug/Frame-eval-05.js b/js/src/jit-test/tests/debug/Frame-eval-05.js index 8e48b20832c..986a18622eb 100644 --- a/js/src/jit-test/tests/debug/Frame-eval-05.js +++ b/js/src/jit-test/tests/debug/Frame-eval-05.js @@ -1,4 +1,3 @@ -// |jit-test| debug // var declarations in strict frame.eval do not modify the frame var g = newGlobal('new-compartment'); diff --git a/js/src/jit-test/tests/debug/Frame-eval-06.js b/js/src/jit-test/tests/debug/Frame-eval-06.js index e799219ef2b..2a573f553c5 100644 --- a/js/src/jit-test/tests/debug/Frame-eval-06.js +++ b/js/src/jit-test/tests/debug/Frame-eval-06.js @@ -1,4 +1,3 @@ -// |jit-test| debug // frame.eval throws if frame is a generator frame that isn't currently on the stack load(libdir + "asserts.js"); diff --git a/js/src/jit-test/tests/debug/Frame-eval-07.js b/js/src/jit-test/tests/debug/Frame-eval-07.js index 8f7fdd2a05a..fba815527a7 100644 --- a/js/src/jit-test/tests/debug/Frame-eval-07.js +++ b/js/src/jit-test/tests/debug/Frame-eval-07.js @@ -1,4 +1,3 @@ -// |jit-test| debug // test frame.eval in non-top frames var g = newGlobal('new-compartment'); diff --git a/js/src/jit-test/tests/debug/Frame-eval-08.js b/js/src/jit-test/tests/debug/Frame-eval-08.js index a1405b96301..ae01b07ca48 100644 --- a/js/src/jit-test/tests/debug/Frame-eval-08.js +++ b/js/src/jit-test/tests/debug/Frame-eval-08.js @@ -1,4 +1,3 @@ -// |jit-test| debug // The arguments can escape from a function via a debugging hook. var g = newGlobal('new-compartment'); diff --git a/js/src/jit-test/tests/debug/Frame-eval-09.js b/js/src/jit-test/tests/debug/Frame-eval-09.js index e8081e9df92..50918fb894e 100644 --- a/js/src/jit-test/tests/debug/Frame-eval-09.js +++ b/js/src/jit-test/tests/debug/Frame-eval-09.js @@ -1,4 +1,3 @@ -// |jit-test| debug // assigning to local variables in frame.eval code var g = newGlobal('new-compartment'); diff --git a/js/src/jit-test/tests/debug/Frame-eval-10.js b/js/src/jit-test/tests/debug/Frame-eval-10.js index 694631c3690..5cd3d2641fa 100644 --- a/js/src/jit-test/tests/debug/Frame-eval-10.js +++ b/js/src/jit-test/tests/debug/Frame-eval-10.js @@ -1,4 +1,3 @@ -// |jit-test| debug // frame.eval returns null if the eval code fails with an uncatchable error. var g = newGlobal('new-compartment'); var dbg = Debug(g); diff --git a/js/src/jit-test/tests/debug/Frame-evalWithBindings-01.js b/js/src/jit-test/tests/debug/Frame-evalWithBindings-01.js index ebaf01fc08e..8892d411ae0 100644 --- a/js/src/jit-test/tests/debug/Frame-evalWithBindings-01.js +++ b/js/src/jit-test/tests/debug/Frame-evalWithBindings-01.js @@ -1,4 +1,3 @@ -// |jit-test| debug // evalWithBindings basics var g = newGlobal('new-compartment'); diff --git a/js/src/jit-test/tests/debug/Frame-evalWithBindings-02.js b/js/src/jit-test/tests/debug/Frame-evalWithBindings-02.js index bc23b258ab3..29c10167501 100644 --- a/js/src/jit-test/tests/debug/Frame-evalWithBindings-02.js +++ b/js/src/jit-test/tests/debug/Frame-evalWithBindings-02.js @@ -1,6 +1,4 @@ -// |jit-test| debug // evalWithBindings to call a method of a debuggee object - var g = newGlobal('new-compartment'); var dbg = new Debug; var global = dbg.addDebuggee(g); diff --git a/js/src/jit-test/tests/debug/Frame-evalWithBindings-03.js b/js/src/jit-test/tests/debug/Frame-evalWithBindings-03.js index e7f670addff..13b2e82bb8e 100644 --- a/js/src/jit-test/tests/debug/Frame-evalWithBindings-03.js +++ b/js/src/jit-test/tests/debug/Frame-evalWithBindings-03.js @@ -1,6 +1,4 @@ -// |jit-test| debug // arguments works in evalWithBindings (it does not interpose a function scope) - var g = newGlobal('new-compartment'); var dbg = new Debug; var global = dbg.addDebuggee(g); diff --git a/js/src/jit-test/tests/debug/Frame-evalWithBindings-04.js b/js/src/jit-test/tests/debug/Frame-evalWithBindings-04.js index 270b67258c0..e0f59736733 100644 --- a/js/src/jit-test/tests/debug/Frame-evalWithBindings-04.js +++ b/js/src/jit-test/tests/debug/Frame-evalWithBindings-04.js @@ -1,6 +1,4 @@ -// |jit-test| debug // evalWithBindings works on non-top frames. - var g = newGlobal('new-compartment'); var dbg = new Debug(g); var f1; diff --git a/js/src/jit-test/tests/debug/Frame-evalWithBindings-05.js b/js/src/jit-test/tests/debug/Frame-evalWithBindings-05.js index 88fd99263a0..45b192549eb 100644 --- a/js/src/jit-test/tests/debug/Frame-evalWithBindings-05.js +++ b/js/src/jit-test/tests/debug/Frame-evalWithBindings-05.js @@ -1,4 +1,3 @@ -// |jit-test| debug // evalWithBindings code can assign to the bindings. var g = newGlobal('new-compartment'); var dbg = new Debug(g); diff --git a/js/src/jit-test/tests/debug/Frame-evalWithBindings-06.js b/js/src/jit-test/tests/debug/Frame-evalWithBindings-06.js index d6c8a7d1745..6d3abea9662 100644 --- a/js/src/jit-test/tests/debug/Frame-evalWithBindings-06.js +++ b/js/src/jit-test/tests/debug/Frame-evalWithBindings-06.js @@ -1,6 +1,4 @@ -// |jit-test| debug // In evalWithBindings code, assignment to any name not in the bindings works just as in eval. - var g = newGlobal('new-compartment'); var dbg = new Debug(g); dbg.hooks = { diff --git a/js/src/jit-test/tests/debug/Frame-evalWithBindings-07.js b/js/src/jit-test/tests/debug/Frame-evalWithBindings-07.js index c2508ebece4..3f47e37e3c8 100644 --- a/js/src/jit-test/tests/debug/Frame-evalWithBindings-07.js +++ b/js/src/jit-test/tests/debug/Frame-evalWithBindings-07.js @@ -1,6 +1,4 @@ -// |jit-test| debug // var statements in strict evalWithBindings code behave like strict eval. - var g = newGlobal('new-compartment'); var dbg = new Debug(g); var hits = 0; diff --git a/js/src/jit-test/tests/debug/Frame-evalWithBindings-08.js b/js/src/jit-test/tests/debug/Frame-evalWithBindings-08.js index 9168bb31932..a59d672eea9 100644 --- a/js/src/jit-test/tests/debug/Frame-evalWithBindings-08.js +++ b/js/src/jit-test/tests/debug/Frame-evalWithBindings-08.js @@ -1,6 +1,4 @@ -// |jit-test| debug // evalWithBindings ignores non-enumerable and non-own properties. - var g = newGlobal('new-compartment'); var dbg = new Debug(g); var hits = 0; diff --git a/js/src/jit-test/tests/debug/Frame-evalWithBindings-09.js b/js/src/jit-test/tests/debug/Frame-evalWithBindings-09.js index d98574f5c5b..8f761572cb2 100644 --- a/js/src/jit-test/tests/debug/Frame-evalWithBindings-09.js +++ b/js/src/jit-test/tests/debug/Frame-evalWithBindings-09.js @@ -1,6 +1,4 @@ -// |jit-test| debug // evalWithBindings code is debuggee code, so it can trip the debugger. It nests! - var g = newGlobal('new-compartment'); var dbg = new Debug(g); var f1; diff --git a/js/src/jit-test/tests/debug/Frame-evalWithBindings-10.js b/js/src/jit-test/tests/debug/Frame-evalWithBindings-10.js index 9dd30432ae5..5407c8e9c28 100644 --- a/js/src/jit-test/tests/debug/Frame-evalWithBindings-10.js +++ b/js/src/jit-test/tests/debug/Frame-evalWithBindings-10.js @@ -1,6 +1,4 @@ -// |jit-test| debug // Direct eval code under evalWithbindings sees both the bindings and the enclosing scope. - var g = newGlobal('new-compartment'); var dbg = new Debug(g); var hits = 0; diff --git a/js/src/jit-test/tests/debug/Frame-identity-04.js b/js/src/jit-test/tests/debug/Frame-identity-04.js index 8cf70f95a5b..8e10b73f823 100644 --- a/js/src/jit-test/tests/debug/Frame-identity-04.js +++ b/js/src/jit-test/tests/debug/Frame-identity-04.js @@ -1,4 +1,3 @@ -// |jit-test| debug // Test that on-stack Debug.Frames are not GC'd even if they are only reachable // from the js::Debug::frames table. diff --git a/js/src/jit-test/tests/debug/Frame-live-03.js b/js/src/jit-test/tests/debug/Frame-live-03.js index 56cfcc966cf..e2c3f31bb44 100644 --- a/js/src/jit-test/tests/debug/Frame-live-03.js +++ b/js/src/jit-test/tests/debug/Frame-live-03.js @@ -4,18 +4,15 @@ load(libdir + "asserts.js"); var g = newGlobal('new-compartment'); -g.debuggeeGlobal = this; -g.eval("var f;"); -g.eval("(" + function () { - Debug(debuggeeGlobal).hooks = { - debuggerHandler: function (frame) { - assertEq(frame.type, "call"); - assertEq(frame.live, true); - f = frame; - } - }; - } + ")()"); +var f; +Debug(g).hooks = { + debuggerHandler: function (frame) { + assertEq(frame.type, "call"); + assertEq(frame.live, true); + f = frame; + } +}; -(function () { debugger; })(); -assertEq(g.f.live, false); -assertThrowsInstanceOf(function () { g.f.type; }, g.Error); +g.eval("(function () { debugger; })();"); +assertEq(f.live, false); +assertThrowsInstanceOf(function () { f.type; }, Error); diff --git a/js/src/jit-test/tests/debug/Frame-live-04.js b/js/src/jit-test/tests/debug/Frame-live-04.js new file mode 100644 index 00000000000..4fd6275ddfe --- /dev/null +++ b/js/src/jit-test/tests/debug/Frame-live-04.js @@ -0,0 +1,28 @@ +// Frame.live is false for frames discarded during uncatchable error unwinding. +var g = newGlobal('new-compartment'); +var dbg = Debug(g); +var hits = 0; +var snapshot; +dbg.hooks = { + debuggerHandler: function (frame) { + var stack = []; + for (var f = frame; f; f = f.older) { + if (f.type === "call") + stack.push(f); + } + snapshot = stack; + if (hits++ === 0) + assertEq(frame.eval("x();"), null); + else + return null; + } +}; + +g.eval("function z() { debugger; }"); +g.eval("function y() { z(); }"); +g.eval("function x() { y(); }"); +assertEq(g.eval("debugger; 'ok';"), "ok"); +assertEq(hits, 2); +assertEq(snapshot.length, 3); +for (var i = 0; i < snapshot.length; i++) + assertEq(snapshot[i].live, false); diff --git a/js/src/jit-test/tests/debug/Frame-older-01.js b/js/src/jit-test/tests/debug/Frame-older-01.js index e2419eaeacf..bde3b4cbe8c 100644 --- a/js/src/jit-test/tests/debug/Frame-older-01.js +++ b/js/src/jit-test/tests/debug/Frame-older-01.js @@ -2,24 +2,21 @@ // Basic call chain. var g = newGlobal('new-compartment'); -g.debuggeeGlobal = this; -g.result = null; -g.eval("(" + function () { - var dbg = new Debug(debuggeeGlobal); - dbg.hooks = { - debuggerHandler: function (frame) { - var a = []; - assertEq(frame === frame.older, false); - for (; frame; frame = frame.older) - a.push(frame.type === 'call' ? frame.callee.name : frame.type); - a.reverse(); - result = a.join(", "); - } - }; - } + ")();"); +var result = null; +var dbg = new Debug(g); +dbg.hooks = { + debuggerHandler: function (frame) { + var a = []; + assertEq(frame === frame.older, false); + for (; frame; frame = frame.older) + a.push(frame.type === 'call' ? frame.callee.name : frame.type); + a.reverse(); + result = a.join(", "); + } +}; -function first() { return second(); } -function second() { return eval("third()"); } -function third() { debugger; } -first(); -assertEq(g.result, "global, first, second, eval, third"); +g.eval("function first() { return second(); }"); +g.eval("function second() { return eval('third()'); }"); +g.eval("function third() { debugger; }"); +g.evaluate("first();"); +assertEq(result, "global, first, second, eval, third"); diff --git a/js/src/jit-test/tests/debug/Frame-this-01.js b/js/src/jit-test/tests/debug/Frame-this-01.js index 862c3e88e61..5eb81aa5935 100644 --- a/js/src/jit-test/tests/debug/Frame-this-01.js +++ b/js/src/jit-test/tests/debug/Frame-this-01.js @@ -1,4 +1,3 @@ -// |jit-test| debug // Frame.prototype.this in strict-mode functions, with primitive values var g = newGlobal('new-compartment'); diff --git a/js/src/jit-test/tests/debug/Frame-this-02.js b/js/src/jit-test/tests/debug/Frame-this-02.js index c87b10656a7..5ce0d4b4781 100644 --- a/js/src/jit-test/tests/debug/Frame-this-02.js +++ b/js/src/jit-test/tests/debug/Frame-this-02.js @@ -1,4 +1,3 @@ -// |jit-test| debug // Frame.prototype.this in strict direct eval frames var g = newGlobal('new-compartment'); diff --git a/js/src/jit-test/tests/debug/Frame-this-03.js b/js/src/jit-test/tests/debug/Frame-this-03.js index c98b426fdcf..78454d20326 100644 --- a/js/src/jit-test/tests/debug/Frame-this-03.js +++ b/js/src/jit-test/tests/debug/Frame-this-03.js @@ -1,4 +1,3 @@ -// |jit-test| debug // Frame.prototype.this in non-strict-mode functions, with primitive values function classOf(obj) { diff --git a/js/src/jit-test/tests/debug/Frame-this-04.js b/js/src/jit-test/tests/debug/Frame-this-04.js index 913320262ed..2efbb397615 100644 --- a/js/src/jit-test/tests/debug/Frame-this-04.js +++ b/js/src/jit-test/tests/debug/Frame-this-04.js @@ -1,4 +1,3 @@ -// |jit-test| debug // Debug.Frame.prototype.this in functions, with object values function classOf(obj) { diff --git a/js/src/jit-test/tests/debug/Object-01.js b/js/src/jit-test/tests/debug/Object-01.js index b8dccd3bf8c..7bc74f431b7 100644 --- a/js/src/jit-test/tests/debug/Object-01.js +++ b/js/src/jit-test/tests/debug/Object-01.js @@ -1,4 +1,3 @@ -// |jit-test| debug // Debug.Object basics var g = newGlobal('new-compartment'); diff --git a/js/src/jit-test/tests/debug/Object-apply-01.js b/js/src/jit-test/tests/debug/Object-apply-01.js index 8598d38669f..30e0d6fe5b4 100644 --- a/js/src/jit-test/tests/debug/Object-apply-01.js +++ b/js/src/jit-test/tests/debug/Object-apply-01.js @@ -1,4 +1,3 @@ -// |jit-test| debug // tests calling script functions via Debug.Object.prototype.apply/call load(libdir + "asserts.js"); diff --git a/js/src/jit-test/tests/debug/Object-apply-02.js b/js/src/jit-test/tests/debug/Object-apply-02.js index ddd758c23ed..1eef67edb40 100644 --- a/js/src/jit-test/tests/debug/Object-apply-02.js +++ b/js/src/jit-test/tests/debug/Object-apply-02.js @@ -1,4 +1,3 @@ -// |jit-test| debug // tests calling native functions via Debug.Object.prototype.apply/call load(libdir + "asserts.js"); diff --git a/js/src/jit-test/tests/debug/Object-apply-03.js b/js/src/jit-test/tests/debug/Object-apply-03.js index f1a24b215de..2bff00c74be 100644 --- a/js/src/jit-test/tests/debug/Object-apply-03.js +++ b/js/src/jit-test/tests/debug/Object-apply-03.js @@ -1,4 +1,3 @@ -// |jit-test| debug // reentering the debugger several times via debuggerHandler and apply/call on a single stack var g = newGlobal("new-compartment"); diff --git a/js/src/jit-test/tests/debug/Object-apply-04.js b/js/src/jit-test/tests/debug/Object-apply-04.js index 78b69463895..6da2e3b918e 100644 --- a/js/src/jit-test/tests/debug/Object-apply-04.js +++ b/js/src/jit-test/tests/debug/Object-apply-04.js @@ -1,4 +1,3 @@ -// |jit-test| debug // Debug.Object.prototype.apply/call works with function proxies var g = newGlobal('new-compartment'); diff --git a/js/src/jit-test/tests/debug/Object-callable.js b/js/src/jit-test/tests/debug/Object-callable.js index a8e9056e418..49313643f90 100644 --- a/js/src/jit-test/tests/debug/Object-callable.js +++ b/js/src/jit-test/tests/debug/Object-callable.js @@ -1,4 +1,3 @@ -// |jit-test| debug // Test Debug.Object.prototype.callable. var g = newGlobal('new-compartment'); diff --git a/js/src/jit-test/tests/debug/Object-class.js b/js/src/jit-test/tests/debug/Object-class.js index 33493efcff2..529137da665 100644 --- a/js/src/jit-test/tests/debug/Object-class.js +++ b/js/src/jit-test/tests/debug/Object-class.js @@ -1,5 +1,4 @@ -// |jit-test| debug - +// Basic tests for Debug.Object.prototype.class. var g = newGlobal('new-compartment'); var dbg = new Debug(g); var hits = 0; @@ -14,6 +13,5 @@ dbg.hooks = { hits++; } }; - g.eval("(function () { debugger; })(Object.prototype, [], eval, new Date, Proxy.create({}));"); assertEq(hits, 1); diff --git a/js/src/jit-test/tests/debug/Object-identity-01.js b/js/src/jit-test/tests/debug/Object-identity-01.js index 957cdd92bdd..d8f4c5a9cd3 100644 --- a/js/src/jit-test/tests/debug/Object-identity-01.js +++ b/js/src/jit-test/tests/debug/Object-identity-01.js @@ -1,6 +1,4 @@ -// |jit-test| debug // Two references to the same object get the same Debug.Object wrapper. - var g = newGlobal('new-compartment'); var dbg = Debug(g); var hits = 0; diff --git a/js/src/jit-test/tests/debug/Object-identity-02.js b/js/src/jit-test/tests/debug/Object-identity-02.js index c082874472e..a58d73956bb 100644 --- a/js/src/jit-test/tests/debug/Object-identity-02.js +++ b/js/src/jit-test/tests/debug/Object-identity-02.js @@ -1,6 +1,4 @@ -// |jit-test| debug // Different objects get different Debug.Object wrappers. - var g = newGlobal('new-compartment'); var dbg = Debug(g); var hits = 0; diff --git a/js/src/jit-test/tests/debug/Object-identity-03.js b/js/src/jit-test/tests/debug/Object-identity-03.js index 75e4abbd145..81feb786263 100644 --- a/js/src/jit-test/tests/debug/Object-identity-03.js +++ b/js/src/jit-test/tests/debug/Object-identity-03.js @@ -1,4 +1,3 @@ -// |jit-test| debug // The same object gets the same Debug.Object wrapper at different times, if the difference would be observable. var N = HOTLOOP + 4; diff --git a/js/src/jit-test/tests/debug/Object-name-01.js b/js/src/jit-test/tests/debug/Object-name-01.js index b59eca69dfb..d59e36237ff 100644 --- a/js/src/jit-test/tests/debug/Object-name-01.js +++ b/js/src/jit-test/tests/debug/Object-name-01.js @@ -1,6 +1,4 @@ -// |jit-test| debug // Debug.Object.prototype.name - var g = newGlobal('new-compartment'); var dbg = Debug(g); var name, hits; diff --git a/js/src/jit-test/tests/debug/Object-name-02.js b/js/src/jit-test/tests/debug/Object-name-02.js index 3096335dd15..b81c155476d 100644 --- a/js/src/jit-test/tests/debug/Object-name-02.js +++ b/js/src/jit-test/tests/debug/Object-name-02.js @@ -1,6 +1,4 @@ -// |jit-test| debug // The .name of a non-function object is undefined. - var g = newGlobal('new-compartment'); var hits = 0; var dbg = new Debug(g); diff --git a/js/src/jit-test/tests/debug/Object-parameterNames.js b/js/src/jit-test/tests/debug/Object-parameterNames.js index e89343626c8..0e365bfa0d2 100644 --- a/js/src/jit-test/tests/debug/Object-parameterNames.js +++ b/js/src/jit-test/tests/debug/Object-parameterNames.js @@ -1,4 +1,3 @@ -// |jit-test| debug load(libdir + 'array-compare.js'); var g = newGlobal('new-compartment'); diff --git a/js/src/jit-test/tests/debug/Object-proto.js b/js/src/jit-test/tests/debug/Object-proto.js index caecdcf17d9..511ce8343c7 100644 --- a/js/src/jit-test/tests/debug/Object-proto.js +++ b/js/src/jit-test/tests/debug/Object-proto.js @@ -1,4 +1,4 @@ -// |jit-test| debug +// Debug.Object.prototype.proto var g = newGlobal('new-compartment'); var dbgeval = function () { var dbg = new Debug(g); diff --git a/js/src/jit-test/tests/debug/dispatch-01.js b/js/src/jit-test/tests/debug/dispatch-01.js index 6239a91d490..2a1c3bf875c 100644 --- a/js/src/jit-test/tests/debug/dispatch-01.js +++ b/js/src/jit-test/tests/debug/dispatch-01.js @@ -1,4 +1,3 @@ -// |jit-test| debug // Test removing hooks during dispatch. var g = newGlobal('new-compartment'); diff --git a/js/src/jit-test/tests/debug/dispatch-02.js b/js/src/jit-test/tests/debug/dispatch-02.js index e5b81511a36..0644fb3e216 100644 --- a/js/src/jit-test/tests/debug/dispatch-02.js +++ b/js/src/jit-test/tests/debug/dispatch-02.js @@ -1,4 +1,3 @@ -// |jit-test| debug // Disabling a Debug object causes events to stop being delivered to it // immediately, even if we're in the middle of dispatching. diff --git a/js/src/jit-test/tests/debug/gc-01.js b/js/src/jit-test/tests/debug/gc-01.js index f0526bbb922..6844ca1e2e9 100644 --- a/js/src/jit-test/tests/debug/gc-01.js +++ b/js/src/jit-test/tests/debug/gc-01.js @@ -1,4 +1,3 @@ -// |jit-test| debug // Debuggers with enabled hooks should not be GC'd even if they are otherwise // unreachable. diff --git a/js/src/jit-test/tests/debug/gc-02.js b/js/src/jit-test/tests/debug/gc-02.js index a4ff9f9d731..2765f6ac691 100644 --- a/js/src/jit-test/tests/debug/gc-02.js +++ b/js/src/jit-test/tests/debug/gc-02.js @@ -1,4 +1,3 @@ -// |jit-test| debug // Dispatching an event to a debugger must keep enough of it gc-alive to avoid // crashing. diff --git a/js/src/jit-test/tests/debug/gc-03.js b/js/src/jit-test/tests/debug/gc-03.js index d6e1d57e198..27b95606013 100644 --- a/js/src/jit-test/tests/debug/gc-03.js +++ b/js/src/jit-test/tests/debug/gc-03.js @@ -1,4 +1,3 @@ -// |jit-test| debug // Storing a property on a Debug.Object protects it from GC as long as the // referent is alive. diff --git a/js/src/jit-test/tests/debug/gc-04.js b/js/src/jit-test/tests/debug/gc-04.js index 8ea9a6f6d15..11031b54586 100644 --- a/js/src/jit-test/tests/debug/gc-04.js +++ b/js/src/jit-test/tests/debug/gc-04.js @@ -1,4 +1,3 @@ -// |jit-test| debug // Storing a Debug.Object as a key in a WeakMap protects it from GC as long as // the referent is alive. diff --git a/js/src/jit-test/tests/debug/gc-05.js b/js/src/jit-test/tests/debug/gc-05.js index df3076899b5..324e2968f26 100644 --- a/js/src/jit-test/tests/debug/gc-05.js +++ b/js/src/jit-test/tests/debug/gc-05.js @@ -1,4 +1,3 @@ -// |jit-test| debug // If a Debug survives its debuggee, its object cache must still be swept. var g2arr = []; // non-debuggee globals diff --git a/js/src/jit-test/tests/debug/gc-06.js b/js/src/jit-test/tests/debug/gc-06.js index 92d0d895c16..522bcb4fe62 100644 --- a/js/src/jit-test/tests/debug/gc-06.js +++ b/js/src/jit-test/tests/debug/gc-06.js @@ -1,6 +1,4 @@ -// |jit-test| debug // Debug objects do not keep debuggee globals live. - var dbg = new Debug; for (var i = 0; i < 4; i++) dbg.addDebuggee(newGlobal('new-compartment')); diff --git a/js/src/jit-test/tests/debug/gc-07.js b/js/src/jit-test/tests/debug/gc-07.js index 2b1de3e8b37..79e71d1d51a 100644 --- a/js/src/jit-test/tests/debug/gc-07.js +++ b/js/src/jit-test/tests/debug/gc-07.js @@ -1,6 +1,4 @@ -// |jit-test| debug // Don't assert with dead Debug.Object and live cross-compartment wrapper of referent. - var g = newGlobal('new-compartment'); for (var j = 0; j < 4; j++) { var dbg = new Debug; diff --git a/js/src/jit-test/tests/debug/gc-08.js b/js/src/jit-test/tests/debug/gc-08.js index 4d5e16a39c4..5c9cfa40a9a 100644 --- a/js/src/jit-test/tests/debug/gc-08.js +++ b/js/src/jit-test/tests/debug/gc-08.js @@ -1,4 +1,3 @@ -// |jit-test| debug // Debuggers with enabled throw hooks should not be GC'd even if they are // otherwise unreachable. diff --git a/js/src/jit-test/tests/debug/hooks-debuggerHandler-01.js b/js/src/jit-test/tests/debug/hooks-debuggerHandler-01.js index 9ae99dbf8ff..fcabbee1185 100644 --- a/js/src/jit-test/tests/debug/hooks-debuggerHandler-01.js +++ b/js/src/jit-test/tests/debug/hooks-debuggerHandler-01.js @@ -1,13 +1,8 @@ -// |jit-test| debug var g = newGlobal('new-compartment'); g.log = ''; var dbg = Debug(g); -var hooks = { - debuggerHandler: function (stack) { - g.log += '!'; - } -}; +var hooks = {debuggerHandler: function (stack) { g.log += '!'; }}; dbg.hooks = hooks; assertEq(dbg.hooks, hooks); assertEq(g.eval("log += '1'; debugger; log += '2'; 3;"), 3); diff --git a/js/src/jit-test/tests/debug/hooks-debuggerHandler-02.js b/js/src/jit-test/tests/debug/hooks-debuggerHandler-02.js index 0f61e6c6a06..e79f8ecdcda 100644 --- a/js/src/jit-test/tests/debug/hooks-debuggerHandler-02.js +++ b/js/src/jit-test/tests/debug/hooks-debuggerHandler-02.js @@ -1,4 +1,3 @@ -// |jit-test| debug // Activity in the debugger compartment should not trigger debug hooks. var g = newGlobal('new-compartment'); diff --git a/js/src/jit-test/tests/debug/hooks-debuggerHandler-03.js b/js/src/jit-test/tests/debug/hooks-debuggerHandler-03.js index 2c5af905cc0..2c4cecdeb1f 100644 --- a/js/src/jit-test/tests/debug/hooks-debuggerHandler-03.js +++ b/js/src/jit-test/tests/debug/hooks-debuggerHandler-03.js @@ -1,4 +1,3 @@ -// |jit-test| debug // A debugger statement in a debuggerHandler should not reenter. var g = newGlobal('new-compartment'); diff --git a/js/src/jit-test/tests/debug/hooks-deleted.js b/js/src/jit-test/tests/debug/hooks-deleted.js index 27ee53a6f03..eef212289bb 100644 --- a/js/src/jit-test/tests/debug/hooks-deleted.js +++ b/js/src/jit-test/tests/debug/hooks-deleted.js @@ -1,4 +1,3 @@ -// |jit-test| debug // If a hook is deleted after setHooks or overwritten with a primitive, it // simply isn't called. diff --git a/js/src/jit-test/tests/debug/hooks-throw-01.js b/js/src/jit-test/tests/debug/hooks-throw-01.js index 3ab429af98f..8757bf3ac03 100644 --- a/js/src/jit-test/tests/debug/hooks-throw-01.js +++ b/js/src/jit-test/tests/debug/hooks-throw-01.js @@ -1,4 +1,3 @@ -// |jit-test| debug // Basic throw hook test. load(libdir + "asserts.js"); diff --git a/js/src/jit-test/tests/debug/hooks-throw-04.js b/js/src/jit-test/tests/debug/hooks-throw-04.js index f5343caee6a..d5e6e38cd22 100644 --- a/js/src/jit-test/tests/debug/hooks-throw-04.js +++ b/js/src/jit-test/tests/debug/hooks-throw-04.js @@ -1,6 +1,4 @@ -// |jit-test| debug // hooks.throw is not called for exceptions thrown and handled in the debugger. - var g = newGlobal('new-compartment'); var dbg = Debug(g); g.log = ''; diff --git a/js/src/jit-test/tests/debug/resumption-01.js b/js/src/jit-test/tests/debug/resumption-01.js index 5438dfc6d0a..7f4cab188f5 100644 --- a/js/src/jit-test/tests/debug/resumption-01.js +++ b/js/src/jit-test/tests/debug/resumption-01.js @@ -1,10 +1,8 @@ -// |jit-test| debug // Simple {throw:} resumption. load(libdir + "asserts.js"); var g = newGlobal('new-compartment'); - var dbg = Debug(g); dbg.hooks = { debuggerHandler: function (stack) { diff --git a/js/src/jit-test/tests/debug/resumption-02.js b/js/src/jit-test/tests/debug/resumption-02.js index efdb64f5487..f24451991f3 100644 --- a/js/src/jit-test/tests/debug/resumption-02.js +++ b/js/src/jit-test/tests/debug/resumption-02.js @@ -1,8 +1,5 @@ -// |jit-test| debug // Simple {return:} resumption. - var g = newGlobal('new-compartment'); - var dbg = Debug(g); dbg.hooks = { debuggerHandler: function (stack) { diff --git a/js/src/jit-test/tests/debug/surfaces-01.js b/js/src/jit-test/tests/debug/surfaces-01.js index 8a04693773c..495937ba884 100644 --- a/js/src/jit-test/tests/debug/surfaces-01.js +++ b/js/src/jit-test/tests/debug/surfaces-01.js @@ -1,4 +1,4 @@ -// |jit-test| debug +// Check superficial characteristics of functions and properties (not functionality). function checkFunction(obj, name, nargs) { var desc = Object.getOwnPropertyDescriptor(obj, name); diff --git a/js/src/jit-test/tests/debug/surfaces-02.js b/js/src/jit-test/tests/debug/surfaces-02.js index f599b42eaec..ceac1fbd941 100644 --- a/js/src/jit-test/tests/debug/surfaces-02.js +++ b/js/src/jit-test/tests/debug/surfaces-02.js @@ -1,4 +1,3 @@ -// |jit-test| debug // Debug.prototype.hooks load(libdir + 'asserts.js'); diff --git a/js/src/jit-test/tests/debug/surfaces-03.js b/js/src/jit-test/tests/debug/surfaces-03.js index 523a03620e8..6ee6ec1b1da 100644 --- a/js/src/jit-test/tests/debug/surfaces-03.js +++ b/js/src/jit-test/tests/debug/surfaces-03.js @@ -1,4 +1,3 @@ -// |jit-test| debug // dumb basics of uncaughtExceptionHook load(libdir + 'asserts.js'); diff --git a/js/src/jit-test/tests/debug/uncaughtExceptionHook-01.js b/js/src/jit-test/tests/debug/uncaughtExceptionHook-01.js index 4ca3230568f..5d9f0e87bf3 100644 --- a/js/src/jit-test/tests/debug/uncaughtExceptionHook-01.js +++ b/js/src/jit-test/tests/debug/uncaughtExceptionHook-01.js @@ -1,4 +1,3 @@ -// |jit-test| debug // Uncaught exceptions in the debugger itself are delivered to the // uncaughtExceptionHook. diff --git a/js/src/jit-test/tests/debug/uncaughtExceptionHook-02.js b/js/src/jit-test/tests/debug/uncaughtExceptionHook-02.js index ec4bd8a6db8..5c77d0d3713 100644 --- a/js/src/jit-test/tests/debug/uncaughtExceptionHook-02.js +++ b/js/src/jit-test/tests/debug/uncaughtExceptionHook-02.js @@ -1,4 +1,3 @@ -// |jit-test| debug // Returning a bad resumption value causes an exception that is reported to the // uncaughtExceptionHook. diff --git a/js/src/jit-test/tests/debug/uncaughtExceptionHook-resumption-01.js b/js/src/jit-test/tests/debug/uncaughtExceptionHook-resumption-01.js index e30cb793327..c253317fc6c 100644 --- a/js/src/jit-test/tests/debug/uncaughtExceptionHook-resumption-01.js +++ b/js/src/jit-test/tests/debug/uncaughtExceptionHook-resumption-01.js @@ -1,4 +1,3 @@ -// |jit-test| debug // uncaughtExceptionHook returns a resumption value. load(libdir + "asserts.js"); diff --git a/js/src/jit-test/tests/debug/uncaughtExceptionHook-resumption-02.js b/js/src/jit-test/tests/debug/uncaughtExceptionHook-resumption-02.js index f2fbda68ab4..a15257e218c 100644 --- a/js/src/jit-test/tests/debug/uncaughtExceptionHook-resumption-02.js +++ b/js/src/jit-test/tests/debug/uncaughtExceptionHook-resumption-02.js @@ -1,4 +1,3 @@ -// |jit-test| debug // uncaughtExceptionHook resumption value other than undefined causes further // hooks to be skipped. diff --git a/js/src/jit-test/tests/debug/uncaughtExceptionHook-resumption-03.js b/js/src/jit-test/tests/debug/uncaughtExceptionHook-resumption-03.js index 67c64d99f2c..ffa67171346 100644 --- a/js/src/jit-test/tests/debug/uncaughtExceptionHook-resumption-03.js +++ b/js/src/jit-test/tests/debug/uncaughtExceptionHook-resumption-03.js @@ -1,4 +1,3 @@ -// |jit-test| debug // After hooks.throw throws, if uncaughtExceptionHook returns undefined, // the original exception continues to propagate. diff --git a/js/src/jsanalyze.cpp b/js/src/jsanalyze.cpp index e7ebbeaaeb2..91c138e0245 100644 --- a/js/src/jsanalyze.cpp +++ b/js/src/jsanalyze.cpp @@ -315,7 +315,7 @@ Script::analyze(JSContext *cx, JSScript *script) * by debug code or by eval, or if they could be accessed by an inner script. */ - if (script->usesEval || cx->compartment->debugMode) { + if (script->usesEval || cx->compartment->debugMode()) { for (uint32 i = 0; i < nfixed; i++) setLocal(i, LOCAL_USE_BEFORE_DEF); } @@ -330,7 +330,7 @@ Script::analyze(JSContext *cx, JSScript *script) * If the script is in debug mode, JS_SetFrameReturnValue can be called at * any safe point. */ - if (cx->compartment->debugMode) + if (cx->compartment->debugMode()) usesRval = true; /* diff --git a/js/src/jsapi-tests/testDebugger.cpp b/js/src/jsapi-tests/testDebugger.cpp index 3201f15f117..45498f2f50a 100644 --- a/js/src/jsapi-tests/testDebugger.cpp +++ b/js/src/jsapi-tests/testDebugger.cpp @@ -139,7 +139,7 @@ BEGIN_TEST(testDebugger_debugObjectVsDebugMode) EVAL("debuggee.eval('debugger; debugger; debugger;');\n" "hits;\n", &v); - CHECK_SAME(v, JSVAL_ONE); + CHECK_SAME(v, INT_TO_JSVAL(4)); return true; } diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 00cfadff2bf..595287fc56c 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -707,7 +707,7 @@ JSRuntime::init(uint32 maxbytes) return false; #endif - debugMode = JS_FALSE; + debugMode = false; return js_InitThreads(this); } diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index ba5f56a48ee..f188894e598 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -495,7 +495,7 @@ struct JSRuntime { /* * Right now, we only support runtime-wide debugging. */ - JSBool debugMode; + bool debugMode; #ifdef JS_TRACER /* True if any debug hooks not supported by the JIT are enabled. */ diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index 30e56054107..05459ce7025 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -87,7 +87,7 @@ JSCompartment::JSCompartment(JSRuntime *rt) emptyWithShape(NULL), initialRegExpShape(NULL), initialStringShape(NULL), - debugMode(rt->debugMode), + debugModeBits(rt->debugMode * DebugFromC), mathCache(NULL) { JS_INIT_CLIST(&scripts); @@ -601,3 +601,54 @@ JSCompartment::isAboutToBeCollected(JSGCInvocationKind gckind) { return !hold && (arenaListsAreEmpty() || gckind == GC_LAST_CONTEXT); } + +bool +JSCompartment::haveScriptsOnStack(JSContext *cx) +{ + for (AllFramesIter i(cx); !i.done(); ++i) { + JSScript *script = i.fp()->maybeScript(); + if (script && script->compartment == this) + return true; + } + return false; +} + +bool +JSCompartment::setDebugModeFromC(JSContext *cx, bool b) +{ + bool wasEnabled = debugMode(); + + // Debug mode can be enabled only when no scripts from the target + // compartment are on the stack. It would even be incorrect to discard just + // the non-live scripts' JITScripts because they might share ICs with live + // scripts (bug 632343). + if (b && !wasEnabled && haveScriptsOnStack(cx)) { + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_DEBUG_NOT_IDLE); + return false; + } + + debugModeBits = (debugModeBits & ~uintN(DebugFromC)) | (b * DebugFromC); + if (b != wasEnabled) + updateForDebugMode(cx); + return true; +} + +void +JSCompartment::updateForDebugMode(JSContext *cx) +{ +#ifdef JS_METHODJIT + bool mode = debugMode(); + + // Discard JIT code for any scripts that change debugMode. This assumes + // that 'comp' is in the same thread as 'cx'. + for (JSScript *script = (JSScript *) scripts.next; + &script->links != &scripts; + script = (JSScript *) script->links.next) + { + if (script->debugMode != mode) { + mjit::ReleaseScriptCode(cx, script); + script->debugMode = mode; + } + } +#endif +} diff --git a/js/src/jscompartment.h b/js/src/jscompartment.h index f307d18593f..93b82d4cda4 100644 --- a/js/src/jscompartment.h +++ b/js/src/jscompartment.h @@ -462,8 +462,11 @@ struct JS_FRIEND_API(JSCompartment) { const js::Shape *initialRegExpShape; const js::Shape *initialStringShape; - bool debugMode; // true iff debug mode on - JSCList scripts; // scripts in this compartment + private: + enum { DebugFromC = 1, DebugFromJS = 2 }; + uintN debugModeBits; // see debugMode() below + public: + JSCList scripts; // scripts in this compartment js::NativeIterCache nativeIterCache; @@ -528,13 +531,52 @@ struct JS_FRIEND_API(JSCompartment) { size_t backEdgeCount(jsbytecode *pc) const; size_t incBackEdgeCount(jsbytecode *pc); + /* + * There are dueling APIs for debug mode. It can be enabled or disabled via + * JS_SetDebugModeForCompartment. It is automatically enabled and disabled + * by Debug objects. Therefore debugModeBits has the DebugFromC bit set if + * the C API wants debug mode and the DebugFromJS bit set if debuggees is + * nonempty. + */ + bool debugMode() const { return !!debugModeBits; } + + /* + * True if any scripts from this compartment are on the JS stack in the + * calling thread. cx is a context in the calling thread, and it is assumed + * that no other thread is using this compartment. + */ + bool haveScriptsOnStack(JSContext *cx); + + bool setDebugModeFromC(JSContext *cx, bool b); + + /* This is called only when debugMode() has just toggled. */ + void updateForDebugMode(JSContext *cx); + js::GlobalObjectSet &getDebuggees() { return debuggees; } - bool addDebuggee(js::GlobalObject *global) { - JS_ASSERT(debugMode); - return !!debuggees.put(global); + + bool addDebuggee(JSContext *cx, js::GlobalObject *global) { + bool wasEnabled = debugMode(); + if (!wasEnabled && haveScriptsOnStack(cx)) { + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_DEBUG_NOT_IDLE); + return false; + } + if (!debuggees.put(global)) { + js_ReportOutOfMemory(cx); + return false; + } + debugModeBits |= DebugFromJS; + if (!wasEnabled) + updateForDebugMode(cx); + return true; } - void removeDebuggee(js::GlobalObject *global) { + + void removeDebuggee(JSContext *cx, js::GlobalObject *global) { + JS_ASSERT(debuggees.has(global)); debuggees.remove(global); + if (debuggees.empty()) { + debugModeBits &= ~DebugFromJS; + updateForDebugMode(cx); + } } }; diff --git a/js/src/jsdbg.cpp b/js/src/jsdbg.cpp index 7118b69d5de..7bb69f4ba8a 100644 --- a/js/src/jsdbg.cpp +++ b/js/src/jsdbg.cpp @@ -160,16 +160,10 @@ Debug::Debug(JSObject *dbg, JSObject *hooks) Debug::~Debug() { - JS_ASSERT(object->compartment()->rt->gcRunning); - if (!debuggees.empty()) { - // This happens only during per-compartment GC. See comment in - // Debug::sweepAll. - JS_ASSERT(object->compartment()->rt->gcCurrentCompartment == object->compartment()); - for (GlobalObjectSet::Enum e(debuggees); !e.empty(); e.popFront()) - removeDebuggeeGlobal(e.front(), NULL, &e); - } + JS_ASSERT(debuggees.empty()); // This always happens in the GC thread, so no locking is required. + JS_ASSERT(object->compartment()->rt->gcRunning); JS_REMOVE_LINK(&link); } @@ -616,8 +610,9 @@ Debug::trace(JSTracer *trc, JSObject *obj) } void -Debug::sweepAll(JSRuntime *rt) +Debug::sweepAll(JSContext *cx) { + JSRuntime *rt = cx->runtime; for (JSCList *p = &rt->debuggerList; (p = JS_NEXT_LINK(p)) != &rt->debuggerList;) { Debug *dbg = (Debug *) ((unsigned char *) p - offsetof(Debug, link)); @@ -636,47 +631,49 @@ Debug::sweepAll(JSRuntime *rt) // they are in different compartments), so in that case we just wait for // Debug::finalize. for (GlobalObjectSet::Enum e(dbg->debuggees); !e.empty(); e.popFront()) - dbg->removeDebuggeeGlobal(e.front(), NULL, &e); + dbg->removeDebuggeeGlobal(cx, e.front(), NULL, &e); } } for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); c++) - sweepCompartment(*c); + sweepCompartment(cx, *c); } void -Debug::detachAllDebuggersFromGlobal(GlobalObject *global, GlobalObjectSet::Enum *compartmentEnum) +Debug::detachAllDebuggersFromGlobal(JSContext *cx, GlobalObject *global, GlobalObjectSet::Enum *compartmentEnum) { const GlobalObject::DebugVector *debuggers = global->getDebuggers(); JS_ASSERT(!debuggers->empty()); while (!debuggers->empty()) - debuggers->back()->removeDebuggeeGlobal(global, compartmentEnum, NULL); + debuggers->back()->removeDebuggeeGlobal(cx, global, compartmentEnum, NULL); } void -Debug::sweepCompartment(JSCompartment *compartment) +Debug::sweepCompartment(JSContext *cx, JSCompartment *compartment) { // For each debuggee being GC'd, detach it from all its debuggers. GlobalObjectSet &debuggees = compartment->getDebuggees(); for (GlobalObjectSet::Enum e(debuggees); !e.empty(); e.popFront()) { GlobalObject *global = e.front(); if (!global->isMarked()) - detachAllDebuggersFromGlobal(global, &e); + detachAllDebuggersFromGlobal(cx, global, &e); } } -void -Debug::detachFromCompartment(JSCompartment *comp) -{ - for (GlobalObjectSet::Enum e(comp->getDebuggees()); !e.empty(); e.popFront()) - detachAllDebuggersFromGlobal(e.front(), &e); -} - void Debug::finalize(JSContext *cx, JSObject *obj) { Debug *dbg = (Debug *) obj->getPrivate(); + if (!dbg) + return; + if (!dbg->debuggees.empty()) { + // This happens only during per-compartment GC. See comment in + // Debug::sweepAll. + JS_ASSERT(cx->runtime->gcCurrentCompartment == dbg->object->compartment()); + for (GlobalObjectSet::Enum e(dbg->debuggees); !e.empty(); e.popFront()) + dbg->removeDebuggeeGlobal(cx, e.front(), NULL, &e); + } cx->delete_(dbg); } @@ -822,7 +819,7 @@ Debug::removeDebuggee(JSContext *cx, uintN argc, Value *vp) return false; GlobalObject *global = referent->getGlobal(); if (dbg->debuggees.has(global)) - dbg->removeDebuggeeGlobal(global, NULL, NULL); + dbg->removeDebuggeeGlobal(cx, global, NULL, NULL); vp->setUndefined(); return true; } @@ -930,10 +927,7 @@ Debug::construct(JSContext *cx, uintN argc, Value *vp) bool Debug::addDebuggeeGlobal(JSContext *cx, GlobalObject *obj) { - if (!obj->compartment()->debugMode) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NEED_DEBUG_MODE); - return false; - } + JSCompartment *debuggeeCompartment = obj->compartment(); // Check for cycles. If obj's compartment is reachable from this Debug // object's compartment by following debuggee-to-debugger links, then @@ -942,10 +936,9 @@ Debug::addDebuggeeGlobal(JSContext *cx, GlobalObject *obj) Vector visited(cx); if (!visited.append(object->compartment())) return false; - JSCompartment *dest = obj->compartment(); for (size_t i = 0; i < visited.length(); i++) { JSCompartment *c = visited[i]; - if (c == dest) { + if (c == debuggeeCompartment) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_DEBUG_LOOP); return false; } @@ -963,12 +956,17 @@ Debug::addDebuggeeGlobal(JSContext *cx, GlobalObject *obj) } // Each debugger-debuggee relation must be stored in up to three places. + // JSCompartment::addDebuggee enables debug mode if needed. GlobalObject::DebugVector *v = obj->getOrCreateDebuggers(cx); - if (!v || !v->append(this)) + if (!v || !v->append(this)) { + js_ReportOutOfMemory(cx); goto fail1; - if (!debuggees.put(obj)) + } + if (!debuggees.put(obj)) { + js_ReportOutOfMemory(cx); goto fail2; - if (obj->getDebuggers()->length() == 1 && !obj->compartment()->addDebuggee(obj)) + } + if (obj->getDebuggers()->length() == 1 && !debuggeeCompartment->addDebuggee(cx, obj)) goto fail3; return true; @@ -979,12 +977,12 @@ fail2: JS_ASSERT(v->back() == this); v->popBack(); fail1: - js_ReportOutOfMemory(cx); return false; } void -Debug::removeDebuggeeGlobal(GlobalObject *global, GlobalObjectSet::Enum *compartmentEnum, +Debug::removeDebuggeeGlobal(JSContext *cx, GlobalObject *global, + GlobalObjectSet::Enum *compartmentEnum, GlobalObjectSet::Enum *debugEnum) { // Each debuggee is in two HashSets: one for its compartment and one for @@ -1026,7 +1024,7 @@ Debug::removeDebuggeeGlobal(GlobalObject *global, GlobalObjectSet::Enum *compart if (compartmentEnum) compartmentEnum->removeFront(); else - global->compartment()->removeDebuggee(global); + global->compartment()->removeDebuggee(cx, global); } if (debugEnum) debugEnum->removeFront(); diff --git a/js/src/jsdbg.h b/js/src/jsdbg.h index 9761fdb986a..d08be9adf98 100644 --- a/js/src/jsdbg.h +++ b/js/src/jsdbg.h @@ -83,7 +83,8 @@ class Debug { ObjectMap objects; bool addDebuggeeGlobal(JSContext *cx, GlobalObject *obj); - void removeDebuggeeGlobal(GlobalObject *global, GlobalObjectSet::Enum *compartmentEnum, + void removeDebuggeeGlobal(JSContext *cx, GlobalObject *global, + GlobalObjectSet::Enum *compartmentEnum, GlobalObjectSet::Enum *debugEnum); JSTrapStatus handleUncaughtException(AutoCompartment &ac, Value *vp, bool callHook); @@ -134,7 +135,6 @@ class Debug { inline JSObject *toJSObject() const; static inline Debug *fromJSObject(JSObject *obj); static Debug *fromChildJSObject(JSObject *obj); - static void detachFromCompartment(JSCompartment *comp); /*********************************** Methods for interaction with the GC. */ @@ -153,9 +153,9 @@ class Debug { // returns true. If not, it returns false. // static bool mark(GCMarker *trc, JSCompartment *compartment, JSGCInvocationKind gckind); - static void sweepAll(JSRuntime *rt); - static void sweepCompartment(JSCompartment *compartment); - static void detachAllDebuggersFromGlobal(GlobalObject *global, + static void sweepAll(JSContext *cx); + static void sweepCompartment(JSContext *cx, JSCompartment *compartment); + static void detachAllDebuggersFromGlobal(JSContext *cx, GlobalObject *global, GlobalObjectSet::Enum *compartmentEnum); static inline void leaveStackFrame(JSContext *cx); diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index d4db795301a..de6673137d1 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -101,7 +101,7 @@ typedef struct JSTrap { JS_PUBLIC_API(JSBool) JS_GetDebugMode(JSContext *cx) { - return cx->compartment->debugMode; + return cx->compartment->debugMode(); } JS_PUBLIC_API(JSBool) @@ -113,7 +113,7 @@ JS_SetDebugMode(JSContext *cx, JSBool debug) JS_PUBLIC_API(void) JS_SetRuntimeDebugMode(JSRuntime *rt, JSBool debug) { - rt->debugMode = debug; + rt->debugMode = !!debug; } namespace js { @@ -159,60 +159,7 @@ ScriptDebugEpilogue(JSContext *cx, StackFrame *fp, bool okArg) JS_FRIEND_API(JSBool) JS_SetDebugModeForCompartment(JSContext *cx, JSCompartment *comp, JSBool debug) { - if (comp->debugMode == !!debug) - return JS_TRUE; - - if (debug) { - // This should only be called when no scripts are live. It would even - // be incorrect to discard just the non-live scripts' JITScripts - // because they might share ICs with live scripts (bug 632343). - for (AllFramesIter i(cx); !i.done(); ++i) { - JSScript *script = i.fp()->maybeScript(); - if (script && script->compartment == comp) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_DEBUG_NOT_IDLE); - return false; - } - } - } - - // All scripts compiled from this point on should be in the requested debugMode. - comp->debugMode = !!debug; - - // Detach any debuggers attached to this compartment. - if (debug) - JS_ASSERT(comp->getDebuggees().empty()); - else - Debug::detachFromCompartment(comp); - - // Discard JIT code for any scripts that change debugMode. This function - // assumes that 'comp' is in the same thread as 'cx'. -#ifdef JS_METHODJIT - JS::AutoEnterScriptCompartment ac; - - for (JSScript *script = (JSScript *)comp->scripts.next; - &script->links != &comp->scripts; - script = (JSScript *)script->links.next) - { - if (!script->debugMode == !debug) - continue; - - /* - * If compartment entry fails, debug mode is left partially on, leading - * to a small performance overhead but no loss of correctness. We set - * the debug flags to false so that the caller will not later attempt - * to use debugging features. - */ - if (!ac.entered() && !ac.enter(cx, script)) { - comp->debugMode = JS_FALSE; - return JS_FALSE; - } - - mjit::ReleaseScriptCode(cx, script); - script->debugMode = !!debug; - } -#endif - - return JS_TRUE; + return comp->setDebugModeFromC(cx, !!debug); } JS_FRIEND_API(JSBool) @@ -225,7 +172,7 @@ js_SetSingleStepMode(JSContext *cx, JSScript *script, JSBool singleStep) return JS_TRUE; #endif - JS_ASSERT_IF(singleStep, cx->compartment->debugMode); + JS_ASSERT_IF(singleStep, cx->compartment->debugMode()); #ifdef JS_METHODJIT /* request the next recompile to inject single step interrupts */ diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index ec916ea3f31..7240a2bb93e 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -2369,7 +2369,7 @@ MarkAndSweep(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind GCTIM js_SweepWatchPoints(cx); if (!comp) - Debug::sweepAll(rt); + Debug::sweepAll(cx); /* * We finalize objects before other GC things to ensure that object's finalizer diff --git a/js/src/jsinterpinlines.h b/js/src/jsinterpinlines.h index 9b1ec580afe..99f432c4a28 100644 --- a/js/src/jsinterpinlines.h +++ b/js/src/jsinterpinlines.h @@ -353,7 +353,7 @@ ScriptPrologue(JSContext *cx, StackFrame *fp) fp->functionThis().setObject(*obj); } - if (cx->compartment->debugMode) + if (cx->compartment->debugMode()) ScriptDebugPrologue(cx, fp); return true; } @@ -361,7 +361,7 @@ ScriptPrologue(JSContext *cx, StackFrame *fp) inline bool ScriptEpilogue(JSContext *cx, StackFrame *fp, bool ok) { - if (cx->compartment->debugMode) + if (cx->compartment->debugMode()) ok = ScriptDebugEpilogue(cx, fp, ok); /* @@ -382,7 +382,7 @@ ScriptPrologueOrGeneratorResume(JSContext *cx, StackFrame *fp) { if (!fp->isGeneratorFrame()) return ScriptPrologue(cx, fp); - if (cx->compartment->debugMode) + if (cx->compartment->debugMode()) ScriptDebugPrologue(cx, fp); return true; } @@ -392,7 +392,7 @@ ScriptEpilogueOrGeneratorYield(JSContext *cx, StackFrame *fp, bool ok) { if (!fp->isYielding()) return ScriptEpilogue(cx, fp, ok); - if (cx->compartment->debugMode) + if (cx->compartment->debugMode()) return ScriptDebugEpilogue(cx, fp, ok); return ok; } diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index 0db553b77d7..97a7a453c56 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -114,7 +114,7 @@ mjit::Compiler::Compiler(JSContext *cx, StackFrame *fp) jumpTables(CompilerAllocPolicy(cx, *thisFromCtor())), jumpTableOffsets(CompilerAllocPolicy(cx, *thisFromCtor())), stubcc(cx, *thisFromCtor(), frame, script), - debugMode_(cx->compartment->debugMode), + debugMode_(cx->compartment->debugMode()), #if defined JS_TRACER addTraceHints(cx->traceJitEnabled), #endif diff --git a/js/src/methodjit/FrameState.cpp b/js/src/methodjit/FrameState.cpp index 933e95c35b6..0f890361343 100644 --- a/js/src/methodjit/FrameState.cpp +++ b/js/src/methodjit/FrameState.cpp @@ -80,7 +80,7 @@ FrameState::init() return false; #endif - eval = script->usesEval || cx->compartment->debugMode; + eval = script->usesEval || cx->compartment->debugMode(); size_t totalBytes = sizeof(FrameEntry) * nentries + // entries[], w/ callee+this sizeof(FrameEntry *) * nentries + // tracker.entries diff --git a/js/src/methodjit/Retcon.cpp b/js/src/methodjit/Retcon.cpp index 05dd2e1e07e..8f370fdd3b8 100644 --- a/js/src/methodjit/Retcon.cpp +++ b/js/src/methodjit/Retcon.cpp @@ -202,7 +202,7 @@ Recompiler::recompile(StackFrame *fp, Vector &patches, Vector &sites) { /* If we get this far, the script is live, and we better be safe to re-jit. */ - JS_ASSERT(cx->compartment->debugMode); + JS_ASSERT(cx->compartment->debugMode()); JS_ASSERT(fp); Compiler c(cx, fp); diff --git a/js/src/vm/GlobalObject.cpp b/js/src/vm/GlobalObject.cpp index df7cda6b467..aac866a11d0 100644 --- a/js/src/vm/GlobalObject.cpp +++ b/js/src/vm/GlobalObject.cpp @@ -253,10 +253,10 @@ GlobalObject::addDebug(JSContext *cx, Debug *dbg) for (Debug **p = vec->begin(); p != vec->end(); p++) JS_ASSERT(*p != dbg); #endif - if (vec->empty() && !compartment()->addDebuggee(this)) + if (vec->empty() && !compartment()->addDebuggee(cx, this)) return false; if (!vec->append(dbg)) { - compartment()->removeDebuggee(this); + compartment()->removeDebuggee(cx, this); return false; } return true;