Merge m-c to inbound.

This commit is contained in:
Ryan VanderMeulen 2012-10-10 06:32:24 -04:00
commit a95cdcdd1d
26 changed files with 654 additions and 58 deletions

View File

@ -100,6 +100,7 @@ let FormAssistant = {
if (this.focusedElement) {
sendAsyncMessage("Forms:Input", { "type": "blur" });
this.setFocusedElement(null);
this.isKeyboardOpened = false;
}
break;

View File

@ -1035,6 +1035,7 @@ pref("devtools.debugger.ui.stackframes-width", 200);
pref("devtools.debugger.ui.stackframes-pane-visible", true);
pref("devtools.debugger.ui.variables-width", 300);
pref("devtools.debugger.ui.variables-pane-visible", true);
pref("devtools.debugger.ui.non-enum-visible", true);
// Enable the style inspector
pref("devtools.styleinspector.enabled", true);

View File

@ -1463,7 +1463,18 @@ Breakpoints.prototype = {
let line = aBreakpoint.line + 1;
this.addBreakpoint({ url: url, line: line }, null, true);
this.addBreakpoint({ url: url, line: line }, function (aBp) {
if (aBp.requestedLocation) {
this.editor.removeBreakpoint(aBp.requestedLocation.line - 1);
let breakpoints = this.getBreakpoints(url, aBp.location.line);
if (breakpoints.length > 1) {
this.removeBreakpoint(breakpoints[0], null, true, true);
} else {
this.updateEditorBreakpoints();
}
}
}.bind(this), true);
},
/**
@ -1555,6 +1566,18 @@ Breakpoints.prototype = {
}
this.activeThread.setBreakpoint(aLocation, function(aResponse, aBpClient) {
let loc = aResponse.actualLocation;
if (loc) {
aBpClient.requestedLocation = {
line: aBpClient.location.line,
url: aBpClient.location.url
};
aBpClient.location.line = loc.line;
aBpClient.location.url = loc.url;
}
this.store[aBpClient.actor] = aBpClient;
this.displayBreakpoint(aBpClient, aNoEditorUpdate, aNoPaneUpdate);
aCallback && aCallback(aBpClient, aResponse.error);
@ -1655,6 +1678,18 @@ Breakpoints.prototype = {
}
}
return null;
},
getBreakpoints: function BP_getBreakpoints(aUrl, aLine) {
let breakpoints = [];
for each (let breakpoint in this.store) {
if (breakpoint.location.url == aUrl && breakpoint.location.line == aLine) {
breakpoints.push(breakpoint);
}
}
return breakpoints;
}
};
@ -1698,6 +1733,7 @@ const REMOTE_HOST = "devtools.debugger.remote-host";
const REMOTE_PORT = "devtools.debugger.remote-port";
const REMOTE_CONNECTION_RETRIES = "devtools.debugger.remote-connection-retries";
const REMOTE_TIMEOUT = "devtools.debugger.remote-timeout";
const NON_ENUM_VISIBLE = "devtools.debugger.ui.non-enum-visible";
/**
* Shortcuts for accessing various debugger preferences.
@ -1785,7 +1821,7 @@ let Prefs = {
},
/**
* Gets a flag specifying if the the debugger should automatically connect to
* Gets a flag specifying if the debugger should automatically connect to
* the default host and port number.
* @return boolean
*/
@ -1797,13 +1833,35 @@ let Prefs = {
},
/**
* Sets a flag specifying if the the debugger should automatically connect to
* Sets a flag specifying if the debugger should automatically connect to
* the default host and port number.
* @param boolean value
*/
set remoteAutoConnect(value) {
Services.prefs.setBoolPref(REMOTE_AUTO_CONNECT, value);
this._autoConnect = value;
},
/**
* Gets a flag specifying if the debugger should show non-enumerable
* properties and variables in the scope view.
* @return boolean
*/
get nonEnumVisible() {
if (this._nonEnumVisible === undefined) {
this._nonEnumVisible = Services.prefs.getBoolPref(NON_ENUM_VISIBLE);
}
return this._nonEnumVisible;
},
/**
* Sets a flag specifying if the debugger should show non-enumerable
* properties and variables in the scope view.
* @param boolean value
*/
set nonEnumVisible(value) {
Services.prefs.setBoolPref(NON_ENUM_VISIBLE, value);
this._nonEnumVisible = value;
}
};

View File

@ -2107,7 +2107,7 @@ BreakpointsView.prototype = {
enableBreakpoint:
function DVB_enableBreakpoint(aTarget, aCallback, aNoCheckboxUpdate) {
let { breakpointUrl: url, breakpointLine: line } = aTarget;
let breakpoint = DebuggerController.Breakpoints.getBreakpoint(url, line)
let breakpoint = DebuggerController.Breakpoints.getBreakpoint(url, line);
if (!breakpoint) {
if (!aNoCheckboxUpdate) {
@ -2585,9 +2585,16 @@ PropertiesView.prototype = {
// Compute the id of the element if not specified.
aId = aId || (aScope.id + "->" + aName + "-variable");
let parent;
if (aFlags && !aFlags.enumerable) {
parent = aScope.childNodes[2];
}
else {
parent = aScope.childNodes[1];
}
// Contains generic nodes and functionality.
let element = this._createPropertyElement(aName, aId, "variable",
aScope.getElementsByClassName("details")[0]);
let element = this._createPropertyElement(aName, aId, "variable", parent);
// Make sure the element was created successfully.
if (!element) {
@ -2789,6 +2796,7 @@ PropertiesView.prototype = {
if (value !== undefined) {
this._addProperty(aVar, [i, value], desc);
}
if (getter !== undefined || setter !== undefined) {
let prop = this._addProperty(aVar, [i]).expand();
prop.getter = this._addProperty(prop, ["get", getter], desc);
@ -2834,9 +2842,16 @@ PropertiesView.prototype = {
// Compute the id of the element if not specified.
aId = aId || (aVar.id + "->" + aProperty[0] + "-property");
let parent;
if (aFlags && !aFlags.enumerable) {
parent = aVar.childNodes[2];
}
else {
parent = aVar.childNodes[1];
}
// Contains generic nodes and functionality.
let element = this._createPropertyElement(aName, aId, "property",
aVar.getElementsByClassName("details")[0]);
let element = this._createPropertyElement(aName, aId, "property", parent);
// Make sure the element was created successfully.
if (!element) {
@ -3112,6 +3127,7 @@ PropertiesView.prototype = {
let title = document.createElement("box");
let details = document.createElement("vbox");
let nonEnum = document.createElement("vbox");
// Create a scope node to contain all the elements.
element.id = aId;
@ -3131,6 +3147,7 @@ PropertiesView.prototype = {
// The node element which will contain any added scope variables.
details.className = "details";
nonEnum.className = "details nonenum";
// Add the click event handler for the title, or arrow and name.
if (aClass === "scope") {
@ -3146,6 +3163,7 @@ PropertiesView.prototype = {
element.appendChild(title);
element.appendChild(details);
element.appendChild(nonEnum);
aParent.appendChild(element);
@ -3192,12 +3210,19 @@ PropertiesView.prototype = {
arrow.setAttribute("open", "");
details.setAttribute("open", "");
if (Prefs.nonEnumVisible) {
nonEnum.setAttribute("open", "");
}
if (!aSkipAnimationFlag) {
details.setAttribute("animated", "");
nonEnum.setAttribute("animated", "");
}
if ("function" === typeof element.onexpand) {
element.onexpand(element);
}
return element;
};
@ -3210,9 +3235,12 @@ PropertiesView.prototype = {
if (element._preventCollapse) {
return;
}
arrow.removeAttribute("open");
details.removeAttribute("open");
details.removeAttribute("animated");
nonEnum.removeAttribute("open");
nonEnum.removeAttribute("animated");
if ("function" === typeof element.oncollapse) {
element.oncollapse(element);
@ -3240,9 +3268,12 @@ PropertiesView.prototype = {
* The same element.
*/
element.showArrow = function DVP_element_showArrow() {
if (element._forceShowArrow || details.childNodes.length) {
let len = details.childNodes.length + nonEnum.childNodes.length;
if (element._forceShowArrow || len) {
arrow.style.visibility = "visible";
}
return element;
};
@ -3327,13 +3358,19 @@ PropertiesView.prototype = {
element.empty = function DVP_element_empty() {
// This details node won't have any elements, so hide the arrow.
arrow.style.visibility = "hidden";
while (details.firstChild) {
details.removeChild(details.firstChild);
}
while (nonEnum.firstChild) {
nonEnum.removeChild(nonEnum.firstChild);
}
if ("function" === typeof element.onempty) {
element.onempty(element);
}
return element;
};
@ -3431,7 +3468,7 @@ PropertiesView.prototype = {
let node = aParent.parentNode;
let arrow = node.getElementsByClassName("arrow")[0];
let children = node.getElementsByClassName("details")[0].childNodes.length;
let children = node.querySelectorAll(".details > vbox").length;
// If the parent details node has at least one element, set the
// expand/collapse arrow visible.
@ -3549,10 +3586,31 @@ PropertiesView.prototype = {
*/
_vars: null,
_onShowNonEnums: function DVP__onShowNonEnums() {
let option = document.getElementById("show-nonenum");
Prefs.nonEnumVisible = option.checked;
let els = document.getElementsByClassName("nonenum").iterator();
for (let el of els) {
if (el.parentNode.expanded) {
if (Prefs.nonEnumVisible) {
el.setAttribute("open", "");
} else {
el.removeAttribute("open");
el.removeAttribute("animated");
}
}
}
},
/**
* Initialization function, called when the debugger is initialized.
*/
initialize: function DVP_initialize() {
let showNonEnums = document.getElementById("show-nonenum");
showNonEnums.addEventListener("click", this._onShowNonEnums, false);
showNonEnums.checked = Prefs.nonEnumVisible;
this._vars = DebuggerView._variables;
this.emptyText();

View File

@ -90,6 +90,10 @@
type="checkbox"
tabindex="0"
label="&debuggerUI.pauseExceptions;"/>
<checkbox id="show-nonenum"
type="checkbox"
tabindex="0"
label="&debuggerUI.showNonEnums;"/>
<spacer flex="1"/>
#ifndef XP_MACOSX
<toolbarbutton id="close"

View File

@ -63,6 +63,7 @@ MOCHITEST_BROWSER_TESTS = \
browser_dbg_bug723069_editor-breakpoints.js \
browser_dbg_bug723071_editor-breakpoints-pane.js \
browser_dbg_bug731394_editor-contextmenu.js \
browser_dbg_bug786070_hide_nonenums.js \
browser_dbg_displayName.js \
browser_dbg_iframes.js \
browser_dbg_pause-exceptions.js \
@ -70,6 +71,7 @@ MOCHITEST_BROWSER_TESTS = \
browser_dbg_menustatus.js \
browser_dbg_bfcache.js \
browser_dbg_breakpoint-new-script.js \
browser_dbg_bug737803_editor_actual_location.js \
head.js \
$(NULL)

View File

@ -160,17 +160,17 @@ function test()
executeSoon(function()
{
line = 4;
line = 6;
gPane.addBreakpoint({url: gScripts.selected, line: line},
function(cl, err) {
onBreakpointAdd.call({ increment: increment, line: line }, cl, err);
line = 5;
line = 7;
gPane.addBreakpoint({url: gScripts.selected, line: line},
function(cl, err) {
onBreakpointAdd.call({ increment: increment, line: line }, cl, err);
line = 6;
line = 8;
gPane.addBreakpoint({url: gScripts.selected, line: line},
function(cl, err) {
onBreakpointAdd.call({ increment: increment, line: line }, cl, err);

View File

@ -0,0 +1,109 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Bug 737803: Setting a breakpoint in a line without code should move
* the icon to the actual location.
*/
const TAB_URL = EXAMPLE_URL + "browser_dbg_script-switching.html";
let gPane = null;
let gTab = null;
let gDebuggee = null;
let gDebugger = null;
let gScripts = null;
let gEditor = null;
let gBreakpoints = null;
function test() {
let tempScope = {};
Cu.import("resource:///modules/source-editor.jsm", tempScope);
let SourceEditor = tempScope.SourceEditor;
let scriptShown = false;
let framesAdded = false;
let testStarted = false;
let resumed = false;
debug_tab_pane(TAB_URL, function (aTab, aDebuggee, aPane) {
gTab = aTab;
gPane = aPane;
gDebuggee = aDebuggee;
gDebugger = gPane.contentWindow;
resumed = true;
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function () {
framesAdded = true;
executeSoon(startTest);
});
executeSoon(function () {
gDebuggee.firstCall();
});
});
function onScriptShown(aEvent) {
scriptShown = aEvent.detail.url.indexOf("-02.js") != -1;
executeSoon(startTest);
}
window.addEventListener("Debugger:ScriptShown", onScriptShown);
function startTest() {
if (scriptShown && framesAdded && resumed && !testStarted) {
window.removeEventListener("Debugger:ScriptShown", onScriptShown);
testStarted = true;
Services.tm.currentThread.dispatch({ run: performTest }, 0);
}
}
function performTest() {
gScripts = gDebugger.DebuggerView.Scripts;
gEditor = gDebugger.editor;
gBreakpoints = gPane.breakpoints;
is(Object.keys(gBreakpoints), 0, "There are no breakpoints");
gEditor.addEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE,
onEditorBreakpointAdd);
let location = { url: gScripts.selected, line: 4 };
executeSoon(function () {
gPane.addBreakpoint(location, onBreakpointAdd);
});
}
function onBreakpointAdd(aBpClient) {
is(aBpClient.location.url, gScripts.selected, "URL is the same");
is(aBpClient.location.line, 6, "Line number is new");
is(aBpClient.requestedLocation.line, 4, "Requested location is correct");
}
function onEditorBreakpointAdd(aEvent) {
gEditor.removeEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE,
onEditorBreakpointAdd);
is(gEditor.getBreakpoints().length, 1,
"There is only one breakpoint in the editor");
ok(!gPane.getBreakpoint(gScripts.selected, 4),
"There are no breakpoints on an invalid line");
let br = gPane.getBreakpoint(gScripts.selected, 6);
is(br.location.url, gScripts.selected, "URL is correct");
is(br.location.line, 6, "Line number is correct");
closeDebuggerAndFinish();
}
registerCleanupFunction(function () {
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gDebugger = null;
gScripts = null;
gEditor = null;
gBreakpoints = null;
});
}

View File

@ -0,0 +1,107 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
var gPane = null;
var gTab = null;
var gDebuggee = null;
var gDebugger = null;
function test() {
debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
testNonEnumProperties();
});
}
function testNonEnumProperties() {
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
Services.tm.currentThread.dispatch({ run: function() {
let testScope = gDebugger.DebuggerView.Properties._addScope("test-scope");
let testVar = testScope.addVar("foo");
testVar.addProperties({
foo: {
value: "bar",
enumerable: true
},
bar: {
value: "foo",
enumerable: false
}
});
testVar.expand();
let details = testVar.childNodes[1];
let nonenum = testVar.childNodes[2];
is(details.childNodes.length, 1,
"There should be just one property in the .details container.");
ok(details.hasAttribute("open"),
".details container should be visible.");
is(nonenum.childNodes.length, 1,
"There should be just one property in the .nonenum container.");
ok(nonenum.hasAttribute("open"),
".nonenum container should be visible.");
let option = gDebugger.document.getElementById("show-nonenum");
// Uncheck 'show hidden properties'.
EventUtils.sendMouseEvent({ type: "click" }, option, gDebugger);
ok(details.hasAttribute("open"),
".details container should stay visible.");
ok(!nonenum.hasAttribute("open"),
".nonenum container should become hidden.");
// Check 'show hidden properties'.
EventUtils.sendMouseEvent({ type: "click" }, option, gDebugger);
ok(details.hasAttribute("open"),
".details container should stay visible.");
ok(nonenum.hasAttribute("open"),
".nonenum container should become visible.");
testVar.collapse();
ok(!details.hasAttribute("open"),
".details container should be hidden.");
ok(!nonenum.hasAttribute("open"),
".nonenum container should be hidden.");
EventUtils.sendMouseEvent({ type: "click" }, option, gDebugger);
ok(!details.hasAttribute("open"),
".details container should stay hidden.");
ok(!nonenum.hasAttribute("open"),
".nonenum container should stay hidden.");
gDebugger.DebuggerController.activeThread.resume(function() {
closeDebuggerAndFinish();
});
}}, 0);
});
gDebuggee.simpleCall();
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gDebugger = null;
});

View File

@ -26,8 +26,16 @@ function testSimpleCall() {
let testScope = gDebugger.DebuggerView.Properties._addScope("test");
let testVar = testScope.addVar("something");
let properties = testVar.addProperties({ "child": { "value": { "type": "object",
"class": "Object" } } });
let properties = testVar.addProperties({
"child": {
"value": {
"type": "object",
"class": "Object"
},
"enumerable": true
}
});
is(testVar.querySelector(".details").childNodes.length, 1,
"A new detail node should have been added in the variable tree.");
@ -39,8 +47,16 @@ function testSimpleCall() {
"Adding a detail property should return that exact property.");
let properties2 = testVar.child.addProperties({ "grandchild": { "value": { "type": "object",
"class": "Object" } } });
let properties2 = testVar.child.addProperties({
"grandchild": {
"value": {
"type": "object",
"class": "Object"
},
"enumerable": true
}
});
is(testVar.child.querySelector(".details").childNodes.length, 1,
"A new detail node should have been added in the variable tree.");

View File

@ -44,28 +44,32 @@ function testSimpleCall() {
"The information for the variable wasn't set correctly.");
testVar.addProperties({ "helloWorld": { "value": "hello world" } });
testVar.addProperties({ "helloWorld": { "value": "hello world", "enumerable": true } });
is(testVar.querySelector(".details").childNodes.length, 1,
"A new detail node should have been added in the variable tree.");
testVar.addProperties({ "helloWorld": { "value": "hello jupiter" } });
testVar.addProperties({ "helloWorld": { "value": "hello jupiter", "enumerable": true } });
is(testVar.querySelector(".details").childNodes.length, 1,
"Shouldn't be able to duplicate nodes added in the variable tree.");
testVar.addProperties({ "someProp0": { "value": "random string" },
"someProp1": { "value": "another string" } });
testVar.addProperties({ "someProp0": { "value": "random string", "enumerable": true },
"someProp1": { "value": "another string", "enumerable": true } });
is(testVar.querySelector(".details").childNodes.length, 3,
"Two new detail nodes should have been added in the variable tree.");
testVar.addProperties({ "someProp2": { "value": { "type": "null" } },
"someProp3": { "value": { "type": "undefined" } },
"someProp4": { "value": { "type": "object", "class": "Object" } } });
testVar.addProperties({ "someProp2": { "value": { "type": "null" }, "enumerable": true },
"someProp3": { "value": { "type": "undefined" }, "enumerable": true },
"someProp4": {
"value": { "type": "object", "class": "Object" },
"enumerable": true
}
});
is(testVar.querySelector(".details").childNodes.length, 6,
"Three new detail nodes should have been added in the variable tree.");

View File

@ -45,20 +45,25 @@ function testSimpleCall() {
localVar4.setGrip({ "type": "null" });
localVar5.setGrip({ "type": "object", "class": "Object" });
localVar5.addProperties({ "someProp0": { "value": 42 },
"someProp1": { "value": true },
"someProp2": { "value": "nasu" },
"someProp3": { "value": { "type": "undefined" } },
"someProp4": { "value": { "type": "null" } },
"someProp5": { "value": { "type": "object", "class": "Object" } } });
localVar5.addProperties({ "someProp0": { "value": 42, "enumerable": true },
"someProp1": { "value": true , "enumerable": true},
"someProp2": { "value": "nasu", "enumerable": true},
"someProp3": { "value": { "type": "undefined" }, "enumerable": true},
"someProp4": { "value": { "type": "null" }, "enumerable": true },
"someProp5": {
"value": { "type": "object", "class": "Object" },
"enumerable": true
}
});
localVar5.someProp5.addProperties({ "someProp0": { "value": 42 },
"someProp1": { "value": true },
"someProp2": { "value": "nasu" },
"someProp3": { "value": { "type": "undefined" } },
"someProp4": { "value": { "type": "null" } },
localVar5.someProp5.addProperties({ "someProp0": { "value": 42, "enumerable": true },
"someProp1": { "value": true, "enumerable": true },
"someProp2": { "value": "nasu", "enumerable": true },
"someProp3": { "value": { "type": "undefined" }, "enumerable": true },
"someProp4": { "value": { "type": "null" }, "enumerable": true },
"someAccessor": { "get": { "type": "object", "class": "Function" },
"set": { "type": "undefined" } } });
"set": { "type": "undefined" },
"enumerable": true } });
windowVar.setGrip({ "type": "object", "class": "Window" });
windowVar.addProperties({ "helloWorld": { "value": "hello world" } });

View File

@ -37,12 +37,14 @@ function testFrameParameters()
var frames = gDebugger.DebuggerView.StackFrames._frames,
localScope = gDebugger.DebuggerView.Properties._vars.firstChild,
localNodes = localScope.querySelector(".details").childNodes;
localNodes = localScope.childNodes[1].childNodes,
localNonEnums = localScope.childNodes[2].childNodes; // .nonenums
dump("Got our variables:\n");
dump("frames - " + frames.constructor + "\n");
dump("localScope - " + localScope.constructor + "\n");
dump("localNodes - " + localNodes.constructor + "\n");
dump("localNonEnums - " + localNonEnums.constructor + "\n");
is(gDebugger.DebuggerController.activeThread.state, "paused",
"Should only be getting stack frames while paused.");
@ -50,8 +52,8 @@ function testFrameParameters()
is(frames.querySelectorAll(".dbg-stackframe").length, 3,
"Should have three frames.");
is(localNodes.length, 11,
"The localScope should contain all the created variable elements.");
is(localNodes.length + localNonEnums.length, 11,
"The localScope and localNonEnums should contain all the created variable elements.");
is(localNodes[0].querySelector(".value").getAttribute("value"), "[object Proxy]",
"Should have the right property value for 'this'.");
@ -79,8 +81,8 @@ function testFrameParameters()
}
window.clearInterval(intervalID);
is(localNodes[0].querySelector(".property > .title > .key")
.getAttribute("value"), "Array",
"Should have the right property name for Array.");
.getAttribute("value"), "InstallTrigger",
"Should have the right property name for InstallTrigger.");
ok(localNodes[0].querySelector(".property > .title > .value")
.getAttribute("value").search(/object/) != -1,
"Array should be an object.");

View File

@ -38,7 +38,7 @@ function testFrameParameters()
var frames = gDebugger.DebuggerView.StackFrames._frames,
globalScope = gDebugger.DebuggerView.Properties._vars.lastChild,
globalNodes = globalScope.querySelector(".details").childNodes;
globalNodes = globalScope.childNodes[2].childNodes;
globalScope.expand();
@ -55,11 +55,11 @@ function testFrameParameters()
"Should have the right property value for |Array|.");
let len = globalNodes.length - 1;
is(globalNodes[len].querySelector(".name").getAttribute("value"), "window",
"Should have the right property name for |window|.");
is(globalNodes[len].querySelector(".name").getAttribute("value"), "uneval",
"Should have the right property name for |uneval|.");
is(globalNodes[len].querySelector(".value").getAttribute("value"), "[object Proxy]",
"Should have the right property value for |window|.");
is(globalNodes[len].querySelector(".value").getAttribute("value"), "[object Function]",
"Should have the right property value for |uneval|.");
resumeAndFinish();
}}, 0);

View File

@ -59,11 +59,11 @@ function testWithFrame()
is(innerNodes[1].querySelector(".value").getAttribute("value"), "1",
"Should have the right property value for |one|.");
is(globalNodes[0].querySelector(".name").getAttribute("value"), "Array",
is(globalNodes[0].querySelector(".name").getAttribute("value"), "InstallTrigger",
"Should have the right property name for |Array|.");
is(globalNodes[0].querySelector(".value").getAttribute("value"), "[object Function]",
"Should have the right property value for |Array|.");
is(globalNodes[0].querySelector(".value").getAttribute("value"), "undefined",
"Should have the right property value for |InstallTrigger|.");
let len = globalNodes.length - 1;
is(globalNodes[len].querySelector(".name").getAttribute("value"), "window",

View File

@ -4,4 +4,8 @@
function secondCall() {
// This comment is useful for browser_dbg_select-line.js. ☺
eval("debugger;");
function foo() {}
if (true) {
foo();
}
}

View File

@ -350,10 +350,12 @@ StyleEditorChrome.prototype = {
if (!aEditor.sourceEditor) {
// If a line or column was specified we move the caret appropriately.
if (setCaret) {
let self = this;
aEditor.addActionListener({
onAttach: function SEC_selectSheet_onAttach()
{
aEditor.removeActionListener(this);
self.selectedStyleSheetIndex = aEditor.styleSheetIndex;
aEditor.sourceEditor.setCaretPosition(aLine - 1, aCol - 1);
}
});
@ -367,6 +369,7 @@ StyleEditorChrome.prototype = {
aEditor.sourceEditor.setCaretPosition(aLine - 1, aCol - 1);
}
}
this.selectedStyleSheetIndex = aEditor.styleSheetIndex;
}.bind(this);
if (!this.editors.length) {

View File

@ -900,6 +900,53 @@ WebConsole.prototype = {
this.chromeWindow.openUILinkIn(aLink, "tab");
},
/**
* Open a link in Firefox's view source.
*
* @param string aSourceURL
* The URL of the file.
* @param integer aSourceLine
* The line number which should be highlighted.
*/
viewSource: function WC_viewSource(aSourceURL, aSourceLine)
{
this.gViewSourceUtils.viewSource(aSourceURL, null,
this.iframeWindow.document, aSourceLine);
},
/**
* Tries to open a Stylesheet file related to the web page for the web console
* instance in the Style Editor. If the file is not found, it is opened in
* source view instead.
*
* @param string aSourceURL
* The URL of the file.
* @param integer aSourceLine
* The line number which you want to place the caret.
* TODO: This function breaks the client-server boundaries.
* To be fixed in bug 793259.
*/
viewSourceInStyleEditor:
function WC_viewSourceInStyleEditor(aSourceURL, aSourceLine)
{
let styleSheets = this.tab.linkedBrowser.contentWindow.document.styleSheets;
for each (let style in styleSheets) {
if (style.href == aSourceURL) {
let SEM = this.chromeWindow.StyleEditor.StyleEditorManager;
let win = SEM.getEditorForWindow(this.chromeWindow.content.window);
if (win) {
SEM.selectEditor(win, style, aSourceLine);
}
else {
this.chromeWindow.StyleEditor.openChrome(style, aSourceLine);
}
return;
}
}
// Open view source if style editor fails.
this.viewSource(aSourceURL, aSourceLine);
},
/**
* Destroy the object. Call this method to avoid memory leaks when the Web
* Console is closed.

View File

@ -109,6 +109,7 @@ MOCHITEST_BROWSER_FILES = \
browser_webconsole_bug_622303_persistent_filters.js \
browser_webconsole_bug_770099_bad_policyuri.js \
browser_webconsole_bug_770099_violation.js \
browser_webconsole_bug_782653_CSS_links_in_Style_Editor.js \
browser_webconsole_window_zombie.js \
browser_cached_messages.js \
browser_bug664688_sandbox_update_after_navigation.js \
@ -186,6 +187,9 @@ MOCHITEST_BROWSER_FILES += \
test-bug-644419-log-limits.html \
test-bug-632275-getters.html \
test-bug-646025-console-file-location.html \
test-bug-782653-css-errors.html \
test-bug-782653-css-errors-1.css \
test-bug-782653-css-errors-2.css \
test-file-location.js \
test-bug-658368-time-methods.html \
test-webconsole-error-observer.html \

View File

@ -0,0 +1,133 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* ***** BEGIN LICENSE BLOCK *****
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
* ***** END LICENSE BLOCK ***** */
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test" +
"/test-bug-782653-css-errors.html";
let nodes;
let styleEditorWin;
function test() {
addTab(TEST_URI);
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
openConsole(null, testViewSource);
}, true);
}
function testViewSource(hud) {
waitForSuccess({
name: "find the location node",
validatorFn: function()
{
return hud.outputNode.querySelector(".webconsole-location");
},
successFn: function()
{
nodes = hud.outputNode.querySelectorAll(".webconsole-location");
Services.ww.registerNotification(observer);
EventUtils.sendMouseEvent({ type: "click" }, nodes[0]);
},
failureFn: finishTest,
});
}
function checkStyleEditorForSheetAndLine(aStyleSheetIndex, aLine, aCallback) {
function doCheck(aEditor) {
if (aEditor.styleSheetIndex != aStyleSheetIndex) {
ok(false, "Correct Style Sheet was not selected.");
if (aCallback) {
executeSoon(aCallback);
}
return;
}
ok(true, "Correct Style Sheet is selected in the editor");
// Editor is already loaded, check the current line of caret.
if (aEditor.sourceEditor) {
executeSoon(function() {
is(aEditor.sourceEditor.getCaretPosition().line, aLine,
"Correct line is selected");
if (aCallback) {
aCallback();
}
});
return;
}
// Wait for source editor to be loaded.
aEditor.addActionListener({
onAttach: function onAttach() {
aEditor.removeActionListener(this);
executeSoon(function() {
is(aEditor.sourceEditor.getCaretPosition().line, aLine,
"Correct line is selected");
if (aCallback) {
aCallback();
}
});
}
});
}
let SEC = styleEditorWin.styleEditorChrome;
ok(SEC, "Syle Editor Chrome is defined properly while calling for [" +
aStyleSheetIndex + ", " + aLine + "]");
// Editors are not ready, so wait for them.
if (!SEC.editors.length) {
SEC.addChromeListener({
onEditorAdded: function onEditorAdded(aChrome, aEditor) {
aChrome.removeChromeListener(this);
doCheck(aEditor);
}
});
}
// Execute soon so that selectedStyleSheetIndex has correct value.
else {
executeSoon(function() {
let aEditor = SEC.editors[SEC.selectedStyleSheetIndex];
doCheck(aEditor);
});
}
}
let observer = {
observe: function(aSubject, aTopic, aData) {
if (aTopic != "domwindowopened") {
return;
}
Services.ww.unregisterNotification(observer);
ok(true, "Style Editor window was opened in response to clicking " +
"the location node");
executeSoon(function() {
styleEditorWin = window.StyleEditor
.StyleEditorManager
.getEditorForWindow(content.window);
ok(styleEditorWin, "Style Editor Window is defined");
styleEditorWin.addEventListener("load", function onStyleEditorWinLoad() {
styleEditorWin.removeEventListener("load", onStyleEditorWinLoad);
checkStyleEditorForSheetAndLine(0, 7, function() {
checkStyleEditorForSheetAndLine(1, 6, function() {
window.StyleEditor.toggle();
styleEditorWin = null;
finishTest();
});
EventUtils.sendMouseEvent({ type: "click" }, nodes[1]);
});
});
});
}
};

View File

@ -0,0 +1,10 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
body {
color: #0f0;
font-weight: green;
}

View File

@ -0,0 +1,10 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
body {
color: #0fl;
font-weight: bold;
}

View File

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Web Console test for bug 782653 : Open CSS Links in Style Editor</title>
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<link rel="stylesheet" href="test-bug-782653-css-errors-1.css">
<link rel="stylesheet" href="test-bug-782653-css-errors-2.css">
</head>
<body>
<p>Web Console test for bug 782653 : Open CSS Links in Style Editor.</p>
</body>
</html>

View File

@ -1398,8 +1398,7 @@ WebConsoleFrame.prototype = {
urlNode, null, null, aFileURI);
this.makeOutputMessageLink(outputNode, function WCF__onFileClick() {
let viewSourceUtils = this.owner.gViewSourceUtils;
viewSourceUtils.viewSource(aFileURI, null, this.document);
this.owner.viewSource(aFileURI);
}.bind(this));
return outputNode;
@ -2389,10 +2388,13 @@ WebConsoleFrame.prototype = {
if (win) {
win.focus();
}
return;
}
let viewSourceUtils = this.owner.gViewSourceUtils;
viewSourceUtils.viewSource(aSourceURL, null, this.document, aSourceLine);
else if (locationNode.parentNode.category == CATEGORY_CSS) {
this.owner.viewSourceInStyleEditor(aSourceURL, aSourceLine);
}
else {
this.owner.viewSource(aSourceURL, aSourceLine);
}
}.bind(this), true);
return locationNode;

View File

@ -39,6 +39,11 @@
- checkbox that toggles pausing on exceptions. -->
<!ENTITY debuggerUI.pauseExceptions "Pause on exceptions">
<!-- LOCALIZATION NOTE (debuggerUI.showNonEnums): This is the label for the
- checkbox that toggles visibility of hidden (non-enumerable) variables and
- properties in stack views. -->
<!ENTITY debuggerUI.showNonEnums "Show hidden properties">
<!-- LOCALIZATION NOTE (debuggerUI.searchPanelTitle): This is the text that
- appears in the filter panel popup as a description. -->
<!ENTITY debuggerUI.searchPanelTitle "Operators">

View File

@ -43,10 +43,7 @@ li.container {
.expander {
position: absolute;
-moz-appearance: treetwisty;
top: 0;
left: 0;
width: 14px;
height: 14px;
padding: 11px 0;
}
.expander[expanded] {