/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ /* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ /** * Make sure that the variables view displays the right variables and * properties when debugger is paused. */ const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html"; var gTab, gPanel, gDebugger; var gVariables; function test() { // Debug test slaves are a bit slow at this test. requestLongerTimeout(2); let options = { source: TAB_URL, line: 1 }; initDebugger(TAB_URL, options).then(([aTab,, aPanel]) => { gTab = aTab; gPanel = aPanel; gDebugger = gPanel.panelWin; gVariables = gDebugger.DebuggerView.Variables; waitForCaretAndScopes(gPanel, 24) .then(testScopeVariables) .then(testArgumentsProperties) .then(testSimpleObject) .then(testComplexObject) .then(testArgumentObject) .then(testInnerArgumentObject) .then(testGetterSetterObject) .then(() => resumeDebuggerThenCloseAndFinish(gPanel)) .then(null, aError => { ok(false, "Got an error: " + aError.message + "\n" + aError.stack); }); generateMouseClickInTab(gTab, "content.document.querySelector('button')"); }); } function testScopeVariables() { let localScope = gVariables.getScopeAtIndex(0); is(localScope.expanded, true, "The local scope should be expanded by default."); let localEnums = localScope.target.querySelector(".variables-view-element-details.enum").childNodes; let localNonEnums = localScope.target.querySelector(".variables-view-element-details.nonenum").childNodes; is(localEnums.length, 12, "The local scope should contain all the created enumerable elements."); is(localNonEnums.length, 0, "The local scope should contain all the created non-enumerable elements."); is(localEnums[0].querySelector(".name").getAttribute("value"), "this", "Should have the right property name for 'this'."); is(localEnums[0].querySelector(".value").getAttribute("value"), "Window \u2192 doc_frame-parameters.html", "Should have the right property value for 'this'."); ok(localEnums[0].querySelector(".value").className.includes("token-other"), "Should have the right token class for 'this'."); is(localEnums[1].querySelector(".name").getAttribute("value"), "aArg", "Should have the right property name for 'aArg'."); is(localEnums[1].querySelector(".value").getAttribute("value"), "Object", "Should have the right property value for 'aArg'."); ok(localEnums[1].querySelector(".value").className.includes("token-other"), "Should have the right token class for 'aArg'."); is(localEnums[2].querySelector(".name").getAttribute("value"), "bArg", "Should have the right property name for 'bArg'."); is(localEnums[2].querySelector(".value").getAttribute("value"), "\"beta\"", "Should have the right property value for 'bArg'."); ok(localEnums[2].querySelector(".value").className.includes("token-string"), "Should have the right token class for 'bArg'."); is(localEnums[3].querySelector(".name").getAttribute("value"), "cArg", "Should have the right property name for 'cArg'."); is(localEnums[3].querySelector(".value").getAttribute("value"), "3", "Should have the right property value for 'cArg'."); ok(localEnums[3].querySelector(".value").className.includes("token-number"), "Should have the right token class for 'cArg'."); is(localEnums[4].querySelector(".name").getAttribute("value"), "dArg", "Should have the right property name for 'dArg'."); is(localEnums[4].querySelector(".value").getAttribute("value"), "false", "Should have the right property value for 'dArg'."); ok(localEnums[4].querySelector(".value").className.includes("token-boolean"), "Should have the right token class for 'dArg'."); is(localEnums[5].querySelector(".name").getAttribute("value"), "eArg", "Should have the right property name for 'eArg'."); is(localEnums[5].querySelector(".value").getAttribute("value"), "null", "Should have the right property value for 'eArg'."); ok(localEnums[5].querySelector(".value").className.includes("token-null"), "Should have the right token class for 'eArg'."); is(localEnums[6].querySelector(".name").getAttribute("value"), "fArg", "Should have the right property name for 'fArg'."); is(localEnums[6].querySelector(".value").getAttribute("value"), "undefined", "Should have the right property value for 'fArg'."); ok(localEnums[6].querySelector(".value").className.includes("token-undefined"), "Should have the right token class for 'fArg'."); is(localEnums[7].querySelector(".name").getAttribute("value"), "a", "Should have the right property name for 'a'."); is(localEnums[7].querySelector(".value").getAttribute("value"), "1", "Should have the right property value for 'a'."); ok(localEnums[7].querySelector(".value").className.includes("token-number"), "Should have the right token class for 'a'."); is(localEnums[8].querySelector(".name").getAttribute("value"), "arguments", "Should have the right property name for 'arguments'."); is(localEnums[8].querySelector(".value").getAttribute("value"), "Arguments", "Should have the right property value for 'arguments'."); ok(localEnums[8].querySelector(".value").className.includes("token-other"), "Should have the right token class for 'arguments'."); is(localEnums[9].querySelector(".name").getAttribute("value"), "b", "Should have the right property name for 'b'."); is(localEnums[9].querySelector(".value").getAttribute("value"), "Object", "Should have the right property value for 'b'."); ok(localEnums[9].querySelector(".value").className.includes("token-other"), "Should have the right token class for 'b'."); is(localEnums[10].querySelector(".name").getAttribute("value"), "c", "Should have the right property name for 'c'."); is(localEnums[10].querySelector(".value").getAttribute("value"), "Object", "Should have the right property value for 'c'."); ok(localEnums[10].querySelector(".value").className.includes("token-other"), "Should have the right token class for 'c'."); is(localEnums[11].querySelector(".name").getAttribute("value"), "myVar", "Should have the right property name for 'myVar'."); is(localEnums[11].querySelector(".value").getAttribute("value"), "Object", "Should have the right property value for 'myVar'."); ok(localEnums[11].querySelector(".value").className.includes("token-other"), "Should have the right token class for 'myVar'."); } function testArgumentsProperties() { let deferred = promise.defer(); let argsVar = gVariables.getScopeAtIndex(0).get("arguments"); is(argsVar.expanded, false, "The 'arguments' variable should not be expanded by default."); let argsEnums = argsVar.target.querySelector(".variables-view-element-details.enum").childNodes; let argsNonEnums = argsVar.target.querySelector(".variables-view-element-details.nonenum").childNodes; gDebugger.once(gDebugger.EVENTS.FETCHED_PROPERTIES, () => { is(argsEnums.length, 5, "The 'arguments' variable should contain all the created enumerable elements."); is(argsNonEnums.length, 3, "The 'arguments' variable should contain all the created non-enumerable elements."); is(argsEnums[0].querySelector(".name").getAttribute("value"), "0", "Should have the right property name for '0'."); is(argsEnums[0].querySelector(".value").getAttribute("value"), "Object", "Should have the right property value for '0'."); ok(argsEnums[0].querySelector(".value").className.includes("token-other"), "Should have the right token class for '0'."); is(argsEnums[1].querySelector(".name").getAttribute("value"), "1", "Should have the right property name for '1'."); is(argsEnums[1].querySelector(".value").getAttribute("value"), "\"beta\"", "Should have the right property value for '1'."); ok(argsEnums[1].querySelector(".value").className.includes("token-string"), "Should have the right token class for '1'."); is(argsEnums[2].querySelector(".name").getAttribute("value"), "2", "Should have the right property name for '2'."); is(argsEnums[2].querySelector(".value").getAttribute("value"), "3", "Should have the right property name for '2'."); ok(argsEnums[2].querySelector(".value").className.includes("token-number"), "Should have the right token class for '2'."); is(argsEnums[3].querySelector(".name").getAttribute("value"), "3", "Should have the right property name for '3'."); is(argsEnums[3].querySelector(".value").getAttribute("value"), "false", "Should have the right property value for '3'."); ok(argsEnums[3].querySelector(".value").className.includes("token-boolean"), "Should have the right token class for '3'."); is(argsEnums[4].querySelector(".name").getAttribute("value"), "4", "Should have the right property name for '4'."); is(argsEnums[4].querySelector(".value").getAttribute("value"), "null", "Should have the right property name for '4'."); ok(argsEnums[4].querySelector(".value").className.includes("token-null"), "Should have the right token class for '4'."); is(argsNonEnums[0].querySelector(".name").getAttribute("value"), "callee", "Should have the right property name for 'callee'."); is(argsNonEnums[0].querySelector(".value").getAttribute("value"), "test(aArg,bArg,cArg,dArg,eArg,fArg)", "Should have the right property name for 'callee'."); ok(argsNonEnums[0].querySelector(".value").className.includes("token-other"), "Should have the right token class for 'callee'."); is(argsNonEnums[1].querySelector(".name").getAttribute("value"), "length", "Should have the right property name for 'length'."); is(argsNonEnums[1].querySelector(".value").getAttribute("value"), "5", "Should have the right property value for 'length'."); ok(argsNonEnums[1].querySelector(".value").className.includes("token-number"), "Should have the right token class for 'length'."); is(argsNonEnums[2].querySelector(".name").getAttribute("value"), "__proto__", "Should have the right property name for '__proto__'."); is(argsNonEnums[2].querySelector(".value").getAttribute("value"), "Object", "Should have the right property value for '__proto__'."); ok(argsNonEnums[2].querySelector(".value").className.includes("token-other"), "Should have the right token class for '__proto__'."); deferred.resolve(); }); argsVar.expand(); return deferred.promise; } function testSimpleObject() { let deferred = promise.defer(); let bVar = gVariables.getScopeAtIndex(0).get("b"); is(bVar.expanded, false, "The 'b' variable should not be expanded by default."); let bEnums = bVar.target.querySelector(".variables-view-element-details.enum").childNodes; let bNonEnums = bVar.target.querySelector(".variables-view-element-details.nonenum").childNodes; gDebugger.once(gDebugger.EVENTS.FETCHED_PROPERTIES, () => { is(bEnums.length, 1, "The 'b' variable should contain all the created enumerable elements."); is(bNonEnums.length, 1, "The 'b' variable should contain all the created non-enumerable elements."); is(bEnums[0].querySelector(".name").getAttribute("value"), "a", "Should have the right property name for 'a'."); is(bEnums[0].querySelector(".value").getAttribute("value"), "1", "Should have the right property value for 'a'."); ok(bEnums[0].querySelector(".value").className.includes("token-number"), "Should have the right token class for 'a'."); is(bNonEnums[0].querySelector(".name").getAttribute("value"), "__proto__", "Should have the right property name for '__proto__'."); is(bNonEnums[0].querySelector(".value").getAttribute("value"), "Object", "Should have the right property value for '__proto__'."); ok(bNonEnums[0].querySelector(".value").className.includes("token-other"), "Should have the right token class for '__proto__'."); deferred.resolve(); }); bVar.expand(); return deferred.promise; } function testComplexObject() { let deferred = promise.defer(); let cVar = gVariables.getScopeAtIndex(0).get("c"); is(cVar.expanded, false, "The 'c' variable should not be expanded by default."); let cEnums = cVar.target.querySelector(".variables-view-element-details.enum").childNodes; let cNonEnums = cVar.target.querySelector(".variables-view-element-details.nonenum").childNodes; gDebugger.once(gDebugger.EVENTS.FETCHED_PROPERTIES, () => { is(cEnums.length, 6, "The 'c' variable should contain all the created enumerable elements."); is(cNonEnums.length, 1, "The 'c' variable should contain all the created non-enumerable elements."); is(cEnums[0].querySelector(".name").getAttribute("value"), "a", "Should have the right property name for 'a'."); is(cEnums[0].querySelector(".value").getAttribute("value"), "1", "Should have the right property value for 'a'."); ok(cEnums[0].querySelector(".value").className.includes("token-number"), "Should have the right token class for 'a'."); is(cEnums[1].querySelector(".name").getAttribute("value"), "b", "Should have the right property name for 'b'."); is(cEnums[1].querySelector(".value").getAttribute("value"), "\"beta\"", "Should have the right property value for 'b'."); ok(cEnums[1].querySelector(".value").className.includes("token-string"), "Should have the right token class for 'b'."); is(cEnums[2].querySelector(".name").getAttribute("value"), "c", "Should have the right property name for 'c'."); is(cEnums[2].querySelector(".value").getAttribute("value"), "3", "Should have the right property value for 'c'."); ok(cEnums[2].querySelector(".value").className.includes("token-number"), "Should have the right token class for 'c'."); is(cEnums[3].querySelector(".name").getAttribute("value"), "d", "Should have the right property name for 'd'."); is(cEnums[3].querySelector(".value").getAttribute("value"), "false", "Should have the right property value for 'd'."); ok(cEnums[3].querySelector(".value").className.includes("token-boolean"), "Should have the right token class for 'd'."); is(cEnums[4].querySelector(".name").getAttribute("value"), "e", "Should have the right property name for 'e'."); is(cEnums[4].querySelector(".value").getAttribute("value"), "null", "Should have the right property value for 'e'."); ok(cEnums[4].querySelector(".value").className.includes("token-null"), "Should have the right token class for 'e'."); is(cEnums[5].querySelector(".name").getAttribute("value"), "f", "Should have the right property name for 'f'."); is(cEnums[5].querySelector(".value").getAttribute("value"), "undefined", "Should have the right property value for 'f'."); ok(cEnums[5].querySelector(".value").className.includes("token-undefined"), "Should have the right token class for 'f'."); is(cNonEnums[0].querySelector(".name").getAttribute("value"), "__proto__", "Should have the right property name for '__proto__'."); is(cNonEnums[0].querySelector(".value").getAttribute("value"), "Object", "Should have the right property value for '__proto__'."); ok(cNonEnums[0].querySelector(".value").className.includes("token-other"), "Should have the right token class for '__proto__'."); deferred.resolve(); }); cVar.expand(); return deferred.promise; } function testArgumentObject() { let deferred = promise.defer(); let argVar = gVariables.getScopeAtIndex(0).get("aArg"); is(argVar.expanded, false, "The 'aArg' variable should not be expanded by default."); let argEnums = argVar.target.querySelector(".variables-view-element-details.enum").childNodes; let argNonEnums = argVar.target.querySelector(".variables-view-element-details.nonenum").childNodes; gDebugger.once(gDebugger.EVENTS.FETCHED_PROPERTIES, () => { is(argEnums.length, 6, "The 'aArg' variable should contain all the created enumerable elements."); is(argNonEnums.length, 1, "The 'aArg' variable should contain all the created non-enumerable elements."); is(argEnums[0].querySelector(".name").getAttribute("value"), "a", "Should have the right property name for 'a'."); is(argEnums[0].querySelector(".value").getAttribute("value"), "1", "Should have the right property value for 'a'."); ok(argEnums[0].querySelector(".value").className.includes("token-number"), "Should have the right token class for 'a'."); is(argEnums[1].querySelector(".name").getAttribute("value"), "b", "Should have the right property name for 'b'."); is(argEnums[1].querySelector(".value").getAttribute("value"), "\"beta\"", "Should have the right property value for 'b'."); ok(argEnums[1].querySelector(".value").className.includes("token-string"), "Should have the right token class for 'b'."); is(argEnums[2].querySelector(".name").getAttribute("value"), "c", "Should have the right property name for 'c'."); is(argEnums[2].querySelector(".value").getAttribute("value"), "3", "Should have the right property value for 'c'."); ok(argEnums[2].querySelector(".value").className.includes("token-number"), "Should have the right token class for 'c'."); is(argEnums[3].querySelector(".name").getAttribute("value"), "d", "Should have the right property name for 'd'."); is(argEnums[3].querySelector(".value").getAttribute("value"), "false", "Should have the right property value for 'd'."); ok(argEnums[3].querySelector(".value").className.includes("token-boolean"), "Should have the right token class for 'd'."); is(argEnums[4].querySelector(".name").getAttribute("value"), "e", "Should have the right property name for 'e'."); is(argEnums[4].querySelector(".value").getAttribute("value"), "null", "Should have the right property value for 'e'."); ok(argEnums[4].querySelector(".value").className.includes("token-null"), "Should have the right token class for 'e'."); is(argEnums[5].querySelector(".name").getAttribute("value"), "f", "Should have the right property name for 'f'."); is(argEnums[5].querySelector(".value").getAttribute("value"), "undefined", "Should have the right property value for 'f'."); ok(argEnums[5].querySelector(".value").className.includes("token-undefined"), "Should have the right token class for 'f'."); is(argNonEnums[0].querySelector(".name").getAttribute("value"), "__proto__", "Should have the right property name for '__proto__'."); is(argNonEnums[0].querySelector(".value").getAttribute("value"), "Object", "Should have the right property value for '__proto__'."); ok(argNonEnums[0].querySelector(".value").className.includes("token-other"), "Should have the right token class for '__proto__'."); deferred.resolve(); }); argVar.expand(); return deferred.promise; } function testInnerArgumentObject() { let deferred = promise.defer(); let argProp = gVariables.getScopeAtIndex(0).get("arguments").get("0"); is(argProp.expanded, false, "The 'arguments[0]' property should not be expanded by default."); let argEnums = argProp.target.querySelector(".variables-view-element-details.enum").childNodes; let argNonEnums = argProp.target.querySelector(".variables-view-element-details.nonenum").childNodes; gDebugger.once(gDebugger.EVENTS.FETCHED_PROPERTIES, () => { is(argEnums.length, 6, "The 'arguments[0]' property should contain all the created enumerable elements."); is(argNonEnums.length, 1, "The 'arguments[0]' property should contain all the created non-enumerable elements."); is(argEnums[0].querySelector(".name").getAttribute("value"), "a", "Should have the right property name for 'a'."); is(argEnums[0].querySelector(".value").getAttribute("value"), "1", "Should have the right property value for 'a'."); ok(argEnums[0].querySelector(".value").className.includes("token-number"), "Should have the right token class for 'a'."); is(argEnums[1].querySelector(".name").getAttribute("value"), "b", "Should have the right property name for 'b'."); is(argEnums[1].querySelector(".value").getAttribute("value"), "\"beta\"", "Should have the right property value for 'b'."); ok(argEnums[1].querySelector(".value").className.includes("token-string"), "Should have the right token class for 'b'."); is(argEnums[2].querySelector(".name").getAttribute("value"), "c", "Should have the right property name for 'c'."); is(argEnums[2].querySelector(".value").getAttribute("value"), "3", "Should have the right property value for 'c'."); ok(argEnums[2].querySelector(".value").className.includes("token-number"), "Should have the right token class for 'c'."); is(argEnums[3].querySelector(".name").getAttribute("value"), "d", "Should have the right property name for 'd'."); is(argEnums[3].querySelector(".value").getAttribute("value"), "false", "Should have the right property value for 'd'."); ok(argEnums[3].querySelector(".value").className.includes("token-boolean"), "Should have the right token class for 'd'."); is(argEnums[4].querySelector(".name").getAttribute("value"), "e", "Should have the right property name for 'e'."); is(argEnums[4].querySelector(".value").getAttribute("value"), "null", "Should have the right property value for 'e'."); ok(argEnums[4].querySelector(".value").className.includes("token-null"), "Should have the right token class for 'e'."); is(argEnums[5].querySelector(".name").getAttribute("value"), "f", "Should have the right property name for 'f'."); is(argEnums[5].querySelector(".value").getAttribute("value"), "undefined", "Should have the right property value for 'f'."); ok(argEnums[5].querySelector(".value").className.includes("token-undefined"), "Should have the right token class for 'f'."); is(argNonEnums[0].querySelector(".name").getAttribute("value"), "__proto__", "Should have the right property name for '__proto__'."); is(argNonEnums[0].querySelector(".value").getAttribute("value"), "Object", "Should have the right property value for '__proto__'."); ok(argNonEnums[0].querySelector(".value").className.includes("token-other"), "Should have the right token class for '__proto__'."); deferred.resolve(); }); argProp.expand(); return deferred.promise; } function testGetterSetterObject() { let deferred = promise.defer(); let myVar = gVariables.getScopeAtIndex(0).get("myVar"); is(myVar.expanded, false, "The myVar variable should not be expanded by default."); let myVarEnums = myVar.target.querySelector(".variables-view-element-details.enum").childNodes; let myVarNonEnums = myVar.target.querySelector(".variables-view-element-details.nonenum").childNodes; gDebugger.once(gDebugger.EVENTS.FETCHED_PROPERTIES, () => { is(myVarEnums.length, 2, "The myVar should contain all the created enumerable elements."); is(myVarNonEnums.length, 1, "The myVar should contain all the created non-enumerable elements."); is(myVarEnums[0].querySelector(".name").getAttribute("value"), "_prop", "Should have the right property name for '_prop'."); is(myVarEnums[0].querySelector(".value").getAttribute("value"), "42", "Should have the right property value for '_prop'."); ok(myVarEnums[0].querySelector(".value").className.includes("token-number"), "Should have the right token class for '_prop'."); is(myVarEnums[1].querySelector(".name").getAttribute("value"), "prop", "Should have the right property name for 'prop'."); is(myVarEnums[1].querySelector(".value").getAttribute("value"), "", "Should have the right property value for 'prop'."); ok(!myVarEnums[1].querySelector(".value").className.includes("token"), "Should have no token class for 'prop'."); is(myVarNonEnums[0].querySelector(".name").getAttribute("value"), "__proto__", "Should have the right property name for '__proto__'."); is(myVarNonEnums[0].querySelector(".value").getAttribute("value"), "Object", "Should have the right property value for '__proto__'."); ok(myVarNonEnums[0].querySelector(".value").className.includes("token-other"), "Should have the right token class for '__proto__'."); let propEnums = myVarEnums[1].querySelector(".variables-view-element-details.enum").childNodes; let propNonEnums = myVarEnums[1].querySelector(".variables-view-element-details.nonenum").childNodes; is(propEnums.length, 0, "The propEnums should contain all the created enumerable elements."); is(propNonEnums.length, 2, "The propEnums should contain all the created non-enumerable elements."); is(propNonEnums[0].querySelector(".name").getAttribute("value"), "get", "Should have the right property name for 'get'."); is(propNonEnums[0].querySelector(".value").getAttribute("value"), "get prop()", "Should have the right property value for 'get'."); ok(propNonEnums[0].querySelector(".value").className.includes("token-other"), "Should have the right token class for 'get'."); is(propNonEnums[1].querySelector(".name").getAttribute("value"), "set", "Should have the right property name for 'set'."); is(propNonEnums[1].querySelector(".value").getAttribute("value"), "set prop(val)", "Should have the right property value for 'set'."); ok(propNonEnums[1].querySelector(".value").className.includes("token-other"), "Should have the right token class for 'set'."); deferred.resolve(); }); myVar.expand(); return deferred.promise; } registerCleanupFunction(function () { gTab = null; gPanel = null; gDebugger = null; gVariables = null; });