Merge fx-team to m-c. a=merge

This commit is contained in:
Ryan VanderMeulen 2015-02-23 12:28:02 -05:00
commit b9a237cfde
22 changed files with 509 additions and 267 deletions

View File

@ -1873,10 +1873,8 @@ pref("dom.ipc.reportProcessHangs", false);
pref("dom.ipc.reportProcessHangs", true);
#endif
#ifndef NIGHTLY_BUILD
// Disable reader mode by default.
pref("reader.parse-on-load.enabled", false);
#endif
// Disable ReadingList by default.
pref("browser.readinglist.enabled", false);

View File

@ -444,6 +444,28 @@
onpopupshowing="if (!this.parentNode._placesView)
new PlacesMenu(event, 'place:folder=TOOLBAR');"/>
</menu>
#ifndef XP_MACOSX
# Disabled on Mac because we can't fill native menupopups asynchronously
<menuseparator/>
<menu id="menu_readingList"
class="menu-iconic bookmark-item"
label="&readingList.label;"
container="true">
<observes element="readingListSidebar" attribute="hidden"/>
<menupopup id="readingListPopup"
#ifndef XP_MACOSX
placespopup="true"
#endif
onpopupshowing="ReadingListUI.onReadingListPopupShowing(this);">
<menuseparator id="viewReadingListSidebarSeparator"/>
<menuitem id="viewReadingListSidebar" class="subviewbutton"
oncommand="SidebarUI.toggle('readingListSidebar');"
label="&readingList.showSidebar.label;">
<observes element="readingListSidebar" attribute="checked"/>
</menuitem>
</menupopup>
</menu>
#endif
<menuseparator id="bookmarksMenuItemsSeparator"/>
<!-- Bookmarks menu items -->
<menuseparator builder="end"

View File

@ -4,6 +4,9 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
XPCOMUtils.defineLazyModuleGetter(this, "ReadingList",
"resource:///modules/readinglist/ReadingList.jsm");
let ReadingListUI = {
/**
* Initialize the ReadingList UI.
@ -65,4 +68,70 @@ let ReadingListUI = {
SidebarUI.hide();
}
},
onReadingListPopupShowing(target) {
if (target.id == "BMB_readingListPopup") {
// Setting this class in the .xul file messes with the way
// browser-places.js inserts bookmarks in the menu.
document.getElementById("BMB_viewReadingListSidebar")
.classList.add("panel-subview-footer");
}
while (!target.firstChild.id)
target.firstChild.remove();
let classList = "menuitem-iconic bookmark-item menuitem-with-favicon";
let insertPoint = target.firstChild;
if (insertPoint.classList.contains("subviewbutton"))
classList += " subviewbutton";
ReadingList.getItems().then(items => {
for (let item of items) {
let menuitem = document.createElement("menuitem");
menuitem.setAttribute("label", item.title || item.url.spec);
menuitem.setAttribute("class", classList);
let node = menuitem._placesNode = {
// Passing the PlacesUtils.nodeIsURI check is required for the
// onCommand handler to load our URI.
type: Ci.nsINavHistoryResultNode.RESULT_TYPE_URI,
// makes PlacesUIUtils.canUserRemove return false.
// The context menu is broken without this.
parent: {type: Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER},
// A -1 id makes this item a non-bookmark, which avoids calling
// PlacesUtils.annotations.itemHasAnnotation to check if the
// bookmark should be opened in the sidebar (this call fails for
// readinglist item, and breaks loading our URI).
itemId: -1,
// Used by the tooltip and onCommand handlers.
uri: item.url.spec,
// Used by the tooltip.
title: item.title
};
Favicons.getFaviconURLForPage(item.url, uri => {
if (uri) {
menuitem.setAttribute("image",
Favicons.getFaviconLinkForIcon(uri).spec);
}
});
target.insertBefore(menuitem, insertPoint);
}
if (!items.length) {
let menuitem = document.createElement("menuitem");
let bundle =
Services.strings.createBundle("chrome://browser/locale/places/places.properties");
menuitem.setAttribute("label", bundle.GetStringFromName("bookmarksMenuEmptyFolder"));
menuitem.setAttribute("class", "bookmark-item");
menuitem.setAttribute("disabled", true);
target.insertBefore(menuitem, insertPoint);
}
});
}
};

View File

@ -37,6 +37,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "ContentSearch",
"resource:///modules/ContentSearch.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AboutHome",
"resource:///modules/AboutHome.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "Favicons",
"@mozilla.org/browser/favicon-service;1",
"mozIAsyncFavicons");
XPCOMUtils.defineLazyServiceGetter(this, "gDNSService",
"@mozilla.org/network/dns-service;1",
"nsIDNSService");

View File

@ -950,6 +950,22 @@
new PlacesMenu(event, 'place:folder=UNFILED_BOOKMARKS',
PlacesUIUtils.getViewForNode(this.parentNode.parentNode).options);"/>
</menu>
<menuseparator>
<observes element="readingListSidebar" attribute="hidden"/>
</menuseparator>
<menu id="BMB_readingList"
class="menu-iconic bookmark-item subviewbutton"
label="&readingList.label;"
container="true">
<observes element="readingListSidebar" attribute="hidden"/>
<menupopup id="BMB_readingListPopup"
placespopup="true"
onpopupshowing="ReadingListUI.onReadingListPopupShowing(this);">
<menuitem id="BMB_viewReadingListSidebar" class="subviewbutton"
oncommand="SidebarUI.show('readingListSidebar');"
label="&readingList.showSidebar.label;"/>
</menupopup>
</menu>
<menuseparator/>
<!-- Bookmarks menu items will go here -->
<menuitem id="BMB_bookmarksShowAll"

View File

@ -126,6 +126,17 @@
label="&unsortedBookmarksCmd.label;"
class="subviewbutton cui-withicon"
oncommand="PlacesCommandHook.showPlacesOrganizer('UnfiledBookmarks'); PanelUI.hide();"/>
<toolbarseparator>
<observes element="readingListSidebar" attribute="hidden"/>
</toolbarseparator>
<toolbarbutton id="panelMenu_viewReadingListSidebar"
label="&readingList.showSidebar.label;"
class="subviewbutton"
key="key_readingListSidebar"
oncommand="SidebarUI.toggle('readingListSidebar'); PanelUI.hide();">
<observes element="readingListSidebar" attribute="checked"/>
<observes element="readingListSidebar" attribute="hidden"/>
</toolbarbutton>
<toolbarseparator class="small-separator"/>
<toolbaritem id="panelMenu_bookmarksMenu"
orient="vertical"

View File

@ -847,7 +847,6 @@ just addresses the organization to follow, e.g. "This site is run by " -->
<!ENTITY readingList.label "Reading List">
<!ENTITY readingList.sidebar.commandKey "R">
<!-- Pre-landed string for bug 1124400 -->
<!ENTITY readingList.showSidebar.label "Show Reading List Sidebar">
<!-- Pre-landed string for bug 1124153 -->
<!ENTITY readingList.sidebar.showMore.label "Show more…">

View File

@ -518,6 +518,11 @@ menuitem:not([type]):not(.menuitem-tooltip):not(.menuitem-iconic-tooltip) {
list-style-image: url("chrome://browser/skin/places/unsortedBookmarks.png");
}
#menu_readingList,
#BMB_readingList {
list-style-image: url("chrome://browser/skin/readinglist/readinglist-icon.svg");
}
#menu_openDownloads {
list-style-image: url("chrome://browser/skin/Toolbar-small.png");
-moz-image-region: rect(0px 16px 16px 0px);

View File

@ -91,6 +91,7 @@ browser.jar:
skin/classic/browser/tab-crashed.svg (../shared/incontent-icons/tab-crashed.svg)
skin/classic/browser/welcome-back.svg (../shared/incontent-icons/welcome-back.svg)
skin/classic/browser/reader-mode-16.png (../shared/reader/reader-mode-16.png)
skin/classic/browser/readinglist/readinglist-icon.svg (../shared/readinglist/readinglist-icon.svg)
skin/classic/browser/readinglist/sidebar.css (../shared/readinglist/sidebar.css)
skin/classic/browser/webRTC-shareDevice-16.png
skin/classic/browser/webRTC-shareDevice-64.png

View File

@ -563,6 +563,11 @@ toolbarpaletteitem[place="palette"] > #personal-bookmarks > #bookmarks-toolbar-p
}
}
/* #menu_readingList, svg icons don't work in the mac native menubar */
#BMB_readingList {
list-style-image: url("chrome://browser/skin/readinglist/readinglist-icon.svg");
}
/* ----- PRIMARY TOOLBAR BUTTONS ----- */
toolbar .toolbarbutton-1:not([type="menu-button"]),

View File

@ -142,6 +142,7 @@ browser.jar:
skin/classic/browser/welcome-back.svg (../shared/incontent-icons/welcome-back.svg)
skin/classic/browser/reader-mode-16.png (../shared/reader/reader-mode-16.png)
skin/classic/browser/reader-mode-16@2x.png (../shared/reader/reader-mode-16@2x.png)
skin/classic/browser/readinglist/readinglist-icon.svg (../shared/readinglist/readinglist-icon.svg)
skin/classic/browser/readinglist/sidebar.css (../shared/readinglist/sidebar.css)
skin/classic/browser/webRTC-shareDevice-16.png
skin/classic/browser/webRTC-shareDevice-16@2x.png

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 16 16">
<rect x="4.8" y="6.4" fill="#808080" width="11.2" height="3.2"/>
<rect x="4.8" y="11.2" fill="#808080" width="11.2" height="3.2"/>
<rect x="4.8" y="1.6" fill="#808080" width="11.2" height="3.2"/>
<circle fill="#808080" cx="1.6" cy="3.2" r="1.6"/>
<circle fill="#808080" cx="1.6" cy="8" r="1.6"/>
<circle fill="#808080" cx="1.6" cy="12.8" r="1.6"/>
</svg>

After

Width:  |  Height:  |  Size: 510 B

View File

@ -2526,6 +2526,12 @@ notification[value="translation"] {
-moz-image-region: auto;
}
#menu_readingList,
#BMB_readingList {
list-style-image: url("chrome://browser/skin/readinglist/readinglist-icon.svg");
-moz-image-region: auto;
}
/* ::::: Keyboard UI Panel ::::: */
.KUI-panel {

View File

@ -110,6 +110,7 @@ browser.jar:
skin/classic/browser/tab-crashed.svg (../shared/incontent-icons/tab-crashed.svg)
skin/classic/browser/welcome-back.svg (../shared/incontent-icons/welcome-back.svg)
skin/classic/browser/reader-mode-16.png (../shared/reader/reader-mode-16.png)
skin/classic/browser/readinglist/readinglist-icon.svg (../shared/readinglist/readinglist-icon.svg)
skin/classic/browser/readinglist/sidebar.css (../shared/readinglist/sidebar.css)
skin/classic/browser/notification-pluginNormal.png (../shared/plugins/notification-pluginNormal.png)
skin/classic/browser/notification-pluginAlert.png (../shared/plugins/notification-pluginAlert.png)
@ -576,6 +577,7 @@ browser.jar:
skin/classic/aero/browser/tab-crashed.svg (../shared/incontent-icons/tab-crashed.svg)
skin/classic/aero/browser/welcome-back.svg (../shared/incontent-icons/welcome-back.svg)
skin/classic/aero/browser/reader-mode-16.png (../shared/reader/reader-mode-16.png)
skin/classic/aero/browser/readinglist/readinglist-icon.svg (../shared/readinglist/readinglist-icon.svg)
skin/classic/aero/browser/readinglist/sidebar.css (../shared/readinglist/sidebar.css)
skin/classic/aero/browser/notification-pluginNormal.png (../shared/plugins/notification-pluginNormal.png)
skin/classic/aero/browser/notification-pluginAlert.png (../shared/plugins/notification-pluginAlert.png)

View File

@ -858,6 +858,3 @@ pref("reader.color_scheme.values", "[\"light\",\"dark\",\"auto\"]");
// Whether to use a vertical or horizontal toolbar.
pref("reader.toolbar.vertical", false);
// Whether or not to display buttons related to reading list in reader view.
pref("browser.readinglist.enabled", true);

View File

@ -57,16 +57,9 @@ let AboutReader = function(mm, win) {
this._setupStyleDropdown();
this._setupButton("close-button", this._onReaderClose.bind(this), "aboutReader.toolbar.close");
this._setupButton("toggle-button", this._onReaderToggle.bind(this), "aboutReader.toolbar.addToReadingList");
this._setupButton("share-button", this._onShare.bind(this), "aboutReader.toolbar.share");
try {
if (Services.prefs.getBoolPref("browser.readinglist.enabled")) {
this._setupButton("toggle-button", this._onReaderToggle.bind(this), "aboutReader.toolbar.addToReadingList");
this._setupButton("list-button", this._onList.bind(this), "aboutReader.toolbar.openReadingList");
}
} catch (e) {
// Pref doesn't exist.
}
this._setupButton("list-button", this._onList.bind(this), "aboutReader.toolbar.openReadingList");
let colorSchemeValues = JSON.parse(Services.prefs.getCharPref("reader.color_scheme.values"));
let colorSchemeOptions = colorSchemeValues.map((value) => {
@ -706,7 +699,6 @@ AboutReader.prototype = {
_setupButton: function Reader_setupButton(id, callback, titleEntity) {
let button = this._doc.getElementById(id);
button.removeAttribute("hidden");
button.setAttribute("title", gStrings.GetStringFromName(titleEntity));
button.addEventListener("click", function(aEvent) {

View File

@ -38,8 +38,8 @@
<div class="dropdown-arrow"/>
</li>
</ul>
<li><button id="toggle-button" class="button toggle-button" hidden="true"/></li>
<li><button id="list-button" class="button list-button" hidden="true"/></li>
<li><button id="toggle-button" class="button toggle-button"/></li>
<li><button id="list-button" class="button list-button"/></li>
</ul>
</body>

View File

@ -295,6 +295,133 @@ ActorPool.prototype = {
exports.ActorPool = ActorPool;
/**
* An OriginalLocation represents a location in an original source.
*
* @param SourceActor actor
* A SourceActor representing an original source.
* @param Number line
* A line within the given source.
* @param Number column
* A column within the given line.
* @param String name
* The name of the symbol corresponding to this OriginalLocation.
*/
function OriginalLocation(actor, line, column, name) {
this._connection = actor ? actor.conn : null;
this._actorID = actor ? actor.actorID : undefined;
this._line = line;
this._column = column;
this._name = name;
}
OriginalLocation.fromGeneratedLocation = function (generatedLocation) {
return new OriginalLocation(
generatedLocation.generatedSourceActor,
generatedLocation.generatedLine,
generatedLocation.generatedColumn
);
};
OriginalLocation.prototype = {
get originalSourceActor() {
return this._connection ? this._connection.getActor(this._actorID) : null;
},
get originalUrl() {
let actor = this.originalSourceActor;
let source = actor.source;
return source ? source.url : actor._originalUrl;
},
get originalLine() {
return this._line;
},
get originalColumn() {
return this._column;
},
get originalName() {
return this._name;
},
get generatedSourceActor() {
throw new Error("Shouldn't access generatedSourceActor from an OriginalLocation");
},
get generatedLine() {
throw new Error("Shouldn't access generatedLine from an OriginalLocation");
},
get generatedColumn() {
throw new Error("Shouldn't access generatedColumn from an Originallocation");
}
};
exports.OriginalLocation = OriginalLocation;
/**
* A GeneratedLocation represents a location in an original source.
*
* @param SourceActor actor
* A SourceActor representing a generated source.
* @param Number line
* A line within the given source.
* @param Number column
* A column within the given line.
*/
function GeneratedLocation(actor, line, column) {
this._connection = actor ? actor.conn : null;
this._actorID = actor ? actor.actorID : undefined;
this._line = line;
this._column = column;
}
GeneratedLocation.fromOriginalLocation = function (originalLocation) {
return new GeneratedLocation(
originalLocation.originalSourceActor,
originalLocation.originalLine,
originalLocation.originalColumn
);
};
GeneratedLocation.prototype = {
get originalSourceActor() {
throw new Error();
},
get originalUrl() {
throw new Error("Shouldn't access originalUrl from a GeneratedLocation");
},
get originalLine() {
throw new Error("Shouldn't access originalLine from a GeneratedLocation");
},
get originalColumn() {
throw new Error("Shouldn't access originalColumn from a GeneratedLocation");
},
get originalName() {
throw new Error("Shouldn't access originalName from a GeneratedLocation");
},
get generatedSourceActor() {
return this._connection ? this._connection.getActor(this._actorID) : null;
},
get generatedLine() {
return this._line;
},
get generatedColumn() {
return this._column;
}
};
exports.GeneratedLocation = GeneratedLocation;
// TODO bug 863089: use Debugger.Script.prototype.getOffsetColumn when it is
// implemented.
exports.getOffsetColumn = function getOffsetColumn(aOffset, aScript) {

View File

@ -8,7 +8,7 @@
const Services = require("Services");
const { Cc, Ci, Cu, components, ChromeWorker } = require("chrome");
const { ActorPool, getOffsetColumn } = require("devtools/server/actors/common");
const { ActorPool, OriginalLocation, GeneratedLocation, getOffsetColumn } = require("devtools/server/actors/common");
const { DebuggerServer } = require("devtools/server/main");
const DevToolsUtils = require("devtools/toolkit/DevToolsUtils");
const { dbg_assert, dumpn, update, fetch } = DevToolsUtils;
@ -75,28 +75,23 @@ function BreakpointActorMap() {
BreakpointActorMap.prototype = {
/**
* Return the number of instances of BreakpointActor in this instance of
* BreakpointActorMap.
* Return the number of BreakpointActors in this BreakpointActorMap.
*
* @returns Number
* The number of instances of BreakpointACtor in this instance of
* BreakpointActorMap.
* The number of BreakpointActor in this BreakpointActorMap.
*/
get size() {
return this._size;
},
/**
* Generate all instances of BreakpointActor that match the given query in
* this instance of BreakpointActorMap.
* Generate all BreakpointActors that match the given location in
* this BreakpointActorMap.
*
* @param Object query
* An optional object with the following properties:
* - source (optional)
* - line (optional, requires source)
* - column (optional, requires line)
* @param GeneratedLocation location
* The location for which matching BreakpointActors should be generated.
*/
findActors: function* (query = {}) {
findActors: function* (location = new GeneratedLocation()) {
function* findKeys(object, key) {
if (key !== undefined) {
if (key in object) {
@ -110,9 +105,12 @@ BreakpointActorMap.prototype = {
}
}
query.sourceActorID = query.sourceActor ? query.sourceActor.actorID : undefined;
query.beginColumn = query.column ? query.column : undefined;
query.endColumn = query.column ? query.column + 1 : undefined;
let query = {
sourceActorID: location.generatedSourceActor ? location.generatedSourceActor.actorID : undefined,
line: location.generatedLine,
beginColumn: location.generatedColumn ? location.generatedColumn : undefined,
endColumn: location.generatedColumn ? location.generatedColumn + 1 : undefined
};
for (let sourceActorID of findKeys(this._actors, query.sourceActorID))
for (let line of findKeys(this._actors[sourceActorID], query.line))
@ -123,17 +121,14 @@ BreakpointActorMap.prototype = {
},
/**
* Return the instance of BreakpointActor at the given location in this
* instance of BreakpointActorMap.
* Return the BreakpointActor at the given location in this
* BreakpointActorMap.
*
* @param Object location
* An object with the following properties:
* - source
* - line
* - column (optional)
* @param GeneratedLocation location
* The location for which the BreakpointActor should be returned.
*
* @returns BreakpointActor actor
* The instance of BreakpointActor at the given location.
* The BreakpointActor at the given location.
*/
getActor: function (location) {
for (let actor of this.findActors(location)) {
@ -144,24 +139,22 @@ BreakpointActorMap.prototype = {
},
/**
* Set the given instance of BreakpointActor to the given location in this
* instance of BreakpointActorMap.
* Set the given BreakpointActor to the given location in this
* BreakpointActorMap.
*
* @param Object location
* An object with the following properties:
* - source
* - line
* - column (optional)
* @param GeneratedLocation location
* The location to which the given BreakpointActor should be set.
*
* @param BreakpointActor actor
* The instance of BreakpointActor to be set to the given location.
* The BreakpointActor to be set to the given location.
*/
setActor: function (location, actor) {
let { sourceActor, line, column } = location;
let { generatedSourceActor, generatedLine, generatedColumn } = location;
let sourceActorID = sourceActor.actorID;
let beginColumn = column ? column : 0;
let endColumn = column ? column + 1 : Infinity;
let sourceActorID = generatedSourceActor.actorID;
let line = generatedLine;
let beginColumn = generatedColumn ? generatedColumn : 0;
let endColumn = generatedColumn ? generatedColumn + 1 : Infinity;
if (!this._actors[sourceActorID]) {
this._actors[sourceActorID] = [];
@ -179,21 +172,19 @@ BreakpointActorMap.prototype = {
},
/**
* Delete the instance of BreakpointActor from the given location in this
* instance of BreakpointActorMap.
* Delete the BreakpointActor from the given location in this
* BreakpointActorMap.
*
* @param Object location
* An object with the following properties:
* - source
* - line
* - column (optional)
* @param GeneratedLocation location
* The location from which the BreakpointActor should be deleted.
*/
deleteActor: function (location) {
let { sourceActor, line, column } = location;
let { generatedSourceActor, generatedLine, generatedColumn } = location;
let sourceActorID = sourceActor.actorID;
let beginColumn = column ? column : 0;
let endColumn = column ? column + 1 : Infinity;
let sourceActorID = generatedSourceActor.actorID;
let line = generatedLine;
let beginColumn = generatedColumn ? generatedColumn : 0;
let endColumn = generatedColumn ? generatedColumn + 1 : Infinity;
if (this._actors[sourceActorID]) {
if (this._actors[sourceActorID][line]) {
@ -742,9 +733,10 @@ ThreadActor.prototype = {
}
packet.why = aReason;
let loc = this.sources.getFrameLocation(aFrame);
this.sources.getOriginalLocation(loc).then(aOrigPosition => {
if (!aOrigPosition.sourceActor) {
let generatedLocation = this.sources.getFrameLocation(aFrame);
this.sources.getOriginalLocation(generatedLocation)
.then((originalLocation) => {
if (!originalLocation.originalSourceActor) {
// The only time the source actor will be null is if there
// was a sourcemap and it tried to look up the original
// location but there was no original URL. This is a strange
@ -759,9 +751,9 @@ ThreadActor.prototype = {
}
packet.frame.where = {
source: aOrigPosition.sourceActor.form(),
line: aOrigPosition.line,
column: aOrigPosition.column
source: originalLocation.originalSourceActor.form(),
line: originalLocation.originalLine,
column: originalLocation.originalColumn
};
resolve(onPacket(packet))
.then(null, error => {
@ -806,9 +798,9 @@ ThreadActor.prototype = {
_makeOnEnterFrame: function ({ pauseAndRespond }) {
return aFrame => {
const generatedLocation = this.sources.getFrameLocation(aFrame);
let { sourceActor } = this.synchronize(this.sources.getOriginalLocation(
let { originalSourceActor } = this.synchronize(this.sources.getOriginalLocation(
generatedLocation));
let url = sourceActor.url;
let url = originalSourceActor.url;
return this.sources.isBlackBoxed(url)
? undefined
@ -821,9 +813,9 @@ ThreadActor.prototype = {
// onPop is called with 'this' set to the current frame.
const generatedLocation = thread.sources.getFrameLocation(this);
const { sourceActor } = thread.synchronize(thread.sources.getOriginalLocation(
const { originalSourceActor } = thread.synchronize(thread.sources.getOriginalLocation(
generatedLocation));
const url = sourceActor.url;
const url = originalSourceActor.url;
if (thread.sources.isBlackBoxed(url)) {
return undefined;
@ -882,15 +874,15 @@ ThreadActor.prototype = {
// 2.2. The source we are in is black boxed.
// Cases 2.1 and 2.2
if (newLocation.url == null
|| thread.sources.isBlackBoxed(newLocation.url)) {
if (newLocation.originalUrl == null
|| thread.sources.isBlackBoxed(newLocation.originalUrl)) {
return undefined;
}
// Cases 1.1, 1.2 and 1.3
if (this !== startFrame
|| startLocation.url !== newLocation.url
|| startLocation.line !== newLocation.line) {
|| startLocation.originalUrl !== newLocation.originalUrl
|| startLocation.originalLine !== newLocation.originalLine) {
return pauseAndRespond(this);
}
@ -1288,16 +1280,16 @@ ThreadActor.prototype = {
form.depth = i;
frames.push(form);
let promise = this.sources.getOriginalLocation({
sourceActor: this.sources.createNonSourceMappedActor(frame.script.source),
line: form.where.line,
column: form.where.column
}).then((aOrigLocation) => {
let sourceForm = aOrigLocation.sourceActor.form();
let promise = this.sources.getOriginalLocation(new GeneratedLocation(
this.sources.createNonSourceMappedActor(frame.script.source),
form.where.line,
form.where.column
)).then((originalLocation) => {
let sourceForm = originalLocation.originalSourceActor.form();
form.where = {
source: sourceForm,
line: aOrigLocation.line,
column: aOrigLocation.column
line: originalLocation.originalLine,
column: originalLocation.originalColumn
};
form.source = sourceForm;
});
@ -1903,9 +1895,9 @@ ThreadActor.prototype = {
// Don't pause if we are currently stepping (in or over) or the frame is
// black-boxed.
const generatedLocation = this.sources.getFrameLocation(aFrame);
const { sourceActor } = this.synchronize(this.sources.getOriginalLocation(
const { originalSourceActor } = this.synchronize(this.sources.getOriginalLocation(
generatedLocation));
const url = sourceActor ? sourceActor.url : null;
const url = originalSourceActor ? originalSourceActor.url : null;
return this.sources.isBlackBoxed(url) || aFrame.onStep
? undefined
@ -2039,8 +2031,8 @@ ThreadActor.prototype = {
let source = this.sources.createNonSourceMappedActor(aScript.source);
for (let bpActor of this.breakpointActorMap.findActors({ sourceActor: source })) {
// Limit the search to the line numbers contained in the new script.
if (bpActor.generatedLocation.line >= aScript.startLine
&& bpActor.generatedLocation.line <= endLine) {
if (bpActor.generatedLocation.generatedLine >= aScript.startLine
&& bpActor.generatedLocation.generatedLine <= endLine) {
source.setBreakpointForActor(bpActor);
}
}
@ -2751,12 +2743,14 @@ SourceActor.prototype = {
* @returns Object
* The RDP response.
*/
_setBreakpointAtColumn: function (scripts, location, actor) {
_setBreakpointAtColumn: function (scripts, generatedLocation, actor) {
// Debugger.Script -> array of offset mappings
const scriptsAndOffsetMappings = new Map();
for (let script of scripts) {
this._findClosestOffsetMappings(location, script, scriptsAndOffsetMappings);
this._findClosestOffsetMappings(generatedLocation,
script,
scriptsAndOffsetMappings);
}
for (let [script, mappings] of scriptsAndOffsetMappings) {
@ -2832,18 +2826,13 @@ SourceActor.prototype = {
* A condition for the breakpoint.
*/
setBreakpoint: function (originalLine, originalColumn, condition) {
let originalLocation = {
sourceActor: this,
line: originalLine,
column: originalColumn
};
let originalLocation = new OriginalLocation(this, originalLine, originalColumn);
return this.threadActor.sources.getGeneratedLocation(originalLocation)
.then(generatedLocation => {
let actor = this._getOrCreateBreakpointActor(originalLocation,
generatedLocation,
condition);
return generatedLocation.sourceActor.setBreakpointForActor(actor);
return generatedLocation.generatedSourceActor.setBreakpointForActor(actor);
});
},
@ -2857,13 +2846,13 @@ SourceActor.prototype = {
*/
setBreakpointForActor: function (actor) {
let originalLocation = actor.originalLocation;
let generatedLocation = {
sourceActor: this,
line: actor.generatedLocation.line,
column: actor.generatedLocation.column
};
let generatedLocation = new GeneratedLocation(
this,
actor.generatedLocation.generatedLine,
actor.generatedLocation.generatedColumn
);
let { line: generatedLine, column: generatedColumn } = generatedLocation;
let { generatedLine, generatedColumn } = generatedLocation;
// Find all scripts matching the given location. We will almost always have
// a `source` object to query, but multiple inline HTML scripts are all
@ -2889,13 +2878,13 @@ SourceActor.prototype = {
// handler.
scripts = scripts.filter((script) => !actor.hasScript(script));
let actualLocation;
let actualGeneratedLocation;
// If generatedColumn is something other than 0, assume this is a column
// breakpoint and do not perform breakpoint sliding.
if (generatedColumn) {
this._setBreakpointAtColumn(scripts, generatedLocation, actor);
actualLocation = generatedLocation;
actualGeneratedLocation = generatedLocation;
} else {
let result;
if (actor.scripts.size === 0) {
@ -2925,53 +2914,49 @@ SourceActor.prototype = {
}
if (result.line !== generatedLine) {
actualLocation = {
sourceActor: generatedLocation.sourceActor,
line: result.line,
column: generatedLocation.column
};
actualGeneratedLocation = new GeneratedLocation(
generatedLocation.generatedSourceActor,
result.line,
generatedLocation.generatedColumn
);
// Check whether we already have a breakpoint actor for the actual
// location. If we do have an existing actor, then the actor we created
// above is redundant and must be destroyed. If we do not have an existing
// actor, we need to update the breakpoint store with the new location.
let existingActor = this.breakpointActorMap.getActor(actualLocation);
let existingActor = this.breakpointActorMap.getActor(actualGeneratedLocation);
if (existingActor) {
actor.onDelete();
this.breakpointActorMap.deleteActor(generatedLocation);
actor = existingActor;
} else {
actor.generatedLocation = actualLocation;
actor.generatedLocation = actualGeneratedLocation;
this.breakpointActorMap.deleteActor(generatedLocation);
this.breakpointActorMap.setActor(actualLocation, actor);
this.breakpointActorMap.setActor(actualGeneratedLocation, actor);
setBreakpointOnEntryPoints(this.threadActor, actor, result.entryPoints);
}
} else {
setBreakpointOnEntryPoints(this.threadActor, actor, result.entryPoints);
actualLocation = generatedLocation;
actualGeneratedLocation = generatedLocation;
}
}
return Promise.resolve().then(() => {
if (actualLocation.sourceActor.source) {
return this.threadActor.sources.getOriginalLocation({
sourceActor: actualLocation.sourceActor,
line: actualLocation.line,
column: actualLocation.column
});
if (actualGeneratedLocation.generatedSourceActor.source) {
return this.threadActor.sources.getOriginalLocation(actualGeneratedLocation);
} else {
return actualLocation;
return OriginalLocation.fromGeneratedLocation(actualGeneratedLocation);
}
}).then((actualLocation) => {
}).then((actualOriginalLocation) => {
let response = { actor: actor.actorID };
if (actualLocation.sourceActor.url !== originalLocation.sourceActor.url ||
actualLocation.line !== originalLocation.line)
if (actualOriginalLocation.originalSourceActor.url !== originalLocation.originalSourceActor.url ||
actualOriginalLocation.originalLine !== originalLocation.originalLine)
{
response.actualLocation = {
source: actualLocation.sourceActor.form(),
line: actualLocation.line,
column: actualLocation.column
source: actualOriginalLocation.originalSourceActor.form(),
line: actualOriginalLocation.originalLine,
column: actualOriginalLocation.originalColumn
};
}
return response;
@ -3019,7 +3004,7 @@ SourceActor.prototype = {
aScript,
aScriptsAndOffsetMappings) {
let offsetMappings = aScript.getAllColumnOffsets()
.filter(({ lineNumber }) => lineNumber === aTargetLocation.line);
.filter(({ lineNumber }) => lineNumber === aTargetLocation.generatedLine);
// Attempt to find the current closest offset distance from the target
// location by grabbing any offset mapping in the map by doing one iteration
@ -3028,13 +3013,13 @@ SourceActor.prototype = {
let closestDistance = Infinity;
if (aScriptsAndOffsetMappings.size) {
for (let mappings of aScriptsAndOffsetMappings.values()) {
closestDistance = Math.abs(aTargetLocation.column - mappings[0].columnNumber);
closestDistance = Math.abs(aTargetLocation.generatedColumn - mappings[0].columnNumber);
break;
}
}
for (let mapping of offsetMappings) {
let currentDistance = Math.abs(aTargetLocation.column - mapping.columnNumber);
let currentDistance = Math.abs(aTargetLocation.generatedColumn - mapping.columnNumber);
if (currentDistance > closestDistance) {
continue;
@ -3329,23 +3314,17 @@ ObjectActor.prototype = {
};
}
const generatedLocation = {
sourceActor: this.threadActor.sources.createNonSourceMappedActor(this.obj.script.source),
line: this.obj.script.startLine,
// TODO bug 901138: use Debugger.Script.prototype.startColumn.
column: 0
};
return this.threadActor.sources.getOriginalLocation(generatedLocation)
.then(({ sourceActor, line, column }) => {
return {
from: this.actorID,
source: sourceActor.form(),
line: line,
column: column
};
});
return this.threadActor.sources.getOriginalLocation(new GeneratedLocation(
this.threadActor.sources.createNonSourceMappedActor(this.obj.script.source),
this.obj.script.startLine,
0 // TODO bug 901138: use Debugger.Script.prototype.startColumn
)).then((originalLocation) => {
return {
source: originalLocation.originalSourceActor.form(),
line: originalLocation.originalLine,
column: originalLocation.originalColumn
};
});
},
/**
@ -4573,11 +4552,11 @@ FrameActor.prototype = {
form.this = threadActor.createValueGrip(this.frame.this);
form.arguments = this._args();
if (this.frame.script) {
var loc = this.threadActor.sources.getFrameLocation(this.frame);
var generatedLocation = this.threadActor.sources.getFrameLocation(this.frame);
form.where = {
source: loc.sourceActor.form(),
line: loc.line,
column: loc.column
source: generatedLocation.generatedSourceActor.form(),
line: generatedLocation.generatedLine,
column: generatedLocation.generatedColumn
};
}
@ -4714,10 +4693,10 @@ BreakpointActor.prototype = {
hit: function (aFrame) {
// Don't pause if we are currently stepping (in or over) or the frame is
// black-boxed.
let loc = this.threadActor.sources.getFrameLocation(aFrame);
let { sourceActor } = this.threadActor.synchronize(
this.threadActor.sources.getOriginalLocation(loc));
let url = sourceActor.url;
let generatedLocation = this.threadActor.sources.getFrameLocation(aFrame);
let { originalSourceActor } = this.threadActor.synchronize(
this.threadActor.sources.getOriginalLocation(generatedLocation));
let url = originalSourceActor.url;
if (this.threadActor.sources.isBlackBoxed(url)
|| aFrame.onStep
@ -5558,13 +5537,13 @@ ThreadSources.prototype = {
*/
getFrameLocation: function (aFrame) {
if (!aFrame || !aFrame.script) {
return { sourceActor: null, line: null, column: null };
}
return {
sourceActor: this.createNonSourceMappedActor(aFrame.script.source),
line: aFrame.script.getOffsetLine(aFrame.offset),
column: getOffsetColumn(aFrame.offset, aFrame.script)
return new GeneratedLocation();
}
return new GeneratedLocation(
this.createNonSourceMappedActor(aFrame.script.source),
aFrame.script.getOffsetLine(aFrame.offset),
getOffsetColumn(aFrame.offset, aFrame.script)
);
},
/**
@ -5574,53 +5553,52 @@ ThreadSources.prototype = {
* sure to that it works properly, reusing source maps if already
* fetched. Use this from any actor that needs sourcemapping.
*/
getOriginalLocation: function ({ sourceActor, line, column }) {
let source = sourceActor.source;
let url = source ? source.url : sourceActor._originalUrl;
getOriginalLocation: function (generatedLocation) {
let {
generatedSourceActor,
generatedLine,
generatedColumn
} = generatedLocation;
let source = generatedSourceActor.source;
let url = source ? source.url : generatedSourceActor._originalUrl;
// In certain scenarios the source map may have not been fetched
// yet (or at least tied to this Debugger.Source instance), so use
// `fetchSourceMap` instead of `getSourceMap`. This allows this
// function to be called from anywere (across debuggers) and it
// should just automatically work.
return this.fetchSourceMap(source).then(sm => {
if (sm) {
return this.fetchSourceMap(source).then(map => {
if (map) {
let {
source: sourceUrl,
line: sourceLine,
column: sourceCol,
name: sourceName
} = sm.originalPositionFor({
line: line,
column: column == null ? Infinity : column
source: originalUrl,
line: originalLine,
column: originalColumn,
name: originalName
} = map.originalPositionFor({
line: generatedLine,
column: generatedColumn == null ? Infinity : generatedColumn
});
return {
// Since the `Debugger.Source` instance may come from a
// different `Debugger` instance (any actor can call this
// method), we can't rely on any of the source discovery
// setup (`_discoverSources`, etc) to have been run yet. So
// we have to assume that the actor may not already exist,
// and we might need to create it, so use `source` and give
// it the required parameters for a sourcemapped source.
sourceActor: (!sourceUrl) ? null : this.source({
originalUrl: sourceUrl,
// Since the `Debugger.Source` instance may come from a
// different `Debugger` instance (any actor can call this
// method), we can't rely on any of the source discovery
// setup (`_discoverSources`, etc) to have been run yet. So
// we have to assume that the actor may not already exist,
// and we might need to create it, so use `source` and give
// it the required parameters for a sourcemapped source.
return new OriginalLocation(
originalUrl ? this.source({
originalUrl: originalUrl,
generatedSource: source
}),
url: sourceUrl,
line: sourceLine,
column: sourceCol,
name: sourceName
};
}) : null,
originalLine,
originalColumn,
originalName
);
}
// No source map
return resolve({
sourceActor: sourceActor,
url: url,
line: line,
column: column
});
return OriginalLocation.fromGeneratedLocation(generatedLocation);
});
},
@ -5633,34 +5611,40 @@ ThreadSources.prototype = {
* the tables this function uses; thus, it won't know that S's original
* source URLs map to S until P is resolved.
*/
getGeneratedLocation: function ({ sourceActor, line, column }) {
getGeneratedLocation: function (originalLocation) {
let { originalSourceActor } = originalLocation;
// Both original sources and normal sources could have sourcemaps,
// because normal sources can be pretty-printed which generates a
// sourcemap for itself. Check both of the source properties to make it work
// for both kinds of sources.
let source = sourceActor.generatedSource || sourceActor.source;
let source = originalSourceActor.source || originalSourceActor.generatedSource;
// See comment about `fetchSourceMap` in `getOriginalLocation`.
return this.fetchSourceMap(source).then(sm => {
if (sm) {
let { line: genLine, column: genColumn } = sm.generatedPositionFor({
source: sourceActor.url,
line: line,
column: column == null ? Infinity : column
return this.fetchSourceMap(source).then((map) => {
if (map) {
let {
originalLine,
originalColumn
} = originalLocation;
let {
line: generatedLine,
column: generatedColumn
} = map.generatedPositionFor({
source: originalSourceActor.url,
line: originalLine,
column: originalColumn == null ? Infinity : originalColumn
});
return {
sourceActor: this.createNonSourceMappedActor(source),
line: genLine,
column: genColumn
};
return new GeneratedLocation(
this.createNonSourceMappedActor(source),
generatedLine,
generatedColumn
);
}
return resolve({
sourceActor: sourceActor,
line: line,
column: column
});
return GeneratedLocation.fromOriginalLocation(originalLocation);
});
},

View File

@ -8,7 +8,7 @@ const { Cu } = require("chrome");
const { DebuggerServer } = require("devtools/server/main");
const { DevToolsUtils } = Cu.import("resource://gre/modules/devtools/DevToolsUtils.jsm", {});
const Debugger = require("Debugger");
const { getOffsetColumn } = require("devtools/server/actors/common");
const { GeneratedLocation, getOffsetColumn } = require("devtools/server/actors/common");
const promise = require("promise");
Cu.import("resource://gre/modules/Task.jsm");
@ -339,25 +339,25 @@ TracerActor.prototype = {
if (aFrame.script) {
let sources = this._parent.threadActor.sources;
sourceMappedLocation = yield sources.getOriginalLocation({
sourceActor: sources.createNonSourceMappedActor(aFrame.script.source),
url: aFrame.script.source.url,
line: aFrame.script.startLine,
sourceMappedLocation = yield sources.getOriginalLocation(new GeneratedLocation(
sources.createNonSourceMappedActor(aFrame.script.source),
aFrame.script.startLine,
// We should return the location of the start of the script, but
// Debugger.Script does not provide complete start locations (bug
// 901138). Instead, return the current offset (the location of the
// first statement in the function).
column: getOffsetColumn(aFrame.offset, aFrame.script)
});
getOffsetColumn(aFrame.offset, aFrame.script)
));
}
}
if (this._requestsForTraceType.name) {
if (sourceMappedLocation && sourceMappedLocation.name) {
packet.name = sourceMappedLocation.name;
if (sourceMappedLocation && sourceMappedLocation.originalName) {
packet.name = sourceMappedLocation.originalName;
} else {
packet.name = name;
}
packet.name = name;
}
if (this._requestsForTraceType.location) {
@ -365,10 +365,9 @@ TracerActor.prototype = {
// Don't copy sourceMappedLocation directly because it
// contains a reference to the source actor
packet.location = {
url: sourceMappedLocation.url,
line: sourceMappedLocation.line,
column: sourceMappedLocation.column,
name: sourceMappedLocation.name
url: sourceMappedLocation.originalUrl,
line: sourceMappedLocation.originalLine,
column: sourceMappedLocation.originalColumn
};
}
}

View File

@ -21,13 +21,13 @@ function run_test()
function test_get_actor() {
let bpStore = new BreakpointActorMap();
let location = {
sourceActor: { actor: 'actor1' },
line: 3
generatedSourceActor: { actor: 'actor1' },
generatedLine: 3
};
let columnLocation = {
sourceActor: { actor: 'actor2' },
line: 5,
column: 15
generatedSourceActor: { actor: 'actor2' },
generatedLine: 5,
generatedColumn: 15
};
// Shouldn't have breakpoint
@ -59,9 +59,9 @@ function test_set_actor() {
// Breakpoint with column
let bpStore = new BreakpointActorMap();
let location = {
sourceActor: { actor: 'actor1' },
line: 10,
column: 9
generatedSourceActor: { actor: 'actor1' },
generatedLine: 10,
generatedColumn: 9
};
bpStore.setActor(location, {});
do_check_true(!!bpStore.getActor(location),
@ -69,8 +69,8 @@ function test_set_actor() {
// Breakpoint without column (whole line breakpoint)
location = {
sourceActor: { actor: 'actor2' },
line: 103
generatedSourceActor: { actor: 'actor2' },
generatedLine: 103
};
bpStore.setActor(location, {});
do_check_true(!!bpStore.getActor(location),
@ -81,9 +81,9 @@ function test_delete_actor() {
// Breakpoint with column
let bpStore = new BreakpointActorMap();
let location = {
sourceActor: { actor: 'actor1' },
line: 10,
column: 9
generatedSourceActor: { actor: 'actor1' },
generatedLine: 10,
generatedColumn: 9
};
bpStore.setActor(location, {});
bpStore.deleteActor(location);
@ -92,8 +92,8 @@ function test_delete_actor() {
// Breakpoint without column (whole line breakpoint)
location = {
sourceActor: { actor: 'actor2' },
line: 103
generatedSourceActor: { actor: 'actor2' },
generatedLine: 103
};
bpStore.setActor(location, {});
bpStore.deleteActor(location);
@ -103,14 +103,14 @@ function test_delete_actor() {
function test_find_actors() {
let bps = [
{ sourceActor: { actor: "actor1" }, line: 10 },
{ sourceActor: { actor: "actor1" }, line: 10, column: 3 },
{ sourceActor: { actor: "actor1" }, line: 10, column: 10 },
{ sourceActor: { actor: "actor1" }, line: 23, column: 89 },
{ sourceActor: { actor: "actor2" }, line: 10, column: 1 },
{ sourceActor: { actor: "actor2" }, line: 20, column: 5 },
{ sourceActor: { actor: "actor2" }, line: 30, column: 34 },
{ sourceActor: { actor: "actor2" }, line: 40, column: 56 }
{ generatedSourceActor: { actor: "actor1" }, generatedLine: 10 },
{ generatedSourceActor: { actor: "actor1" }, generatedLine: 10, generatedColumn: 3 },
{ generatedSourceActor: { actor: "actor1" }, generatedLine: 10, generatedColumn: 10 },
{ generatedSourceActor: { actor: "actor1" }, generatedLine: 23, generatedColumn: 89 },
{ generatedSourceActor: { actor: "actor2" }, generatedLine: 10, generatedColumn: 1 },
{ generatedSourceActor: { actor: "actor2" }, generatedLine: 20, generatedColumn: 5 },
{ generatedSourceActor: { actor: "actor2" }, generatedLine: 30, generatedColumn: 34 },
{ generatedSourceActor: { actor: "actor2" }, generatedLine: 40, generatedColumn: 56 }
];
let bpStore = new BreakpointActorMap();
@ -130,8 +130,8 @@ function test_find_actors() {
// Breakpoints by URL
bpSet = new Set(bps.filter(bp => { return bp.sourceActor.actorID === "actor1" }));
for (let bp of bpStore.findActors({ sourceActor: { actorID: "actor1" } })) {
bpSet = new Set(bps.filter(bp => { return bp.generatedSourceActor.actorID === "actor1" }));
for (let bp of bpStore.findActors({ generatedSourceActor: { actorID: "actor1" } })) {
bpSet.delete(bp);
}
do_check_eq(bpSet.size, 0,
@ -139,15 +139,15 @@ function test_find_actors() {
// Breakpoints by URL and line
bpSet = new Set(bps.filter(bp => { return bp.sourceActor.actorID === "actor1" && bp.line === 10; }));
bpSet = new Set(bps.filter(bp => { return bp.generatedSourceActor.actorID === "actor1" && bp.generatedLine === 10; }));
let first = true;
for (let bp of bpStore.findActors({ sourceActor: { actorID: "actor1" }, line: 10 })) {
for (let bp of bpStore.findActors({ generatedSourceActor: { actorID: "actor1" }, generatedLine: 10 })) {
if (first) {
do_check_eq(bp.column, undefined,
do_check_eq(bp.generatedColumn, undefined,
"Should always get the whole line breakpoint first");
first = false;
} else {
do_check_neq(bp.column, undefined,
do_check_neq(bp.generatedColumn, undefined,
"Should not get the whole line breakpoint any time other than first.");
}
bpSet.delete(bp);
@ -161,9 +161,9 @@ function test_duplicate_actors() {
// Breakpoint with column
let location = {
sourceActor: { actorID: "foo-actor" },
line: 10,
column: 9
generatedSourceActor: { actorID: "foo-actor" },
generatedLine: 10,
generatedColumn: 9
};
bpStore.setActor(location, {});
bpStore.setActor(location, {});
@ -172,8 +172,8 @@ function test_duplicate_actors() {
// Breakpoint without column (whole line breakpoint)
location = {
sourceActor: { actorID: "foo-actor" },
line: 15
generatedSourceActor: { actorID: "foo-actor" },
generatedLine: 15
};
bpStore.setActor(location, {});
bpStore.setActor(location, {});

View File

@ -248,10 +248,6 @@ body {
border-bottom: 1px solid #c1c1c1;
}
.button[hidden] {
display: none;
}
.dropdown {
text-align: center;
list-style: none;