michael@0: /* Any copyright is dedicated to the Public Domain. michael@0: http://creativecommons.org/publicdomain/zero/1.0/ */ michael@0: michael@0: /** michael@0: * Bug 727429: Test the debugger watch expressions. michael@0: */ michael@0: michael@0: const TAB_URL = EXAMPLE_URL + "doc_watch-expressions.html"; michael@0: michael@0: function test() { michael@0: // Debug test slaves are a bit slow at this test. michael@0: requestLongerTimeout(2); michael@0: michael@0: let gTab, gDebuggee, gPanel, gDebugger; michael@0: let gWatch, gVariables; michael@0: michael@0: initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { michael@0: gTab = aTab; michael@0: gDebuggee = aDebuggee; michael@0: gPanel = aPanel; michael@0: gDebugger = gPanel.panelWin; michael@0: gWatch = gDebugger.DebuggerView.WatchExpressions; michael@0: gVariables = gDebugger.DebuggerView.Variables; michael@0: michael@0: gDebugger.DebuggerView.toggleInstrumentsPane({ visible: true, animated: false }); michael@0: michael@0: waitForSourceShown(gPanel, ".html", 1) michael@0: .then(() => addExpressions()) michael@0: .then(() => performTest()) michael@0: .then(() => finishTest()) michael@0: .then(() => closeDebuggerAndFinish(gPanel)) michael@0: .then(null, aError => { michael@0: ok(false, "Got an error: " + aError.message + "\n" + aError.stack); michael@0: }); michael@0: }); michael@0: michael@0: function addExpressions() { michael@0: gWatch.addExpression("'a'"); michael@0: gWatch.addExpression("\"a\""); michael@0: gWatch.addExpression("'a\"\"'"); michael@0: gWatch.addExpression("\"a''\""); michael@0: gWatch.addExpression("?"); michael@0: gWatch.addExpression("a"); michael@0: gWatch.addExpression("this"); michael@0: gWatch.addExpression("this.canada"); michael@0: gWatch.addExpression("[1, 2, 3]"); michael@0: gWatch.addExpression("x = [1, 2, 3]"); michael@0: gWatch.addExpression("y = [1, 2, 3]; y.test = 4"); michael@0: gWatch.addExpression("z = [1, 2, 3]; z.test = 4; z"); michael@0: gWatch.addExpression("t = [1, 2, 3]; t.test = 4; !t"); michael@0: gWatch.addExpression("arguments[0]"); michael@0: gWatch.addExpression("encodeURI(\"\\\")"); michael@0: gWatch.addExpression("decodeURI(\"\\\")"); michael@0: gWatch.addExpression("decodeURIComponent(\"%\")"); michael@0: gWatch.addExpression("//"); michael@0: gWatch.addExpression("// 42"); michael@0: gWatch.addExpression("{}.foo"); michael@0: gWatch.addExpression("{}.foo()"); michael@0: gWatch.addExpression("({}).foo()"); michael@0: gWatch.addExpression("new Array(-1)"); michael@0: gWatch.addExpression("4.2.toExponential(-4.2)"); michael@0: gWatch.addExpression("throw new Error(\"bazinga\")"); michael@0: gWatch.addExpression("({ get error() { throw new Error(\"bazinga\") } }).error"); michael@0: gWatch.addExpression("throw { get name() { throw \"bazinga\" } }"); michael@0: } michael@0: michael@0: function performTest() { michael@0: let deferred = promise.defer(); michael@0: michael@0: is(gDebugger.document.querySelectorAll(".dbg-expression[hidden=true]").length, 0, michael@0: "There should be 0 hidden nodes in the watch expressions container"); michael@0: is(gDebugger.document.querySelectorAll(".dbg-expression:not([hidden=true])").length, 27, michael@0: "There should be 27 visible nodes in the watch expressions container"); michael@0: michael@0: test1(function() { michael@0: test2(function() { michael@0: test3(function() { michael@0: test4(function() { michael@0: test5(function() { michael@0: test6(function() { michael@0: test7(function() { michael@0: test8(function() { michael@0: test9(function() { michael@0: deferred.resolve(); michael@0: }); michael@0: }); michael@0: }); michael@0: }); michael@0: }); michael@0: }); michael@0: }); michael@0: }); michael@0: }); michael@0: michael@0: return deferred.promise; michael@0: } michael@0: michael@0: function finishTest() { michael@0: is(gDebugger.document.querySelectorAll(".dbg-expression[hidden=true]").length, 0, michael@0: "There should be 0 hidden nodes in the watch expressions container"); michael@0: is(gDebugger.document.querySelectorAll(".dbg-expression:not([hidden=true])").length, 27, michael@0: "There should be 27 visible nodes in the watch expressions container"); michael@0: } michael@0: michael@0: function test1(aCallback) { michael@0: gDebugger.once(gDebugger.EVENTS.FETCHED_WATCH_EXPRESSIONS, () => { michael@0: checkWatchExpressions(26, { michael@0: a: "ReferenceError: a is not defined", michael@0: this: { type: "object", class: "Object" }, michael@0: prop: { type: "object", class: "String" }, michael@0: args: { type: "undefined" } michael@0: }); michael@0: aCallback(); michael@0: }); michael@0: michael@0: gDebuggee.test(); michael@0: } michael@0: michael@0: function test2(aCallback) { michael@0: gDebugger.once(gDebugger.EVENTS.FETCHED_WATCH_EXPRESSIONS, () => { michael@0: checkWatchExpressions(26, { michael@0: a: { type: "undefined" }, michael@0: this: { type: "object", class: "Window" }, michael@0: prop: { type: "undefined" }, michael@0: args: "sensational" michael@0: }); michael@0: aCallback(); michael@0: }); michael@0: michael@0: EventUtils.sendMouseEvent({ type: "mousedown" }, michael@0: gDebugger.document.getElementById("resume"), michael@0: gDebugger); michael@0: } michael@0: michael@0: function test3(aCallback) { michael@0: gDebugger.once(gDebugger.EVENTS.FETCHED_WATCH_EXPRESSIONS, () => { michael@0: checkWatchExpressions(26, { michael@0: a: { type: "object", class: "Object" }, michael@0: this: { type: "object", class: "Window" }, michael@0: prop: { type: "undefined" }, michael@0: args: "sensational" michael@0: }); michael@0: aCallback(); michael@0: }); michael@0: michael@0: EventUtils.sendMouseEvent({ type: "mousedown" }, michael@0: gDebugger.document.getElementById("resume"), michael@0: gDebugger); michael@0: } michael@0: michael@0: function test4(aCallback) { michael@0: gDebugger.once(gDebugger.EVENTS.FETCHED_WATCH_EXPRESSIONS, () => { michael@0: checkWatchExpressions(27, { michael@0: a: 5, michael@0: this: { type: "object", class: "Window" }, michael@0: prop: { type: "undefined" }, michael@0: args: "sensational" michael@0: }); michael@0: aCallback(); michael@0: }); michael@0: michael@0: gWatch.addExpression("a = 5"); michael@0: EventUtils.sendKey("RETURN", gDebugger); michael@0: } michael@0: michael@0: function test5(aCallback) { michael@0: gDebugger.once(gDebugger.EVENTS.FETCHED_WATCH_EXPRESSIONS, () => { michael@0: checkWatchExpressions(27, { michael@0: a: 5, michael@0: this: { type: "object", class: "Window" }, michael@0: prop: { type: "undefined" }, michael@0: args: "sensational" michael@0: }); michael@0: aCallback(); michael@0: }); michael@0: michael@0: gWatch.addExpression("encodeURI(\"\\\")"); michael@0: EventUtils.sendKey("RETURN", gDebugger); michael@0: } michael@0: michael@0: function test6(aCallback) { michael@0: gDebugger.once(gDebugger.EVENTS.FETCHED_WATCH_EXPRESSIONS, () => { michael@0: checkWatchExpressions(27, { michael@0: a: 5, michael@0: this: { type: "object", class: "Window" }, michael@0: prop: { type: "undefined" }, michael@0: args: "sensational" michael@0: }); michael@0: aCallback(); michael@0: }) michael@0: michael@0: gWatch.addExpression("decodeURI(\"\\\")"); michael@0: EventUtils.sendKey("RETURN", gDebugger); michael@0: } michael@0: michael@0: function test7(aCallback) { michael@0: gDebugger.once(gDebugger.EVENTS.FETCHED_WATCH_EXPRESSIONS, () => { michael@0: checkWatchExpressions(27, { michael@0: a: 5, michael@0: this: { type: "object", class: "Window" }, michael@0: prop: { type: "undefined" }, michael@0: args: "sensational" michael@0: }); michael@0: aCallback(); michael@0: }); michael@0: michael@0: gWatch.addExpression("?"); michael@0: EventUtils.sendKey("RETURN", gDebugger); michael@0: } michael@0: michael@0: function test8(aCallback) { michael@0: gDebugger.once(gDebugger.EVENTS.FETCHED_WATCH_EXPRESSIONS, () => { michael@0: checkWatchExpressions(27, { michael@0: a: 5, michael@0: this: { type: "object", class: "Window" }, michael@0: prop: { type: "undefined" }, michael@0: args: "sensational" michael@0: }); michael@0: aCallback(); michael@0: }); michael@0: michael@0: gWatch.addExpression("a"); michael@0: EventUtils.sendKey("RETURN", gDebugger); michael@0: } michael@0: michael@0: function test9(aCallback) { michael@0: gDebugger.once(gDebugger.EVENTS.AFTER_FRAMES_CLEARED, () => { michael@0: aCallback(); michael@0: }); michael@0: michael@0: EventUtils.sendMouseEvent({ type: "mousedown" }, michael@0: gDebugger.document.getElementById("resume"), michael@0: gDebugger); michael@0: } michael@0: michael@0: function checkWatchExpressions(aTotal, aExpectedExpressions) { michael@0: let { michael@0: a: expected_a, michael@0: this: expected_this, michael@0: prop: expected_prop, michael@0: args: expected_args michael@0: } = aExpectedExpressions; michael@0: michael@0: is(gDebugger.document.querySelectorAll(".dbg-expression[hidden=true]").length, aTotal, michael@0: "There should be " + aTotal + " hidden nodes in the watch expressions container."); michael@0: is(gDebugger.document.querySelectorAll(".dbg-expression:not([hidden=true])").length, 0, michael@0: "There should be 0 visible nodes in the watch expressions container."); michael@0: michael@0: let label = gDebugger.L10N.getStr("watchExpressionsScopeLabel"); michael@0: let scope = gVariables._currHierarchy.get(label); michael@0: michael@0: ok(scope, "There should be a wach expressions scope in the variables view."); michael@0: is(scope._store.size, aTotal, "There should be " + aTotal + " evaluations availalble."); michael@0: michael@0: let w1 = scope.get("'a'"); michael@0: let w2 = scope.get("\"a\""); michael@0: let w3 = scope.get("'a\"\"'"); michael@0: let w4 = scope.get("\"a''\""); michael@0: let w5 = scope.get("?"); michael@0: let w6 = scope.get("a"); michael@0: let w7 = scope.get("this"); michael@0: let w8 = scope.get("this.canada"); michael@0: let w9 = scope.get("[1, 2, 3]"); michael@0: let w10 = scope.get("x = [1, 2, 3]"); michael@0: let w11 = scope.get("y = [1, 2, 3]; y.test = 4"); michael@0: let w12 = scope.get("z = [1, 2, 3]; z.test = 4; z"); michael@0: let w13 = scope.get("t = [1, 2, 3]; t.test = 4; !t"); michael@0: let w14 = scope.get("arguments[0]"); michael@0: let w15 = scope.get("encodeURI(\"\\\")"); michael@0: let w16 = scope.get("decodeURI(\"\\\")"); michael@0: let w17 = scope.get("decodeURIComponent(\"%\")"); michael@0: let w18 = scope.get("//"); michael@0: let w19 = scope.get("// 42"); michael@0: let w20 = scope.get("{}.foo"); michael@0: let w21 = scope.get("{}.foo()"); michael@0: let w22 = scope.get("({}).foo()"); michael@0: let w23 = scope.get("new Array(-1)"); michael@0: let w24 = scope.get("4.2.toExponential(-4.2)"); michael@0: let w25 = scope.get("throw new Error(\"bazinga\")"); michael@0: let w26 = scope.get("({ get error() { throw new Error(\"bazinga\") } }).error"); michael@0: let w27 = scope.get("throw { get name() { throw \"bazinga\" } }"); michael@0: michael@0: ok(w1, "The first watch expression should be present in the scope."); michael@0: ok(w2, "The second watch expression should be present in the scope."); michael@0: ok(w3, "The third watch expression should be present in the scope."); michael@0: ok(w4, "The fourth watch expression should be present in the scope."); michael@0: ok(w5, "The fifth watch expression should be present in the scope."); michael@0: ok(w6, "The sixth watch expression should be present in the scope."); michael@0: ok(w7, "The seventh watch expression should be present in the scope."); michael@0: ok(w8, "The eight watch expression should be present in the scope."); michael@0: ok(w9, "The ninth watch expression should be present in the scope."); michael@0: ok(w10, "The tenth watch expression should be present in the scope."); michael@0: ok(w11, "The eleventh watch expression should be present in the scope."); michael@0: ok(w12, "The twelfth watch expression should be present in the scope."); michael@0: ok(w13, "The 13th watch expression should be present in the scope."); michael@0: ok(w14, "The 14th watch expression should be present in the scope."); michael@0: ok(w15, "The 15th watch expression should be present in the scope."); michael@0: ok(w16, "The 16th watch expression should be present in the scope."); michael@0: ok(w17, "The 17th watch expression should be present in the scope."); michael@0: ok(w18, "The 18th watch expression should be present in the scope."); michael@0: ok(w19, "The 19th watch expression should be present in the scope."); michael@0: ok(w20, "The 20th watch expression should be present in the scope."); michael@0: ok(w21, "The 21st watch expression should be present in the scope."); michael@0: ok(w22, "The 22nd watch expression should be present in the scope."); michael@0: ok(w23, "The 23nd watch expression should be present in the scope."); michael@0: ok(w24, "The 24th watch expression should be present in the scope."); michael@0: ok(w25, "The 25th watch expression should be present in the scope."); michael@0: ok(w26, "The 26th watch expression should be present in the scope."); michael@0: ok(!w27, "The 27th watch expression should not be present in the scope."); michael@0: michael@0: is(w1.value, "a", "The first value is correct."); michael@0: is(w2.value, "a", "The second value is correct."); michael@0: is(w3.value, "a\"\"", "The third value is correct."); michael@0: is(w4.value, "a''", "The fourth value is correct."); michael@0: is(w5.value, "SyntaxError: syntax error", "The fifth value is correct."); michael@0: michael@0: if (typeof expected_a == "object") { michael@0: is(w6.value.type, expected_a.type, "The sixth value type is correct."); michael@0: is(w6.value.class, expected_a.class, "The sixth value class is correct."); michael@0: } else { michael@0: is(w6.value, expected_a, "The sixth value is correct."); michael@0: } michael@0: michael@0: if (typeof expected_this == "object") { michael@0: is(w7.value.type, expected_this.type, "The seventh value type is correct."); michael@0: is(w7.value.class, expected_this.class, "The seventh value class is correct."); michael@0: } else { michael@0: is(w7.value, expected_this, "The seventh value is correct."); michael@0: } michael@0: michael@0: if (typeof expected_prop == "object") { michael@0: is(w8.value.type, expected_prop.type, "The eighth value type is correct."); michael@0: is(w8.value.class, expected_prop.class, "The eighth value class is correct."); michael@0: } else { michael@0: is(w8.value, expected_prop, "The eighth value is correct."); michael@0: } michael@0: michael@0: is(w9.value.type, "object", "The ninth value type is correct."); michael@0: is(w9.value.class, "Array", "The ninth value class is correct."); michael@0: is(w10.value.type, "object", "The tenth value type is correct."); michael@0: is(w10.value.class, "Array", "The tenth value class is correct."); michael@0: is(w11.value, "4", "The eleventh value is correct."); michael@0: is(w12.value.type, "object", "The eleventh value type is correct."); michael@0: is(w12.value.class, "Array", "The twelfth value class is correct."); michael@0: is(w13.value, false, "The 13th value is correct."); michael@0: michael@0: if (typeof expected_args == "object") { michael@0: is(w14.value.type, expected_args.type, "The 14th value type is correct."); michael@0: is(w14.value.class, expected_args.class, "The 14th value class is correct."); michael@0: } else { michael@0: is(w14.value, expected_args, "The 14th value is correct."); michael@0: } michael@0: michael@0: is(w15.value, "SyntaxError: unterminated string literal", "The 15th value is correct."); michael@0: is(w16.value, "SyntaxError: unterminated string literal", "The 16th value is correct."); michael@0: is(w17.value, "URIError: malformed URI sequence", "The 17th value is correct."); michael@0: michael@0: is(w18.value.type, "undefined", "The 18th value type is correct."); michael@0: is(w18.value.class, undefined, "The 18th value class is correct."); michael@0: michael@0: is(w19.value.type, "undefined", "The 19th value type is correct."); michael@0: is(w19.value.class, undefined, "The 19th value class is correct."); michael@0: michael@0: is(w20.value, "SyntaxError: syntax error", "The 20th value is correct."); michael@0: is(w21.value, "SyntaxError: syntax error", "The 21th value is correct."); michael@0: is(w22.value, "TypeError: (intermediate value).foo is not a function", "The 22th value is correct."); michael@0: is(w23.value, "RangeError: invalid array length", "The 23th value is correct."); michael@0: is(w24.value, "RangeError: precision -4 out of range", "The 24th value is correct."); michael@0: is(w25.value, "Error: bazinga", "The 25th value is correct."); michael@0: is(w26.value, "Error: bazinga", "The 26th value is correct."); michael@0: } michael@0: }