mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-08 20:47:44 +00:00
Merge m-c to b-i.
This commit is contained in:
commit
db4dc38b67
1
aclocal.m4
vendored
1
aclocal.m4
vendored
@ -30,6 +30,7 @@ builtin(include, build/autoconf/zlib.m4)dnl
|
||||
builtin(include, build/autoconf/linux.m4)dnl
|
||||
builtin(include, build/autoconf/python-virtualenv.m4)dnl
|
||||
builtin(include, build/autoconf/winsdk.m4)dnl
|
||||
builtin(include, build/autoconf/icu.m4)dnl
|
||||
|
||||
MOZ_PROG_CHECKMSYS()
|
||||
|
||||
|
@ -605,12 +605,13 @@ int main(int argc, char* argv[])
|
||||
#ifdef HAS_DLL_BLOCKLIST
|
||||
DllBlocklist_Initialize();
|
||||
|
||||
#ifdef DEBUG
|
||||
// In order to be effective against AppInit DLLs, the blocklist must be
|
||||
// initialized before user32.dll is loaded into the process. If this assert
|
||||
// ever fires, then the fix for bug 932100 has been defeated and the
|
||||
// blocklist will miss AppInit DLLs. You should use a delayload or reorder
|
||||
// the code to prevent user32.dll from loading during early startup.
|
||||
MOZ_ASSERT(!GetModuleHandleA("user32.dll"));
|
||||
// initialized before user32.dll is loaded into the process (bug 932100).
|
||||
if (GetModuleHandleA("user32.dll")) {
|
||||
fprintf(stderr, "DLL blocklist was unable to intercept AppInit DLLs.\n");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
nsresult rv = InitXPCOMGlue(argv[0], &xreDirectory);
|
||||
|
@ -574,11 +574,7 @@ pref("browser.gesture.twist.left", "cmd_gestureRotateLeft");
|
||||
pref("browser.gesture.twist.end", "cmd_gestureRotateEnd");
|
||||
pref("browser.gesture.tap", "cmd_fullZoomReset");
|
||||
|
||||
#ifndef RELEASE_BUILD
|
||||
pref("browser.snapshots.limit", 5);
|
||||
#else
|
||||
pref("browser.snapshots.limit", 0);
|
||||
#endif
|
||||
|
||||
// 0: Nothing happens
|
||||
// 1: Scrolling contents
|
||||
|
@ -869,7 +869,7 @@ let PlacesToolbarHelper = {
|
||||
return document.getElementById("PlacesToolbar");
|
||||
},
|
||||
|
||||
init: function PTH_init() {
|
||||
init: function PTH_init(forceToolbarOverflowCheck) {
|
||||
let viewElt = this._viewElt;
|
||||
if (!viewElt || viewElt._placesView)
|
||||
return;
|
||||
@ -886,6 +886,9 @@ let PlacesToolbarHelper = {
|
||||
return;
|
||||
|
||||
new PlacesToolbar(this._place);
|
||||
if (forceToolbarOverflowCheck) {
|
||||
viewElt._placesView.updateOverflowStatus();
|
||||
}
|
||||
},
|
||||
|
||||
customizeStart: function PTH_customizeStart() {
|
||||
@ -900,7 +903,7 @@ let PlacesToolbarHelper = {
|
||||
|
||||
customizeDone: function PTH_customizeDone() {
|
||||
this._isCustomizing = false;
|
||||
this.init();
|
||||
this.init(true);
|
||||
},
|
||||
|
||||
onPlaceholderCommand: function () {
|
||||
|
@ -1037,32 +1037,14 @@ PlacesToolbar.prototype = {
|
||||
this.updateChevron();
|
||||
break;
|
||||
case "overflow":
|
||||
if (aEvent.target != aEvent.currentTarget)
|
||||
if (!this._isOverflowStateEventRelevant(aEvent))
|
||||
return;
|
||||
|
||||
// Ignore purely vertical overflows.
|
||||
if (aEvent.detail == 0)
|
||||
return;
|
||||
|
||||
// Attach the popup binding to the chevron popup if it has not yet
|
||||
// been initialized.
|
||||
if (!this._chevronPopup.hasAttribute("type")) {
|
||||
this._chevronPopup.setAttribute("place", this.place);
|
||||
this._chevronPopup.setAttribute("type", "places");
|
||||
}
|
||||
this._chevron.collapsed = false;
|
||||
this.updateChevron();
|
||||
this._onOverflow();
|
||||
break;
|
||||
case "underflow":
|
||||
if (aEvent.target != aEvent.currentTarget)
|
||||
if (!this._isOverflowStateEventRelevant(aEvent))
|
||||
return;
|
||||
|
||||
// Ignore purely vertical underflows.
|
||||
if (aEvent.detail == 0)
|
||||
return;
|
||||
|
||||
this.updateChevron();
|
||||
this._chevron.collapsed = true;
|
||||
this._onUnderflow();
|
||||
break;
|
||||
case "TabOpen":
|
||||
case "TabClose":
|
||||
@ -1103,6 +1085,35 @@ PlacesToolbar.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
updateOverflowStatus: function() {
|
||||
if (this._rootElt.scrollLeftMax > 0) {
|
||||
this._onOverflow();
|
||||
} else {
|
||||
this._onUnderflow();
|
||||
}
|
||||
},
|
||||
|
||||
_isOverflowStateEventRelevant: function PT_isOverflowStateEventRelevant(aEvent) {
|
||||
// Ignore events not aimed at ourselves, as well as purely vertical ones:
|
||||
return aEvent.target == aEvent.currentTarget && aEvent.detail > 0;
|
||||
},
|
||||
|
||||
_onOverflow: function PT_onOverflow() {
|
||||
// Attach the popup binding to the chevron popup if it has not yet
|
||||
// been initialized.
|
||||
if (!this._chevronPopup.hasAttribute("type")) {
|
||||
this._chevronPopup.setAttribute("place", this.place);
|
||||
this._chevronPopup.setAttribute("type", "places");
|
||||
}
|
||||
this._chevron.collapsed = false;
|
||||
this.updateChevron();
|
||||
},
|
||||
|
||||
_onUnderflow: function PT_onUnderflow() {
|
||||
this.updateChevron();
|
||||
this._chevron.collapsed = true;
|
||||
},
|
||||
|
||||
updateChevron: function PT_updateChevron() {
|
||||
// If the chevron is collapsed there's nothing to update.
|
||||
if (this._chevron.collapsed)
|
||||
|
@ -1508,12 +1508,34 @@ let SessionStoreInternal = {
|
||||
throw Components.Exception("Window is not tracked", Cr.NS_ERROR_INVALID_ARG);
|
||||
},
|
||||
|
||||
/**
|
||||
* Restores the given state |aState| for a given window |aWindow|.
|
||||
*
|
||||
* @param aWindow (xul window)
|
||||
* The window that the given state will be restored to.
|
||||
* @param aState (string)
|
||||
* The state that will be applied to the given window.
|
||||
* @param aOverwrite (bool)
|
||||
* When true, existing tabs in the given window will be re-used or
|
||||
* removed. When false, only new tabs will be added, no existing ones
|
||||
8 will be removed or overwritten.
|
||||
*/
|
||||
setWindowState: function ssi_setWindowState(aWindow, aState, aOverwrite) {
|
||||
if (!aWindow.__SSi) {
|
||||
throw Components.Exception("Window is not tracked", Cr.NS_ERROR_INVALID_ARG);
|
||||
}
|
||||
|
||||
this.restoreWindow(aWindow, aState, {overwriteTabs: aOverwrite});
|
||||
let winState = JSON.parse(aState);
|
||||
if (!winState) {
|
||||
throw Components.Exception("Invalid state string: not JSON", Cr.NS_ERROR_INVALID_ARG);
|
||||
}
|
||||
|
||||
if (!winState.windows || !winState.windows[0]) {
|
||||
throw Components.Exception("Invalid window state passed", Cr.NS_ERROR_INVALID_ARG);
|
||||
}
|
||||
|
||||
let state = {windows: [winState.windows[0]]};
|
||||
this.restoreWindow(aWindow, state, {overwriteTabs: aOverwrite});
|
||||
},
|
||||
|
||||
getTabState: function ssi_getTabState(aTab) {
|
||||
@ -2280,7 +2302,7 @@ let SessionStoreInternal = {
|
||||
* @param aWindow
|
||||
* Window reference
|
||||
* @param aState
|
||||
* JS object or its eval'able source
|
||||
* JS object
|
||||
* @param aOptions
|
||||
* {overwriteTabs: true} to overwrite existing tabs w/ new ones
|
||||
* {isFollowUp: true} if this is not the restoration of the 1st window
|
||||
@ -2300,17 +2322,10 @@ let SessionStoreInternal = {
|
||||
if (aWindow && (!aWindow.__SSi || !this._windows[aWindow.__SSi]))
|
||||
this.onLoad(aWindow);
|
||||
|
||||
try {
|
||||
var root = typeof aState == "string" ? JSON.parse(aState) : aState;
|
||||
if (!root.windows[0]) {
|
||||
this._sendRestoreCompletedNotifications();
|
||||
return; // nothing to restore
|
||||
}
|
||||
}
|
||||
catch (ex) { // invalid state object - don't restore anything
|
||||
debug(ex);
|
||||
var root = aState;
|
||||
if (!root.windows[0]) {
|
||||
this._sendRestoreCompletedNotifications();
|
||||
return;
|
||||
return; // nothing to restore
|
||||
}
|
||||
|
||||
TelemetryStopwatch.start("FX_SESSION_RESTORE_RESTORE_WINDOW_MS");
|
||||
|
@ -78,44 +78,38 @@ function test() {
|
||||
}
|
||||
}
|
||||
|
||||
// open a window and add the above closed window list
|
||||
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no");
|
||||
newWin.addEventListener("load", function(aEvent) {
|
||||
this.removeEventListener("load", arguments.callee, false);
|
||||
gPrefService.setIntPref("browser.sessionstore.max_windows_undo",
|
||||
test_state._closedWindows.length);
|
||||
ss.setWindowState(newWin, JSON.stringify(test_state), true);
|
||||
gPrefService.setIntPref("browser.sessionstore.max_windows_undo",
|
||||
test_state._closedWindows.length);
|
||||
ss.setBrowserState(JSON.stringify(test_state), true);
|
||||
|
||||
let closedWindows = JSON.parse(ss.getClosedWindowData());
|
||||
is(closedWindows.length, test_state._closedWindows.length,
|
||||
"Closed window list has the expected length");
|
||||
is(countByTitle(closedWindows, FORGET),
|
||||
test_state._closedWindows.length - remember_count,
|
||||
"The correct amount of windows are to be forgotten");
|
||||
is(countByTitle(closedWindows, REMEMBER), remember_count,
|
||||
"Everything is set up.");
|
||||
let closedWindows = JSON.parse(ss.getClosedWindowData());
|
||||
is(closedWindows.length, test_state._closedWindows.length,
|
||||
"Closed window list has the expected length");
|
||||
is(countByTitle(closedWindows, FORGET),
|
||||
test_state._closedWindows.length - remember_count,
|
||||
"The correct amount of windows are to be forgotten");
|
||||
is(countByTitle(closedWindows, REMEMBER), remember_count,
|
||||
"Everything is set up.");
|
||||
|
||||
// all of the following calls with illegal arguments should throw NS_ERROR_ILLEGAL_VALUE
|
||||
ok(testForError(function() ss.forgetClosedWindow(-1)),
|
||||
"Invalid window for forgetClosedWindow throws");
|
||||
ok(testForError(function() ss.forgetClosedWindow(test_state._closedWindows.length + 1)),
|
||||
"Invalid window for forgetClosedWindow throws");
|
||||
// all of the following calls with illegal arguments should throw NS_ERROR_ILLEGAL_VALUE
|
||||
ok(testForError(function() ss.forgetClosedWindow(-1)),
|
||||
"Invalid window for forgetClosedWindow throws");
|
||||
ok(testForError(function() ss.forgetClosedWindow(test_state._closedWindows.length + 1)),
|
||||
"Invalid window for forgetClosedWindow throws");
|
||||
|
||||
// Remove third window, then first window
|
||||
ss.forgetClosedWindow(2);
|
||||
ss.forgetClosedWindow(null);
|
||||
// Remove third window, then first window
|
||||
ss.forgetClosedWindow(2);
|
||||
ss.forgetClosedWindow(null);
|
||||
|
||||
closedWindows = JSON.parse(ss.getClosedWindowData());
|
||||
is(closedWindows.length, remember_count,
|
||||
"The correct amount of windows were removed");
|
||||
is(countByTitle(closedWindows, FORGET), 0,
|
||||
"All windows specifically forgotten were indeed removed");
|
||||
is(countByTitle(closedWindows, REMEMBER), remember_count,
|
||||
"... and windows not specifically forgetten weren't.");
|
||||
closedWindows = JSON.parse(ss.getClosedWindowData());
|
||||
is(closedWindows.length, remember_count,
|
||||
"The correct amount of windows were removed");
|
||||
is(countByTitle(closedWindows, FORGET), 0,
|
||||
"All windows specifically forgotten were indeed removed");
|
||||
is(countByTitle(closedWindows, REMEMBER), remember_count,
|
||||
"... and windows not specifically forgetten weren't.");
|
||||
|
||||
// clean up
|
||||
newWin.close();
|
||||
gPrefService.clearUserPref("browser.sessionstore.max_windows_undo");
|
||||
finish();
|
||||
}, false);
|
||||
// clean up
|
||||
gPrefService.clearUserPref("browser.sessionstore.max_windows_undo");
|
||||
finish();
|
||||
}
|
||||
|
@ -686,9 +686,9 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, {
|
||||
// The container is not empty and an actual item was selected.
|
||||
DebuggerView.setEditorLocation(sourceItem.value);
|
||||
|
||||
// Set window title.
|
||||
let script = sourceItem.value.split(" -> ").pop();
|
||||
document.title = L10N.getFormatStr("DebuggerWindowScriptTitle", script);
|
||||
// Set window title. No need to split the url by " -> " here, because it was
|
||||
// already sanitized when the source was added.
|
||||
document.title = L10N.getFormatStr("DebuggerWindowScriptTitle", sourceItem.value);
|
||||
|
||||
DebuggerView.maybeShowBlackBoxMessage();
|
||||
this.updateToolbarButtonsState();
|
||||
@ -1085,38 +1085,14 @@ let SourceUtils = {
|
||||
|
||||
try {
|
||||
// Use an nsIURL to parse all the url path parts.
|
||||
var uri = Services.io.newURI(aUrl, null, null).QueryInterface(Ci.nsIURL);
|
||||
let url = aUrl.split(" -> ").pop();
|
||||
var uri = Services.io.newURI(url, null, null).QueryInterface(Ci.nsIURL);
|
||||
} catch (e) {
|
||||
// This doesn't look like a url, or nsIURL can't handle it.
|
||||
return "";
|
||||
}
|
||||
|
||||
let { scheme, directory, fileName } = uri;
|
||||
let hostPort;
|
||||
// Add-on SDK jar: URLs will cause accessing hostPort to throw.
|
||||
if (scheme != "jar") {
|
||||
hostPort = uri.hostPort;
|
||||
}
|
||||
let lastDir = directory.split("/").reverse()[1];
|
||||
let group = [];
|
||||
|
||||
// Only show interesting schemes, http is implicit.
|
||||
if (scheme != "http") {
|
||||
group.push(scheme);
|
||||
}
|
||||
// Hostnames don't always exist for files or some resource urls.
|
||||
// e.g. file://foo/bar.js or resource:///foo/bar.js don't have a host.
|
||||
if (hostPort) {
|
||||
// If the hostname is a dot-separated identifier, show the first 2 parts.
|
||||
group.push(hostPort.split(".").slice(0, 2).join("."));
|
||||
}
|
||||
// Append the last directory if the path leads to an actual file.
|
||||
// e.g. http://foo.org/bar/ should only show "foo.org", not "foo.org bar"
|
||||
if (fileName) {
|
||||
group.push(lastDir);
|
||||
}
|
||||
|
||||
let groupLabel = group.join(" ");
|
||||
let groupLabel = uri.prePath;
|
||||
let unicodeLabel = NetworkHelper.convertToUnicode(unescape(groupLabel));
|
||||
this._groupsCache.set(aUrl, unicodeLabel)
|
||||
return unicodeLabel;
|
||||
|
@ -399,14 +399,6 @@ StackFramesView.prototype = Heritage.extend(WidgetMethods, {
|
||||
initialize: function() {
|
||||
dumpn("Initializing the StackFramesView");
|
||||
|
||||
let commandset = this._commandset = document.createElement("commandset");
|
||||
let menupopup = this._menupopup = document.createElement("menupopup");
|
||||
commandset.id = "stackframesCommandset";
|
||||
menupopup.id = "stackframesMenupopup";
|
||||
|
||||
document.getElementById("debuggerPopupset").appendChild(menupopup);
|
||||
document.getElementById("debuggerCommands").appendChild(commandset);
|
||||
|
||||
this.widget = new BreadcrumbsWidget(document.getElementById("stackframes"));
|
||||
this.widget.addEventListener("select", this._onSelect, false);
|
||||
this.widget.addEventListener("scroll", this._onScroll, true);
|
||||
@ -414,6 +406,9 @@ StackFramesView.prototype = Heritage.extend(WidgetMethods, {
|
||||
|
||||
this.autoFocusOnFirstItem = false;
|
||||
this.autoFocusOnSelection = false;
|
||||
|
||||
// This view's contents are also mirrored in a different container.
|
||||
this._mirror = DebuggerView.StackFramesClassicList;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -453,24 +448,22 @@ StackFramesView.prototype = Heritage.extend(WidgetMethods, {
|
||||
this._prevBlackBoxedUrl = null;
|
||||
}
|
||||
|
||||
// Create the element node and menu entry for the stack frame item.
|
||||
// Create the element node for the stack frame item.
|
||||
let frameView = this._createFrameView.apply(this, arguments);
|
||||
let menuEntry = this._createMenuEntry.apply(this, arguments);
|
||||
|
||||
// Append a stack frame item to this container.
|
||||
this.push([frameView, aTitle, aUrl], {
|
||||
index: 0, /* specifies on which position should the item be appended */
|
||||
attachment: {
|
||||
popup: menuEntry,
|
||||
depth: aDepth
|
||||
},
|
||||
attributes: [
|
||||
["contextmenu", "stackframesMenupopup"]
|
||||
],
|
||||
// Make sure that when the stack frame item is removed, the corresponding
|
||||
// menuitem and command are also destroyed.
|
||||
// mirrored item in the classic list is also removed.
|
||||
finalize: this._onStackframeRemoved
|
||||
});
|
||||
|
||||
// Mirror this newly inserted item inside the "Call Stack" tab.
|
||||
this._mirror.addFrame(aTitle, aUrl, aLine, aDepth);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -542,65 +535,6 @@ StackFramesView.prototype = Heritage.extend(WidgetMethods, {
|
||||
return container;
|
||||
},
|
||||
|
||||
/**
|
||||
* Customization function for populating an item's context menu.
|
||||
*
|
||||
* @param string aTitle
|
||||
* The frame title to be displayed in the list.
|
||||
* @param string aUrl
|
||||
* The frame source url.
|
||||
* @param string aLine
|
||||
* The frame line number.
|
||||
* @param number aDepth
|
||||
* The frame depth in the stack.
|
||||
* @param boolean aIsBlackBoxed
|
||||
* Whether or not the frame is black boxed.
|
||||
* @return object
|
||||
* An object containing the stack frame command and menu item.
|
||||
*/
|
||||
_createMenuEntry: function(aTitle, aUrl, aLine, aDepth, aIsBlackBoxed) {
|
||||
let frameDescription = SourceUtils.trimUrlLength(
|
||||
SourceUtils.getSourceLabel(aUrl),
|
||||
STACK_FRAMES_POPUP_SOURCE_URL_MAX_LENGTH,
|
||||
STACK_FRAMES_POPUP_SOURCE_URL_TRIM_SECTION) +
|
||||
SEARCH_LINE_FLAG + aLine;
|
||||
|
||||
let prefix = "sf-cMenu-"; // "stackframes context menu"
|
||||
let commandId = prefix + aDepth + "-" + "-command";
|
||||
let menuitemId = prefix + aDepth + "-" + "-menuitem";
|
||||
|
||||
let command = document.createElement("command");
|
||||
command.id = commandId;
|
||||
command.addEventListener("command", () => this.selectedDepth = aDepth, false);
|
||||
|
||||
let menuitem = document.createElement("menuitem");
|
||||
menuitem.id = menuitemId;
|
||||
menuitem.className = "dbg-stackframe-menuitem";
|
||||
menuitem.setAttribute("type", "checkbox");
|
||||
menuitem.setAttribute("command", commandId);
|
||||
menuitem.setAttribute("tooltiptext", aUrl);
|
||||
|
||||
let labelNode = document.createElement("label");
|
||||
labelNode.className = "plain dbg-stackframe-menuitem-title";
|
||||
labelNode.setAttribute("value", aTitle);
|
||||
labelNode.setAttribute("flex", "1");
|
||||
|
||||
let descriptionNode = document.createElement("label");
|
||||
descriptionNode.className = "plain dbg-stackframe-menuitem-details";
|
||||
descriptionNode.setAttribute("value", frameDescription);
|
||||
|
||||
menuitem.appendChild(labelNode);
|
||||
menuitem.appendChild(descriptionNode);
|
||||
|
||||
this._commandset.appendChild(command);
|
||||
this._menupopup.appendChild(menuitem);
|
||||
|
||||
return {
|
||||
command: command,
|
||||
menuitem: menuitem
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Function called each time a stack frame item is removed.
|
||||
*
|
||||
@ -610,10 +544,9 @@ StackFramesView.prototype = Heritage.extend(WidgetMethods, {
|
||||
_onStackframeRemoved: function(aItem) {
|
||||
dumpn("Finalizing stackframe item: " + aItem);
|
||||
|
||||
// Destroy the context menu item for the stack frame.
|
||||
let contextItem = aItem.attachment.popup;
|
||||
contextItem.command.remove();
|
||||
contextItem.menuitem.remove();
|
||||
// Remove the mirrored item in the classic list.
|
||||
let depth = aItem.attachment.depth;
|
||||
this._mirror.remove(this._mirror.getItemForAttachment(e => e.depth == depth));
|
||||
|
||||
// Forget the previously blackboxed stack frame url.
|
||||
this._prevBlackBoxedUrl = null;
|
||||
@ -626,17 +559,13 @@ StackFramesView.prototype = Heritage.extend(WidgetMethods, {
|
||||
let stackframeItem = this.selectedItem;
|
||||
if (stackframeItem) {
|
||||
// The container is not empty and an actual item was selected.
|
||||
DebuggerController.StackFrames.selectFrame(stackframeItem.attachment.depth);
|
||||
let depth = stackframeItem.attachment.depth;
|
||||
DebuggerController.StackFrames.selectFrame(depth);
|
||||
|
||||
// Update the context menu to show the currently selected stackframe item
|
||||
// as a checked entry.
|
||||
for (let otherItem of this) {
|
||||
if (otherItem != stackframeItem) {
|
||||
otherItem.attachment.popup.menuitem.removeAttribute("checked");
|
||||
} else {
|
||||
otherItem.attachment.popup.menuitem.setAttribute("checked", "");
|
||||
}
|
||||
}
|
||||
// Mirror the selected item in the classic list.
|
||||
this.suppressSelectionEvents = true;
|
||||
this._mirror.selectedItem = e => e.attachment.depth == depth;
|
||||
this.suppressSelectionEvents = false;
|
||||
}
|
||||
},
|
||||
|
||||
@ -673,11 +602,142 @@ StackFramesView.prototype = Heritage.extend(WidgetMethods, {
|
||||
}
|
||||
},
|
||||
|
||||
_commandset: null,
|
||||
_menupopup: null,
|
||||
_mirror: null,
|
||||
_prevBlackBoxedUrl: null
|
||||
});
|
||||
|
||||
/*
|
||||
* Functions handling the stackframes classic list UI.
|
||||
* Controlled by the DebuggerView.StackFrames isntance.
|
||||
*/
|
||||
function StackFramesClassicListView() {
|
||||
dumpn("StackFramesClassicListView was instantiated");
|
||||
|
||||
this._onSelect = this._onSelect.bind(this);
|
||||
}
|
||||
|
||||
StackFramesClassicListView.prototype = Heritage.extend(WidgetMethods, {
|
||||
/**
|
||||
* Initialization function, called when the debugger is started.
|
||||
*/
|
||||
initialize: function() {
|
||||
dumpn("Initializing the StackFramesClassicListView");
|
||||
|
||||
this.widget = new SideMenuWidget(document.getElementById("callstack-list"), {
|
||||
theme: "light"
|
||||
});
|
||||
this.widget.addEventListener("select", this._onSelect, false);
|
||||
|
||||
this.emptyText = L10N.getStr("noStackFramesText");
|
||||
this.autoFocusOnFirstItem = false;
|
||||
this.autoFocusOnSelection = false;
|
||||
|
||||
// This view's contents are also mirrored in a different container.
|
||||
this._mirror = DebuggerView.StackFrames;
|
||||
|
||||
// Show an empty label by default.
|
||||
this.empty();
|
||||
},
|
||||
|
||||
/**
|
||||
* Destruction function, called when the debugger is closed.
|
||||
*/
|
||||
destroy: function() {
|
||||
dumpn("Destroying the StackFramesClassicListView");
|
||||
|
||||
this.widget.removeEventListener("select", this._onSelect, false);
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a frame in this stackframes container.
|
||||
*
|
||||
* @param string aTitle
|
||||
* The frame title (function name).
|
||||
* @param string aUrl
|
||||
* The frame source url.
|
||||
* @param string aLine
|
||||
* The frame line number.
|
||||
* @param number aDepth
|
||||
* The frame depth in the stack.
|
||||
*/
|
||||
addFrame: function(aTitle, aUrl, aLine, aDepth) {
|
||||
// Create the element node for the stack frame item.
|
||||
let frameView = this._createFrameView.apply(this, arguments);
|
||||
|
||||
// Append a stack frame item to this container.
|
||||
this.push([frameView, aUrl], {
|
||||
attachment: {
|
||||
depth: aDepth
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Customization function for creating an item's UI.
|
||||
*
|
||||
* @param string aTitle
|
||||
* The frame title to be displayed in the list.
|
||||
* @param string aUrl
|
||||
* The frame source url.
|
||||
* @param string aLine
|
||||
* The frame line number.
|
||||
* @param number aDepth
|
||||
* The frame depth in the stack.
|
||||
* @return nsIDOMNode
|
||||
* The stack frame view.
|
||||
*/
|
||||
_createFrameView: function(aTitle, aUrl, aLine, aDepth) {
|
||||
let container = document.createElement("hbox");
|
||||
container.id = "classic-stackframe-" + aDepth;
|
||||
container.className = "dbg-classic-stackframe";
|
||||
container.setAttribute("flex", "1");
|
||||
|
||||
let frameTitleNode = document.createElement("label");
|
||||
frameTitleNode.className = "plain dbg-classic-stackframe-title";
|
||||
frameTitleNode.setAttribute("value", aTitle);
|
||||
frameTitleNode.setAttribute("crop", "center");
|
||||
|
||||
let frameDetailsNode = document.createElement("hbox");
|
||||
frameDetailsNode.className = "plain dbg-classic-stackframe-details";
|
||||
|
||||
let frameUrlNode = document.createElement("label");
|
||||
frameUrlNode.className = "plain dbg-classic-stackframe-details-url";
|
||||
frameUrlNode.setAttribute("value", SourceUtils.getSourceLabel(aUrl));
|
||||
frameUrlNode.setAttribute("crop", "center");
|
||||
frameDetailsNode.appendChild(frameUrlNode);
|
||||
|
||||
let frameDetailsSeparator = document.createElement("label");
|
||||
frameDetailsSeparator.className = "plain dbg-classic-stackframe-details-sep";
|
||||
frameDetailsSeparator.setAttribute("value", SEARCH_LINE_FLAG);
|
||||
frameDetailsNode.appendChild(frameDetailsSeparator);
|
||||
|
||||
let frameLineNode = document.createElement("label");
|
||||
frameLineNode.className = "plain dbg-classic-stackframe-details-line";
|
||||
frameLineNode.setAttribute("value", aLine);
|
||||
frameDetailsNode.appendChild(frameLineNode);
|
||||
|
||||
container.appendChild(frameTitleNode);
|
||||
container.appendChild(frameDetailsNode);
|
||||
|
||||
return container;
|
||||
},
|
||||
|
||||
/**
|
||||
* The select listener for the stackframes container.
|
||||
*/
|
||||
_onSelect: function(e) {
|
||||
let stackframeItem = this.selectedItem;
|
||||
if (stackframeItem) {
|
||||
// The container is not empty and an actual item was selected.
|
||||
// Mirror the selected item in the breadcrumbs list.
|
||||
let depth = stackframeItem.attachment.depth;
|
||||
this._mirror.selectedItem = e => e.attachment.depth == depth;
|
||||
}
|
||||
},
|
||||
|
||||
_mirror: null
|
||||
});
|
||||
|
||||
/**
|
||||
* Functions handling the filtering UI.
|
||||
*/
|
||||
@ -1533,3 +1593,4 @@ DebuggerView.FilteredSources = new FilteredSourcesView();
|
||||
DebuggerView.FilteredFunctions = new FilteredFunctionsView();
|
||||
DebuggerView.ChromeGlobals = new ChromeGlobalsView();
|
||||
DebuggerView.StackFrames = new StackFramesView();
|
||||
DebuggerView.StackFramesClassicList = new StackFramesClassicListView();
|
||||
|
@ -9,8 +9,6 @@ const SOURCE_SYNTAX_HIGHLIGHT_MAX_FILE_SIZE = 1048576; // 1 MB in bytes
|
||||
const SOURCE_URL_DEFAULT_MAX_LENGTH = 64; // chars
|
||||
const STACK_FRAMES_SOURCE_URL_MAX_LENGTH = 15; // chars
|
||||
const STACK_FRAMES_SOURCE_URL_TRIM_SECTION = "center";
|
||||
const STACK_FRAMES_POPUP_SOURCE_URL_MAX_LENGTH = 32; // chars
|
||||
const STACK_FRAMES_POPUP_SOURCE_URL_TRIM_SECTION = "center";
|
||||
const STACK_FRAMES_SCROLL_DELAY = 100; // ms
|
||||
const BREAKPOINT_LINE_TOOLTIP_MAX_LENGTH = 1000; // chars
|
||||
const BREAKPOINT_CONDITIONAL_POPUP_POSITION = "before_start";
|
||||
@ -59,6 +57,7 @@ let DebuggerView = {
|
||||
this.FilteredFunctions.initialize();
|
||||
this.ChromeGlobals.initialize();
|
||||
this.StackFrames.initialize();
|
||||
this.StackFramesClassicList.initialize();
|
||||
this.Sources.initialize();
|
||||
this.VariableBubble.initialize();
|
||||
this.WatchExpressions.initialize();
|
||||
@ -93,6 +92,7 @@ let DebuggerView = {
|
||||
this.FilteredFunctions.destroy();
|
||||
this.ChromeGlobals.destroy();
|
||||
this.StackFrames.destroy();
|
||||
this.StackFramesClassicList.destroy();
|
||||
this.Sources.destroy();
|
||||
this.VariableBubble.destroy();
|
||||
this.WatchExpressions.destroy();
|
||||
@ -531,7 +531,7 @@ let DebuggerView = {
|
||||
animated: true,
|
||||
delayed: true,
|
||||
callback: aCallback
|
||||
}, 0);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -4,14 +4,9 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Sources search view */
|
||||
|
||||
#globalsearch {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/* Instruments pane view (watch expressions, variables, events...) */
|
||||
/* Side pane views */
|
||||
|
||||
#sources-pane > tabpanels > tabpanel,
|
||||
#instruments-pane > tabpanels > tabpanel {
|
||||
-moz-box-orient: vertical;
|
||||
}
|
||||
@ -21,6 +16,10 @@
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
#globalsearch {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/* Toolbar controls */
|
||||
|
||||
.devtools-toolbarbutton:not([label]) > .toolbarbutton-text {
|
||||
|
@ -321,23 +321,35 @@
|
||||
<scrollbox id="globalsearch" orient="vertical" hidden="true"/>
|
||||
<splitter class="devtools-horizontal-splitter" hidden="true"/>
|
||||
<hbox id="debugger-widgets" flex="1">
|
||||
<vbox id="sources-pane">
|
||||
<vbox id="sources" flex="1"/>
|
||||
<toolbar id="sources-toolbar" class="devtools-toolbar">
|
||||
<hbox id="sources-controls">
|
||||
<toolbarbutton id="black-box"
|
||||
tooltiptext="&debuggerUI.sources.blackBoxTooltip;"
|
||||
command="blackBoxCommand"
|
||||
class="devtools-toolbarbutton"/>
|
||||
<toolbarbutton id="pretty-print"
|
||||
label="{}"
|
||||
tooltiptext="&debuggerUI.sources.prettyPrint;"
|
||||
class="devtools-toolbarbutton devtools-monospace"
|
||||
command="prettyPrintCommand"
|
||||
hidden="true"/>
|
||||
</hbox>
|
||||
</toolbar>
|
||||
</vbox>
|
||||
<tabbox id="sources-pane"
|
||||
class="devtools-sidebar-tabs">
|
||||
<tabs>
|
||||
<tab id="sources-tab" label="&debuggerUI.tabs.sources;"/>
|
||||
<tab id="callstack-tab" label="&debuggerUI.tabs.callstack;"/>
|
||||
</tabs>
|
||||
<tabpanels flex="1">
|
||||
<tabpanel id="sources-tabpanel">
|
||||
<vbox id="sources" flex="1"/>
|
||||
<toolbar id="sources-toolbar" class="devtools-toolbar">
|
||||
<hbox id="sources-controls">
|
||||
<toolbarbutton id="black-box"
|
||||
tooltiptext="&debuggerUI.sources.blackBoxTooltip;"
|
||||
command="blackBoxCommand"
|
||||
class="devtools-toolbarbutton"/>
|
||||
<toolbarbutton id="pretty-print"
|
||||
label="{}"
|
||||
tooltiptext="&debuggerUI.sources.prettyPrint;"
|
||||
class="devtools-toolbarbutton devtools-monospace"
|
||||
command="prettyPrintCommand"
|
||||
hidden="true"/>
|
||||
</hbox>
|
||||
</toolbar>
|
||||
</tabpanel>
|
||||
<tabpanel id="callstack-tabpanel">
|
||||
<vbox id="callstack-list" flex="1"/>
|
||||
</tabpanel>
|
||||
</tabpanels>
|
||||
</tabbox>
|
||||
<splitter id="sources-and-editor-splitter"
|
||||
class="devtools-side-splitter"/>
|
||||
<deck id="editor-deck" flex="4">
|
||||
@ -367,12 +379,12 @@
|
||||
<tab id="events-tab" label="&debuggerUI.tabs.events;"/>
|
||||
</tabs>
|
||||
<tabpanels flex="1">
|
||||
<tabpanel id="variables-tabpanel">
|
||||
<tabpanel id="variables-tabpanel" class="theme-body">
|
||||
<vbox id="expressions"/>
|
||||
<splitter class="devtools-horizontal-splitter"/>
|
||||
<vbox id="variables" flex="1"/>
|
||||
</tabpanel>
|
||||
<tabpanel id="events-tabpanel">
|
||||
<tabpanel id="events-tabpanel" class="theme-body">
|
||||
<vbox id="event-listeners" flex="1"/>
|
||||
</tabpanel>
|
||||
</tabpanels>
|
||||
|
@ -48,34 +48,40 @@ function test() {
|
||||
}
|
||||
|
||||
function checkNavigationWhileFocused() {
|
||||
let deferred = promise.defer();
|
||||
return Task.spawn(function() {
|
||||
yield promise.all([
|
||||
waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_SCOPES),
|
||||
EventUtils.sendKey("UP", gDebugger)
|
||||
]);
|
||||
checkState({ frame: 2, source: 1, line: 6 });
|
||||
|
||||
EventUtils.sendKey("UP", gDebugger);
|
||||
checkState({ frame: 2, source: 1, line: 6 });
|
||||
|
||||
waitForSourceAndCaret(gPanel, "-01.js", 5).then(() => {
|
||||
yield promise.all([
|
||||
waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_SCOPES),
|
||||
waitForSourceAndCaret(gPanel, "-01.js", 5),
|
||||
EventUtils.sendKey("UP", gDebugger)
|
||||
]);
|
||||
checkState({ frame: 1, source: 0, line: 5 });
|
||||
|
||||
EventUtils.sendKey("UP", gDebugger);
|
||||
yield promise.all([
|
||||
waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_SCOPES),
|
||||
EventUtils.sendKey("UP", gDebugger)
|
||||
]);
|
||||
checkState({ frame: 0, source: 0, line: 5 });
|
||||
|
||||
waitForSourceAndCaret(gPanel, "-02.js", 6).then(() => {
|
||||
checkState({ frame: 3, source: 1, line: 6 });
|
||||
|
||||
waitForSourceAndCaret(gPanel, "-01.js", 5).then(() => {
|
||||
checkState({ frame: 0, source: 0, line: 5 });
|
||||
deferred.resolve();
|
||||
});
|
||||
yield promise.all([
|
||||
waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_SCOPES),
|
||||
waitForSourceAndCaret(gPanel, "-02.js", 6),
|
||||
EventUtils.sendKey("END", gDebugger)
|
||||
]);
|
||||
checkState({ frame: 3, source: 1, line: 6 });
|
||||
|
||||
yield promise.all([
|
||||
waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_SCOPES),
|
||||
waitForSourceAndCaret(gPanel, "-01.js", 5),
|
||||
EventUtils.sendKey("HOME", gDebugger)
|
||||
});
|
||||
|
||||
EventUtils.sendKey("END", gDebugger)
|
||||
]);
|
||||
checkState({ frame: 0, source: 0, line: 5 });
|
||||
});
|
||||
|
||||
EventUtils.sendKey("UP", gDebugger)
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function checkState({ frame, source, line }) {
|
||||
|
@ -46,7 +46,7 @@ function performTest() {
|
||||
|
||||
is(gSources.widget.getAttribute("label"), "doc_recursion-stack.html",
|
||||
"The sources widget should have a correct label attribute.");
|
||||
is(gSources.widget.getAttribute("tooltiptext"), "example.com test",
|
||||
is(gSources.widget.getAttribute("tooltiptext"), "http://example.com",
|
||||
"The sources widget should have a correct tooltip text attribute.");
|
||||
|
||||
is(gDebugger.document.querySelectorAll("#sources .side-menu-widget-empty-notice-container").length, 0,
|
||||
|
@ -48,7 +48,7 @@ function testLocationChange() {
|
||||
|
||||
is(gSources.widget.getAttribute("label"), "doc_inline-debugger-statement.html",
|
||||
"The sources widget should have a correct label attribute.");
|
||||
is(gSources.widget.getAttribute("tooltiptext"), "example.com test",
|
||||
is(gSources.widget.getAttribute("tooltiptext"), "http://example.com",
|
||||
"The sources widget should have a correct tooltip text attribute.");
|
||||
|
||||
is(gDebugger.document.querySelectorAll("#sources .side-menu-widget-empty-notice-container").length, 0,
|
||||
|
@ -8,7 +8,7 @@
|
||||
const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html";
|
||||
|
||||
let gTab, gDebuggee, gPanel, gDebugger;
|
||||
let gFrames;
|
||||
let gFrames, gClassicFrames;
|
||||
|
||||
function test() {
|
||||
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
|
||||
@ -17,6 +17,7 @@ function test() {
|
||||
gPanel = aPanel;
|
||||
gDebugger = gPanel.panelWin;
|
||||
gFrames = gDebugger.DebuggerView.StackFrames;
|
||||
gClassicFrames = gDebugger.DebuggerView.StackFramesClassicList;
|
||||
|
||||
waitForSourceAndCaretAndScopes(gPanel, ".html", 14).then(performTest);
|
||||
gDebuggee.simpleCall();
|
||||
@ -28,6 +29,8 @@ function performTest() {
|
||||
"Should only be getting stack frames while paused.");
|
||||
is(gFrames.itemCount, 1,
|
||||
"Should have only one frame.");
|
||||
is(gClassicFrames.itemCount, 1,
|
||||
"Should also have only one frame in the mirrored view.");
|
||||
|
||||
resumeDebuggerThenCloseAndFinish(gPanel);
|
||||
}
|
||||
@ -38,4 +41,5 @@ registerCleanupFunction(function() {
|
||||
gPanel = null;
|
||||
gDebugger = null;
|
||||
gFrames = null;
|
||||
gClassicFrames = null;
|
||||
});
|
||||
|
@ -8,7 +8,7 @@
|
||||
const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html";
|
||||
|
||||
let gTab, gDebuggee, gPanel, gDebugger;
|
||||
let gFrames;
|
||||
let gFrames, gClassicFrames;
|
||||
|
||||
function test() {
|
||||
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
|
||||
@ -17,6 +17,7 @@ function test() {
|
||||
gPanel = aPanel;
|
||||
gDebugger = gPanel.panelWin;
|
||||
gFrames = gDebugger.DebuggerView.StackFrames;
|
||||
gClassicFrames = gDebugger.DebuggerView.StackFramesClassicList;
|
||||
|
||||
waitForSourceAndCaretAndScopes(gPanel, ".html", 18).then(performTest);
|
||||
gDebuggee.evalCall();
|
||||
@ -28,21 +29,32 @@ function performTest() {
|
||||
"Should only be getting stack frames while paused.");
|
||||
is(gFrames.itemCount, 2,
|
||||
"Should have two frames.");
|
||||
is(gClassicFrames.itemCount, 2,
|
||||
"Should also have only two in the mirrored view.");
|
||||
|
||||
is(gFrames.getItemAtIndex(0).value,
|
||||
"evalCall", "Oldest frame name should be correct.");
|
||||
is(gFrames.getItemAtIndex(0).description,
|
||||
TAB_URL, "Oldest frame url should be correct.");
|
||||
is(gClassicFrames.getItemAtIndex(0).value,
|
||||
TAB_URL, "Oldest frame name is mirrored correctly.");
|
||||
|
||||
is(gFrames.getItemAtIndex(1).value,
|
||||
"(eval)", "Newest frame name should be correct.");
|
||||
is(gFrames.getItemAtIndex(1).description,
|
||||
TAB_URL, "Newest frame url should be correct.");
|
||||
is(gClassicFrames.getItemAtIndex(1).value,
|
||||
TAB_URL, "Newest frame name is mirrored correctly.");
|
||||
|
||||
is(gFrames.selectedIndex, 1,
|
||||
"Newest frame should be selected by default.");
|
||||
is(gClassicFrames.selectedIndex, 0,
|
||||
"Newest frame should be selected by default in the mirrored view.");
|
||||
|
||||
isnot(gFrames.selectedIndex, 0,
|
||||
"Oldest frame should not be selected.");
|
||||
isnot(gClassicFrames.selectedIndex, 1,
|
||||
"Oldest frame should not be selected in the mirrored view.");
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" },
|
||||
gFrames.getItemAtIndex(0).target,
|
||||
@ -50,8 +62,13 @@ function performTest() {
|
||||
|
||||
isnot(gFrames.selectedIndex, 1,
|
||||
"Newest frame should not be selected after click.");
|
||||
isnot(gClassicFrames.selectedIndex, 0,
|
||||
"Newest frame in the mirrored view should not be selected.");
|
||||
|
||||
is(gFrames.selectedIndex, 0,
|
||||
"Oldest frame should be selected after click.");
|
||||
is(gClassicFrames.selectedIndex, 1,
|
||||
"Oldest frame in the mirrored view should be selected.");
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" },
|
||||
gFrames.getItemAtIndex(1).target.querySelector(".dbg-stackframe-title"),
|
||||
@ -59,8 +76,13 @@ function performTest() {
|
||||
|
||||
is(gFrames.selectedIndex, 1,
|
||||
"Newest frame should be selected after click inside the newest frame.");
|
||||
is(gClassicFrames.selectedIndex, 0,
|
||||
"Newest frame in the mirrored view should be selected.");
|
||||
|
||||
isnot(gFrames.selectedIndex, 0,
|
||||
"Oldest frame should not be selected after click inside the newest frame.");
|
||||
isnot(gClassicFrames.selectedIndex, 1,
|
||||
"Oldest frame in the mirrored view should not be selected.");
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" },
|
||||
gFrames.getItemAtIndex(0).target.querySelector(".dbg-stackframe-details"),
|
||||
@ -68,8 +90,13 @@ function performTest() {
|
||||
|
||||
isnot(gFrames.selectedIndex, 1,
|
||||
"Newest frame should not be selected after click inside the oldest frame.");
|
||||
isnot(gClassicFrames.selectedIndex, 0,
|
||||
"Newest frame in the mirrored view should not be selected.");
|
||||
|
||||
is(gFrames.selectedIndex, 0,
|
||||
"Oldest frame should be selected after click inside the oldest frame.");
|
||||
is(gClassicFrames.selectedIndex, 1,
|
||||
"Oldest frame in the mirrored view should be selected.");
|
||||
|
||||
resumeDebuggerThenCloseAndFinish(gPanel);
|
||||
}
|
||||
@ -80,4 +107,5 @@ registerCleanupFunction(function() {
|
||||
gPanel = null;
|
||||
gDebugger = null;
|
||||
gFrames = null;
|
||||
gClassicFrames = null;
|
||||
});
|
||||
|
@ -8,7 +8,7 @@
|
||||
const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html";
|
||||
|
||||
let gTab, gDebuggee, gPanel, gDebugger;
|
||||
let gFrames, gFramesScrollingInterval;
|
||||
let gFrames, gClassicFrames, gFramesScrollingInterval;
|
||||
|
||||
function test() {
|
||||
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
|
||||
@ -17,6 +17,7 @@ function test() {
|
||||
gPanel = aPanel;
|
||||
gDebugger = gPanel.panelWin;
|
||||
gFrames = gDebugger.DebuggerView.StackFrames;
|
||||
gClassicFrames = gDebugger.DebuggerView.StackFramesClassicList;
|
||||
|
||||
waitForSourceAndCaretAndScopes(gPanel, ".html", 26).then(performTest);
|
||||
|
||||
@ -30,14 +31,20 @@ function performTest() {
|
||||
"Should only be getting stack frames while paused.");
|
||||
is(gFrames.itemCount, gDebugger.gCallStackPageSize,
|
||||
"Should have only the max limit of frames.");
|
||||
is(gClassicFrames.itemCount, gDebugger.gCallStackPageSize,
|
||||
"Should have only the max limit of frames in the mirrored view as well.")
|
||||
|
||||
gDebugger.gThreadClient.addOneTimeListener("framesadded", () => {
|
||||
is(gFrames.itemCount, gDebugger.gCallStackPageSize * 2,
|
||||
"Should now have twice the max limit of frames.");
|
||||
is(gClassicFrames.itemCount, gDebugger.gCallStackPageSize * 2,
|
||||
"Should now have twice the max limit of frames in the mirrored view as well.");
|
||||
|
||||
gDebugger.gThreadClient.addOneTimeListener("framesadded", () => {
|
||||
is(gFrames.itemCount, gDebuggee.gRecurseLimit,
|
||||
"Should have reached the recurse limit.");
|
||||
is(gClassicFrames.itemCount, gDebuggee.gRecurseLimit,
|
||||
"Should have reached the recurse limit in the mirrored view as well.");
|
||||
|
||||
gDebugger.gThreadClient.resume(() => {
|
||||
window.clearInterval(gFramesScrollingInterval);
|
||||
@ -60,4 +67,5 @@ registerCleanupFunction(function() {
|
||||
gPanel = null;
|
||||
gDebugger = null;
|
||||
gFrames = null;
|
||||
gClassicFrames = null;
|
||||
});
|
||||
|
@ -8,7 +8,7 @@
|
||||
const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html";
|
||||
|
||||
let gTab, gDebuggee, gPanel, gDebugger;
|
||||
let gFrames;
|
||||
let gFrames, gClassicFrames;
|
||||
|
||||
function test() {
|
||||
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
|
||||
@ -17,6 +17,7 @@ function test() {
|
||||
gPanel = aPanel;
|
||||
gDebugger = gPanel.panelWin;
|
||||
gFrames = gDebugger.DebuggerView.StackFrames;
|
||||
gClassicFrames = gDebugger.DebuggerView.StackFramesClassicList;
|
||||
|
||||
waitForSourceAndCaretAndScopes(gPanel, ".html", 18).then(performTest);
|
||||
gDebuggee.evalCall();
|
||||
@ -28,10 +29,14 @@ function performTest() {
|
||||
"Should only be getting stack frames while paused.");
|
||||
is(gFrames.itemCount, 2,
|
||||
"Should have two frames.");
|
||||
is(gClassicFrames.itemCount, 2,
|
||||
"Should also have two frames in the mirrored view.");
|
||||
|
||||
gDebugger.once(gDebugger.EVENTS.AFTER_FRAMES_CLEARED, () => {
|
||||
is(gFrames.itemCount, 0,
|
||||
"Should have no frames after resume.");
|
||||
is(gClassicFrames.itemCount, 0,
|
||||
"Should also have no frames in the mirrored view after resume.");
|
||||
|
||||
closeDebuggerAndFinish(gPanel);
|
||||
}, true);
|
||||
@ -45,4 +50,5 @@ registerCleanupFunction(function() {
|
||||
gPanel = null;
|
||||
gDebugger = null;
|
||||
gFrames = null;
|
||||
gClassicFrames = null;
|
||||
});
|
||||
|
@ -9,7 +9,7 @@
|
||||
const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html";
|
||||
|
||||
let gTab, gDebuggee, gPanel, gDebugger;
|
||||
let gEditor, gSources, gFrames;
|
||||
let gEditor, gSources, gFrames, gClassicFrames;
|
||||
|
||||
function test() {
|
||||
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
|
||||
@ -20,6 +20,7 @@ function test() {
|
||||
gEditor = gDebugger.DebuggerView.editor;
|
||||
gSources = gDebugger.DebuggerView.Sources;
|
||||
gFrames = gDebugger.DebuggerView.StackFrames;
|
||||
gClassicFrames = gDebugger.DebuggerView.StackFramesClassicList;
|
||||
|
||||
waitForSourceAndCaretAndScopes(gPanel, "-02.js", 6)
|
||||
.then(initialChecks)
|
||||
@ -40,6 +41,8 @@ function initialChecks() {
|
||||
"Should only be getting stack frames while paused.");
|
||||
is(gFrames.itemCount, 4,
|
||||
"Should have four frames.");
|
||||
is(gClassicFrames.itemCount, 4,
|
||||
"Should also have four frames in the mirrored view.");
|
||||
}
|
||||
|
||||
function testNewestTwoFrames() {
|
||||
@ -47,6 +50,8 @@ function testNewestTwoFrames() {
|
||||
|
||||
is(gFrames.selectedIndex, 3,
|
||||
"Newest frame should be selected by default.");
|
||||
is(gClassicFrames.selectedIndex, 0,
|
||||
"Newest frame should be selected in the mirrored view as well.");
|
||||
is(gSources.selectedIndex, 1,
|
||||
"The second source is selected in the widget.");
|
||||
ok(isCaretPos(gPanel, 6),
|
||||
@ -63,6 +68,8 @@ function testNewestTwoFrames() {
|
||||
|
||||
is(gFrames.selectedIndex, 2,
|
||||
"Third frame should be selected after click.");
|
||||
is(gClassicFrames.selectedIndex, 1,
|
||||
"Third frame should be selected in the mirrored view as well.");
|
||||
is(gSources.selectedIndex, 1,
|
||||
"The second source is still selected in the widget.");
|
||||
ok(isCaretPos(gPanel, 6),
|
||||
@ -83,9 +90,11 @@ function testNewestTwoFrames() {
|
||||
function testOldestTwoFrames() {
|
||||
let deferred = promise.defer();
|
||||
|
||||
waitForSourceAndCaret(gPanel, "-01.js", 5).then(() => {
|
||||
waitForSourceAndCaret(gPanel, "-01.js", 5).then(waitForTick).then(() => {
|
||||
is(gFrames.selectedIndex, 1,
|
||||
"Second frame should be selected after click.");
|
||||
is(gClassicFrames.selectedIndex, 2,
|
||||
"Second frame should be selected in the mirrored view as well.");
|
||||
is(gSources.selectedIndex, 0,
|
||||
"The first source is now selected in the widget.");
|
||||
ok(isCaretPos(gPanel, 5),
|
||||
@ -102,6 +111,8 @@ function testOldestTwoFrames() {
|
||||
|
||||
is(gFrames.selectedIndex, 0,
|
||||
"Oldest frame should be selected after click.");
|
||||
is(gClassicFrames.selectedIndex, 3,
|
||||
"Oldest frame should be selected in the mirrored view as well.");
|
||||
is(gSources.selectedIndex, 0,
|
||||
"The first source is still selected in the widget.");
|
||||
ok(isCaretPos(gPanel, 5),
|
||||
@ -118,7 +129,7 @@ function testOldestTwoFrames() {
|
||||
});
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" },
|
||||
gFrames.getItemAtIndex(1).target,
|
||||
gDebugger.document.querySelector("#stackframe-2"),
|
||||
gDebugger);
|
||||
|
||||
return deferred.promise;
|
||||
@ -130,6 +141,8 @@ function testAfterResume() {
|
||||
gDebugger.once(gDebugger.EVENTS.AFTER_FRAMES_CLEARED, () => {
|
||||
is(gFrames.itemCount, 0,
|
||||
"Should have no frames after resume.");
|
||||
is(gClassicFrames.itemCount, 0,
|
||||
"Should have no frames in the mirrored view as well.");
|
||||
ok(isCaretPos(gPanel, 5),
|
||||
"Editor caret location is correct after resume.");
|
||||
is(gEditor.getDebugLocation(), null,
|
||||
@ -150,5 +163,6 @@ registerCleanupFunction(function() {
|
||||
gDebugger = null;
|
||||
gEditor = null;
|
||||
gFrames = null;
|
||||
gClassicFrames = null;
|
||||
});
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html";
|
||||
|
||||
let gTab, gDebuggee, gPanel, gDebugger;
|
||||
let gEditor, gSources, gFrames;
|
||||
let gEditor, gSources, gFrames, gClassicFrames;
|
||||
|
||||
function test() {
|
||||
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
|
||||
@ -20,6 +20,7 @@ function test() {
|
||||
gEditor = gDebugger.DebuggerView.editor;
|
||||
gSources = gDebugger.DebuggerView.Sources;
|
||||
gFrames = gDebugger.DebuggerView.StackFrames;
|
||||
gClassicFrames = gDebugger.DebuggerView.StackFramesClassicList;
|
||||
|
||||
waitForSourceAndCaretAndScopes(gPanel, "-02.js", 6).then(performTest);
|
||||
gDebuggee.firstCall();
|
||||
@ -29,16 +30,20 @@ function test() {
|
||||
function performTest() {
|
||||
is(gFrames.selectedIndex, 3,
|
||||
"Newest frame should be selected by default.");
|
||||
is(gClassicFrames.selectedIndex, 0,
|
||||
"Newest frame should also be selected in the mirrored view.");
|
||||
is(gSources.selectedIndex, 1,
|
||||
"The second source is selected in the widget.");
|
||||
is(gEditor.getText().search(/firstCall/), -1,
|
||||
"The first source is not displayed.");
|
||||
is(gEditor.getText().search(/debugger/), 172,
|
||||
"The second source is displayed.")
|
||||
"The second source is displayed.");
|
||||
|
||||
waitForSourceAndCaret(gPanel, "-01.js", 6).then(() => {
|
||||
waitForSourceAndCaret(gPanel, "-01.js", 6).then(waitForTick).then(() => {
|
||||
is(gFrames.selectedIndex, 0,
|
||||
"Oldest frame should be selected after click.");
|
||||
is(gClassicFrames.selectedIndex, 3,
|
||||
"Oldest frame should also be selected in the mirrored view.");
|
||||
is(gSources.selectedIndex, 0,
|
||||
"The first source is now selected in the widget.");
|
||||
is(gEditor.getText().search(/firstCall/), 118,
|
||||
@ -46,7 +51,24 @@ function performTest() {
|
||||
is(gEditor.getText().search(/debugger/), -1,
|
||||
"The second source is not displayed.");
|
||||
|
||||
resumeDebuggerThenCloseAndFinish(gPanel);
|
||||
waitForSourceAndCaret(gPanel, "-02.js", 6).then(waitForTick).then(() => {
|
||||
is(gFrames.selectedIndex, 3,
|
||||
"Newest frame should be selected again after click.");
|
||||
is(gClassicFrames.selectedIndex, 0,
|
||||
"Newest frame should also be selected again in the mirrored view.");
|
||||
is(gSources.selectedIndex, 1,
|
||||
"The second source is selected in the widget.");
|
||||
is(gEditor.getText().search(/firstCall/), -1,
|
||||
"The first source is not displayed.");
|
||||
is(gEditor.getText().search(/debugger/), 172,
|
||||
"The second source is displayed.");
|
||||
|
||||
resumeDebuggerThenCloseAndFinish(gPanel);
|
||||
});
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" },
|
||||
gDebugger.document.querySelector("#classic-stackframe-0"),
|
||||
gDebugger);
|
||||
});
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" },
|
||||
@ -62,4 +84,5 @@ registerCleanupFunction(function() {
|
||||
gEditor = null;
|
||||
gSources = null;
|
||||
gFrames = null;
|
||||
gClassicFrames = null;
|
||||
});
|
||||
|
@ -10,7 +10,7 @@
|
||||
const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html";
|
||||
|
||||
let gTab, gDebuggee, gPanel, gDebugger;
|
||||
let gEditor, gSources, gFrames, gToolbar;
|
||||
let gEditor, gSources, gFrames, gClassicFrames, gToolbar;
|
||||
|
||||
function test() {
|
||||
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
|
||||
@ -21,6 +21,7 @@ function test() {
|
||||
gEditor = gDebugger.DebuggerView.editor;
|
||||
gSources = gDebugger.DebuggerView.Sources;
|
||||
gFrames = gDebugger.DebuggerView.StackFrames;
|
||||
gClassicFrames = gDebugger.DebuggerView.StackFramesClassicList;
|
||||
gToolbar = gDebugger.DebuggerView.Toolbar;
|
||||
|
||||
waitForSourceAndCaretAndScopes(gPanel, "-02.js", 6).then(performTest);
|
||||
@ -53,13 +54,15 @@ function performTest() {
|
||||
|
||||
function selectBottomFrame() {
|
||||
let updated = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_SCOPES);
|
||||
gFrames.selectedIndex = 0;
|
||||
gClassicFrames.selectedIndex = gClassicFrames.itemCount - 1;
|
||||
return updated.then(waitForTick);
|
||||
}
|
||||
|
||||
function testBottomFrame(debugLocation) {
|
||||
is(gFrames.selectedIndex, 0,
|
||||
"Oldest frame should be selected after click.");
|
||||
is(gClassicFrames.selectedIndex, gFrames.itemCount - 1,
|
||||
"Oldest frame should also be selected in the mirrored view.");
|
||||
is(gSources.selectedIndex, 0,
|
||||
"The first source is now selected in the widget.");
|
||||
is(gEditor.getText().search(/firstCall/), 118,
|
||||
@ -82,6 +85,8 @@ function performTest() {
|
||||
function testTopFrame(frameIndex) {
|
||||
is(gFrames.selectedIndex, frameIndex,
|
||||
"Topmost frame should be selected after click.");
|
||||
is(gClassicFrames.selectedIndex, gFrames.itemCount - frameIndex - 1,
|
||||
"Topmost frame should also be selected in the mirrored view.");
|
||||
is(gSources.selectedIndex, 1,
|
||||
"The second source is now selected in the widget.");
|
||||
is(gEditor.getText().search(/firstCall/), -1,
|
||||
@ -99,5 +104,6 @@ registerCleanupFunction(function() {
|
||||
gEditor = null;
|
||||
gSources = null;
|
||||
gFrames = null;
|
||||
gClassicFrames = null;
|
||||
gToolbar = null;
|
||||
});
|
||||
|
@ -6,7 +6,7 @@
|
||||
"use strict";
|
||||
|
||||
const { Cc, Ci, Cu, Cr } = require("chrome");
|
||||
const promise = require("sdk/core/promise");
|
||||
const promise = Cu.import("resource://gre/modules/Promise.jsm", {}).Promise;
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
const { WebGLFront } = require("devtools/server/actors/webgl");
|
||||
|
||||
|
@ -13,7 +13,7 @@ Cu.import("resource:///modules/devtools/SideMenuWidget.jsm");
|
||||
Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
|
||||
|
||||
const require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
|
||||
const promise = require("sdk/core/promise");
|
||||
const promise = Cu.import("resource://gre/modules/Promise.jsm", {}).Promise;
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
const {Tooltip} = require("devtools/shared/widgets/Tooltip");
|
||||
const Editor = require("devtools/sourceeditor/editor");
|
||||
@ -28,7 +28,13 @@ const EVENTS = {
|
||||
SOURCES_SHOWN: "ShaderEditor:SourcesShown",
|
||||
|
||||
// When a shader's source was edited and compiled via the editor.
|
||||
SHADER_COMPILED: "ShaderEditor:ShaderCompiled"
|
||||
SHADER_COMPILED: "ShaderEditor:ShaderCompiled",
|
||||
|
||||
// When the UI is reset from tab navigation
|
||||
UI_RESET: "ShaderEditor:UIReset",
|
||||
|
||||
// When the editor's error markers are all removed
|
||||
EDITOR_ERROR_MARKERS_REMOVED: "ShaderEditor:EditorCleaned"
|
||||
};
|
||||
|
||||
const STRINGS_URI = "chrome://browser/locale/devtools/shadereditor.properties"
|
||||
@ -114,15 +120,17 @@ let EventsHandler = {
|
||||
_onTabNavigated: function(event) {
|
||||
switch (event) {
|
||||
case "will-navigate": {
|
||||
// Make sure the backend is prepared to handle WebGL contexts.
|
||||
gFront.setup({ reload: false });
|
||||
Task.spawn(function() {
|
||||
// Make sure the backend is prepared to handle WebGL contexts.
|
||||
gFront.setup({ reload: false });
|
||||
|
||||
// Reset UI.
|
||||
ShadersListView.empty();
|
||||
ShadersEditorsView.setText({ vs: "", fs: "" });
|
||||
$("#reload-notice").hidden = true;
|
||||
$("#waiting-notice").hidden = false;
|
||||
$("#content").hidden = true;
|
||||
// Reset UI.
|
||||
ShadersListView.empty();
|
||||
$("#reload-notice").hidden = true;
|
||||
$("#waiting-notice").hidden = false;
|
||||
yield ShadersEditorsView.setText({ vs: "", fs: "" });
|
||||
$("#content").hidden = true;
|
||||
}).then(() => window.emit(EVENTS.UI_RESET));
|
||||
break;
|
||||
}
|
||||
case "navigate": {
|
||||
@ -272,13 +280,16 @@ let ShadersListView = Heritage.extend(WidgetMethods, {
|
||||
]);
|
||||
}
|
||||
function showSources([vertexShaderText, fragmentShaderText]) {
|
||||
ShadersEditorsView.setText({
|
||||
return ShadersEditorsView.setText({
|
||||
vs: vertexShaderText,
|
||||
fs: fragmentShaderText
|
||||
});
|
||||
}
|
||||
|
||||
getShaders().then(getSources).then(showSources).then(null, Cu.reportError);
|
||||
getShaders()
|
||||
.then(getSources)
|
||||
.then(showSources)
|
||||
.then(null, Cu.reportError);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -351,19 +362,24 @@ let ShadersEditorsView = {
|
||||
* An object containing the following properties
|
||||
* - vs: the vertex shader source code
|
||||
* - fs: the fragment shader source code
|
||||
* @return object
|
||||
* A promise resolving upon completion of text setting.
|
||||
*/
|
||||
setText: function(sources) {
|
||||
let view = this;
|
||||
function setTextAndClearHistory(editor, text) {
|
||||
editor.setText(text);
|
||||
editor.clearHistory();
|
||||
}
|
||||
|
||||
this._toggleListeners("off");
|
||||
this._getEditor("vs").then(e => setTextAndClearHistory(e, sources.vs));
|
||||
this._getEditor("fs").then(e => setTextAndClearHistory(e, sources.fs));
|
||||
this._toggleListeners("on");
|
||||
|
||||
window.emit(EVENTS.SOURCES_SHOWN, sources);
|
||||
return Task.spawn(function() {
|
||||
yield view._toggleListeners("off");
|
||||
yield promise.all([
|
||||
view._getEditor("vs").then(e => setTextAndClearHistory(e, sources.vs)),
|
||||
view._getEditor("fs").then(e => setTextAndClearHistory(e, sources.fs))
|
||||
]);
|
||||
yield view._toggleListeners("on");
|
||||
}).then(() => window.emit(EVENTS.SOURCES_SHOWN, sources));
|
||||
},
|
||||
|
||||
/**
|
||||
@ -372,10 +388,12 @@ let ShadersEditorsView = {
|
||||
* @param string type
|
||||
* Specifies for which shader type should an editor be retrieved,
|
||||
* either are "vs" for a vertex, or "fs" for a fragment shader.
|
||||
* @return object
|
||||
* Returns a promise that resolves to an editor instance
|
||||
*/
|
||||
_getEditor: function(type) {
|
||||
if ($("#content").hidden) {
|
||||
return promise.reject(null);
|
||||
return promise.reject(new Error("Shader Editor is still waiting for a WebGL context to be created."));
|
||||
}
|
||||
if (this._editorPromises.has(type)) {
|
||||
return this._editorPromises.get(type);
|
||||
@ -399,14 +417,16 @@ let ShadersEditorsView = {
|
||||
*
|
||||
* @param string flag
|
||||
* Either "on" to enable the event listeners, "off" to disable them.
|
||||
* @return object
|
||||
* A promise resolving upon completion of toggling the listeners.
|
||||
*/
|
||||
_toggleListeners: function(flag) {
|
||||
["vs", "fs"].forEach(type => {
|
||||
this._getEditor(type).then(editor => {
|
||||
return promise.all(["vs", "fs"].map(type => {
|
||||
return this._getEditor(type).then(editor => {
|
||||
editor[flag]("focus", this["_" + type + "Focused"]);
|
||||
editor[flag]("change", this["_" + type + "Changed"]);
|
||||
});
|
||||
});
|
||||
}));
|
||||
},
|
||||
|
||||
/**
|
||||
@ -486,7 +506,7 @@ let ShadersEditorsView = {
|
||||
}
|
||||
function sanitizeValidMatches(e) {
|
||||
return {
|
||||
// Drivers might yield retarded line numbers under some obscure
|
||||
// Drivers might yield confusing line numbers under some obscure
|
||||
// circumstances. Don't throw the errors away in those cases,
|
||||
// just display them on the currently edited line.
|
||||
line: e.lineMatch[0] > lineCount ? currentLine : e.lineMatch[0] - 1,
|
||||
@ -554,6 +574,7 @@ let ShadersEditorsView = {
|
||||
editor.removeAllMarkers("errors");
|
||||
this._errors[type].forEach(e => editor.removeLineClass(e.line));
|
||||
this._errors[type].length = 0;
|
||||
window.emit(EVENTS.EDITOR_ERROR_MARKERS_REMOVED);
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -14,8 +14,7 @@ function ifWebGLSupported() {
|
||||
yield reloaded;
|
||||
|
||||
let navigated = navigate(target, MULTIPLE_CONTEXTS_URL);
|
||||
let secondProgram = yield once(gFront, "program-linked");
|
||||
let thirdProgram = yield once(gFront, "program-linked");
|
||||
let [secondProgram, thirdProgram] = yield getPrograms(gFront, 2);
|
||||
yield navigated;
|
||||
|
||||
let vsEditor = yield ShadersEditorsView._getEditor("vs");
|
||||
@ -56,9 +55,3 @@ function ifWebGLSupported() {
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
||||
|
||||
function once(aTarget, aEvent) {
|
||||
let deferred = promise.defer();
|
||||
aTarget.once(aEvent, deferred.resolve);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
@ -8,14 +8,18 @@
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, panel] = yield initShaderEditor(SIMPLE_CANVAS_URL);
|
||||
let { gFront, ShadersEditorsView } = panel.panelWin;
|
||||
let { gFront, ShadersEditorsView, EVENTS } = panel.panelWin;
|
||||
|
||||
reload(target);
|
||||
yield once(gFront, "program-linked");
|
||||
yield promise.all([
|
||||
once(gFront, "program-linked"),
|
||||
once(panel.panelWin, EVENTS.SOURCES_SHOWN)
|
||||
]);
|
||||
|
||||
let vsEditor = yield ShadersEditorsView._getEditor("vs");
|
||||
let fsEditor = yield ShadersEditorsView._getEditor("fs");
|
||||
|
||||
|
||||
is(vsEditor.getText().indexOf("gl_Position"), 170,
|
||||
"The vertex shader editor contains the correct text.");
|
||||
is(fsEditor.getText().indexOf("gl_FragColor"), 97,
|
||||
|
@ -11,55 +11,61 @@ function ifWebGLSupported() {
|
||||
let { gFront, EVENTS, ShadersEditorsView } = panel.panelWin;
|
||||
|
||||
reload(target);
|
||||
yield once(gFront, "program-linked");
|
||||
yield promise.all([
|
||||
once(gFront, "program-linked"),
|
||||
once(panel.panelWin, EVENTS.SOURCES_SHOWN)
|
||||
]);
|
||||
|
||||
let vsEditor = yield ShadersEditorsView._getEditor("vs");
|
||||
let fsEditor = yield ShadersEditorsView._getEditor("fs");
|
||||
|
||||
vsEditor.replaceText("vec3", { line: 7, ch: 22 }, { line: 7, ch: 26 });
|
||||
let vertError = yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
|
||||
let [, vertError] = yield onceSpread(panel.panelWin, EVENTS.SHADER_COMPILED);
|
||||
checkHasVertFirstError(true, vertError);
|
||||
checkHasVertSecondError(false, vertError);
|
||||
info("Error marks added in the vertex shader editor.");
|
||||
|
||||
vsEditor.insertText(" ", { line: 1, ch: 0 });
|
||||
yield once(panel.panelWin, EVENTS.EDITOR_ERROR_MARKERS_REMOVED);
|
||||
is(vsEditor.getText(1), " precision lowp float;", "Typed space.");
|
||||
checkHasVertFirstError(false, vertError);
|
||||
checkHasVertSecondError(false, vertError);
|
||||
info("Error marks removed while typing in the vertex shader editor.");
|
||||
|
||||
let vertError = yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
|
||||
[, vertError] = yield onceSpread(panel.panelWin, EVENTS.SHADER_COMPILED);
|
||||
checkHasVertFirstError(true, vertError);
|
||||
checkHasVertSecondError(false, vertError);
|
||||
info("Error marks were re-added after recompiling the vertex shader.");
|
||||
|
||||
fsEditor.replaceText("vec4", { line: 2, ch: 14 }, { line: 2, ch: 18 });
|
||||
let fragError = yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
|
||||
let [, fragError] = yield onceSpread(panel.panelWin, EVENTS.SHADER_COMPILED);
|
||||
checkHasVertFirstError(true, vertError);
|
||||
checkHasVertSecondError(false, vertError);
|
||||
checkHasFragError(true, fragError);
|
||||
info("Error marks added in the fragment shader editor.");
|
||||
|
||||
fsEditor.insertText(" ", { line: 1, ch: 0 });
|
||||
yield once(panel.panelWin, EVENTS.EDITOR_ERROR_MARKERS_REMOVED);
|
||||
is(fsEditor.getText(1), " precision lowp float;", "Typed space.");
|
||||
checkHasVertFirstError(true, vertError);
|
||||
checkHasVertSecondError(false, vertError);
|
||||
checkHasFragError(false, fragError);
|
||||
info("Error marks removed while typing in the fragment shader editor.");
|
||||
|
||||
let fragError = yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
|
||||
[, fragError] = yield onceSpread(panel.panelWin, EVENTS.SHADER_COMPILED);
|
||||
checkHasVertFirstError(true, vertError);
|
||||
checkHasVertSecondError(false, vertError);
|
||||
checkHasFragError(true, fragError);
|
||||
info("Error marks were re-added after recompiling the fragment shader.");
|
||||
|
||||
vsEditor.replaceText("2", { line: 3, ch: 19 }, { line: 3, ch: 20 });
|
||||
yield once(panel.panelWin, EVENTS.EDITOR_ERROR_MARKERS_REMOVED);
|
||||
checkHasVertFirstError(false, vertError);
|
||||
checkHasVertSecondError(false, vertError);
|
||||
checkHasFragError(true, fragError);
|
||||
info("Error marks removed while typing in the vertex shader editor again.");
|
||||
|
||||
let vertError = yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
|
||||
[, vertError] = yield onceSpread(panel.panelWin, EVENTS.SHADER_COMPILED);
|
||||
checkHasVertFirstError(true, vertError);
|
||||
checkHasVertSecondError(true, vertError);
|
||||
checkHasFragError(true, fragError);
|
||||
@ -148,9 +154,3 @@ function ifWebGLSupported() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function once(aTarget, aEvent) {
|
||||
let deferred = promise.defer();
|
||||
aTarget.once(aEvent, (aName, aData) => deferred.resolve(aData));
|
||||
return deferred.promise;
|
||||
}
|
||||
|
@ -11,7 +11,10 @@ function ifWebGLSupported() {
|
||||
let { gFront, EVENTS, ShadersEditorsView } = panel.panelWin;
|
||||
|
||||
reload(target);
|
||||
yield once(gFront, "program-linked");
|
||||
yield promise.all([
|
||||
once(gFront, "program-linked"),
|
||||
once(panel.panelWin, EVENTS.SOURCES_SHOWN)
|
||||
]);
|
||||
|
||||
let vsEditor = yield ShadersEditorsView._getEditor("vs");
|
||||
let fsEditor = yield ShadersEditorsView._getEditor("fs");
|
||||
@ -51,9 +54,3 @@ function ifWebGLSupported() {
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
||||
|
||||
function once(aTarget, aEvent) {
|
||||
let deferred = promise.defer();
|
||||
aTarget.once(aEvent, (aName, aData) => deferred.resolve(aData));
|
||||
return deferred.promise;
|
||||
}
|
||||
|
@ -7,10 +7,13 @@
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, panel] = yield initShaderEditor(SIMPLE_CANVAS_URL);
|
||||
let { gFront, $, ShadersListView, ShadersEditorsView } = panel.panelWin;
|
||||
let { gFront, $, EVENTS, ShadersListView, ShadersEditorsView } = panel.panelWin;
|
||||
|
||||
reload(target);
|
||||
yield once(gFront, "program-linked");
|
||||
yield promise.all([
|
||||
once(gFront, "program-linked"),
|
||||
once(panel.panelWin, EVENTS.SOURCES_SHOWN)
|
||||
]);
|
||||
|
||||
is($("#reload-notice").hidden, true,
|
||||
"The 'reload this page' notice should be hidden after linking.");
|
||||
@ -39,6 +42,7 @@ function ifWebGLSupported() {
|
||||
navigate(target, "about:blank");
|
||||
|
||||
yield navigating;
|
||||
yield once(panel.panelWin, EVENTS.UI_RESET);
|
||||
|
||||
is($("#reload-notice").hidden, true,
|
||||
"The 'reload this page' notice should be hidden while navigating.");
|
||||
@ -54,19 +58,17 @@ function ifWebGLSupported() {
|
||||
is(ShadersListView.selectedIndex, -1,
|
||||
"The shaders list has a negative index.");
|
||||
|
||||
try {
|
||||
yield ShadersEditorsView._getEditor("vs");
|
||||
yield ShadersEditorsView._getEditor("vs").then(() => {
|
||||
ok(false, "The promise for a vertex shader editor should be rejected.");
|
||||
} catch (e) {
|
||||
}, () => {
|
||||
ok(true, "The vertex shader editors wasn't initialized.");
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
yield ShadersEditorsView._getEditor("fs");
|
||||
yield ShadersEditorsView._getEditor("fs").then(() => {
|
||||
ok(false, "The promise for a fragment shader editor should be rejected.");
|
||||
} catch (e) {
|
||||
}, () => {
|
||||
ok(true, "The fragment shader editors wasn't initialized.");
|
||||
}
|
||||
});
|
||||
|
||||
yield navigated;
|
||||
|
||||
|
@ -14,8 +14,10 @@ function ifWebGLSupported() {
|
||||
});
|
||||
|
||||
reload(target);
|
||||
let firstProgramActor = yield once(gFront, "program-linked");
|
||||
let secondProgramActor = yield once(gFront, "program-linked");
|
||||
let [firstProgramActor, secondProgramActor] = yield promise.all([
|
||||
getPrograms(gFront, 2),
|
||||
once(panel.panelWin, EVENTS.SOURCES_SHOWN)
|
||||
]).then(([programs]) => programs);
|
||||
|
||||
let vsEditor = yield ShadersEditorsView._getEditor("vs");
|
||||
let fsEditor = yield ShadersEditorsView._getEditor("fs");
|
||||
|
@ -11,8 +11,10 @@ function ifWebGLSupported() {
|
||||
let { gFront, EVENTS, ShadersListView, ShadersEditorsView } = panel.panelWin;
|
||||
|
||||
reload(target);
|
||||
let firstProgramActor = yield once(gFront, "program-linked");
|
||||
let secondProgramActor = yield once(gFront, "program-linked");
|
||||
let [firstProgramActor, secondProgramActor] = yield promise.all([
|
||||
getPrograms(gFront, 2),
|
||||
once(panel.panelWin, EVENTS.SOURCES_SHOWN)
|
||||
]).then(([programs]) => programs);
|
||||
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 127, g: 127, b: 127, a: 255 }, true);
|
||||
yield ensurePixelIs(debuggee, { x: 64, y: 64 }, { r: 0, g: 127, b: 127, a: 127 }, true);
|
||||
@ -59,9 +61,3 @@ function getBlackBoxCheckbox(aPanel, aIndex) {
|
||||
return aPanel.panelWin.document.querySelectorAll(
|
||||
".side-menu-widget-item-checkbox")[aIndex];
|
||||
}
|
||||
|
||||
function once(aTarget, aEvent) {
|
||||
let deferred = promise.defer();
|
||||
aTarget.once(aEvent, deferred.resolve);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
@ -7,10 +7,14 @@
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, panel] = yield initShaderEditor(MULTIPLE_CONTEXTS_URL);
|
||||
let { gFront, ShadersListView, ShadersEditorsView } = panel.panelWin;
|
||||
let { EVENTS, gFront, ShadersListView, ShadersEditorsView } = panel.panelWin;
|
||||
|
||||
reload(target);
|
||||
let programActor = yield once(gFront, "program-linked");
|
||||
let [programActor] = yield promise.all([
|
||||
getPrograms(gFront, 1),
|
||||
once(panel.panelWin, EVENTS.SOURCES_SHOWN)
|
||||
]).then(([programs]) => programs);
|
||||
|
||||
let programItem = ShadersListView.selectedItem;
|
||||
|
||||
is(programItem.attachment.programActor, programActor,
|
||||
|
@ -14,8 +14,10 @@ function ifWebGLSupported() {
|
||||
});
|
||||
|
||||
reload(target);
|
||||
let firstProgramActor = yield once(gFront, "program-linked");
|
||||
let secondProgramActor = yield once(gFront, "program-linked");
|
||||
let [firstProgramActor, secondProgramActor] = yield promise.all([
|
||||
getPrograms(gFront, 2),
|
||||
once(panel.panelWin, EVENTS.SOURCES_SHOWN)
|
||||
]).then(([programs]) => programs);
|
||||
|
||||
let vsEditor = yield ShadersEditorsView._getEditor("vs");
|
||||
let fsEditor = yield ShadersEditorsView._getEditor("fs");
|
||||
@ -89,9 +91,3 @@ function getBlackBoxCheckbox(aPanel, aIndex) {
|
||||
return aPanel.panelWin.document.querySelectorAll(
|
||||
".side-menu-widget-item-checkbox")[aIndex];
|
||||
}
|
||||
|
||||
function once(aTarget, aEvent) {
|
||||
let deferred = promise.defer();
|
||||
aTarget.once(aEvent, deferred.resolve);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
@ -11,8 +11,10 @@ function ifWebGLSupported() {
|
||||
let { gFront, EVENTS, ShadersListView, ShadersEditorsView } = panel.panelWin;
|
||||
|
||||
reload(target);
|
||||
let firstProgramActor = yield once(gFront, "program-linked");
|
||||
let secondProgramActor = yield once(gFront, "program-linked");
|
||||
let [firstProgramActor, secondProgramActor] = yield promise.all([
|
||||
getPrograms(gFront, 2),
|
||||
once(panel.panelWin, EVENTS.SOURCES_SHOWN)
|
||||
]).then(([programs]) => programs);
|
||||
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 127, g: 127, b: 127, a: 255 }, true);
|
||||
yield ensurePixelIs(debuggee, { x: 64, y: 64 }, { r: 0, g: 127, b: 127, a: 127 }, true);
|
||||
@ -45,9 +47,3 @@ function getItemLabel(aPanel, aIndex) {
|
||||
return aPanel.panelWin.document.querySelectorAll(
|
||||
".side-menu-widget-item-label")[aIndex];
|
||||
}
|
||||
|
||||
function once(aTarget, aEvent) {
|
||||
let deferred = promise.defer();
|
||||
aTarget.once(aEvent, deferred.resolve);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
@ -19,23 +19,17 @@ function ifWebGLSupported() {
|
||||
|
||||
reload(target);
|
||||
|
||||
let firstProgramActor = yield once(gFront, "program-linked");
|
||||
|
||||
is(ShadersListView.itemCount, 1,
|
||||
"The shaders list contains one entry.");
|
||||
is(ShadersListView.selectedItem, ShadersListView.items[0],
|
||||
"The shaders list has a correct item selected.");
|
||||
is(ShadersListView.selectedIndex, 0,
|
||||
"The shaders list has a correct index selected.");
|
||||
|
||||
let secondProgramActor = yield once(gFront, "program-linked");
|
||||
|
||||
is(ShadersListView.itemCount, 2,
|
||||
"The shaders list contains two entries.");
|
||||
is(ShadersListView.selectedItem, ShadersListView.items[0],
|
||||
"The shaders list has a correct item selected.");
|
||||
is(ShadersListView.selectedIndex, 0,
|
||||
"The shaders list has a correct index selected.");
|
||||
let [firstProgramActor, secondProgramActor] = yield promise.all([
|
||||
getPrograms(gFront, 2, (actors) => {
|
||||
// Fired upon each actor addition, we want to check only
|
||||
// after the first actor has been added so we can test state
|
||||
if (actors.length === 1)
|
||||
checkFirstProgram();
|
||||
if (actors.length === 2)
|
||||
checkSecondProgram();
|
||||
}),
|
||||
once(panel.panelWin, EVENTS.SOURCES_SHOWN)
|
||||
]).then(([programs, ]) => programs);
|
||||
|
||||
is(ShadersListView.labels[0], L10N.getFormatStr("shadersList.programLabel", 0),
|
||||
"The correct first label is shown in the shaders list.");
|
||||
@ -73,10 +67,21 @@ function ifWebGLSupported() {
|
||||
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
||||
|
||||
function once(aTarget, aEvent) {
|
||||
let deferred = promise.defer();
|
||||
aTarget.once(aEvent, deferred.resolve);
|
||||
return deferred.promise;
|
||||
function checkFirstProgram () {
|
||||
is(ShadersListView.itemCount, 1,
|
||||
"The shaders list contains one entry.");
|
||||
is(ShadersListView.selectedItem, ShadersListView.items[0],
|
||||
"The shaders list has a correct item selected.");
|
||||
is(ShadersListView.selectedIndex, 0,
|
||||
"The shaders list has a correct index selected.");
|
||||
}
|
||||
function checkSecondProgram () {
|
||||
is(ShadersListView.itemCount, 2,
|
||||
"The shaders list contains two entries.");
|
||||
is(ShadersListView.selectedItem, ShadersListView.items[0],
|
||||
"The shaders list has a correct item selected.");
|
||||
is(ShadersListView.selectedIndex, 0,
|
||||
"The shaders list has a correct index selected.");
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,10 @@ function ifWebGLSupported() {
|
||||
let { gFront, $, EVENTS, ShadersEditorsView } = panel.panelWin;
|
||||
|
||||
reload(target);
|
||||
yield once(gFront, "program-linked");
|
||||
yield promise.all([
|
||||
once(gFront, "program-linked"),
|
||||
once(panel.panelWin, EVENTS.SOURCES_SHOWN)
|
||||
]);
|
||||
|
||||
let vsEditor = yield ShadersEditorsView._getEditor("vs");
|
||||
let fsEditor = yield ShadersEditorsView._getEditor("fs");
|
||||
@ -68,9 +71,3 @@ function ifWebGLSupported() {
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
||||
|
||||
function once(aTarget, aEvent) {
|
||||
let deferred = promise.defer();
|
||||
aTarget.once(aEvent, deferred.resolve);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
@ -11,13 +11,16 @@ function ifWebGLSupported() {
|
||||
let { gFront, EVENTS, ShadersEditorsView } = panel.panelWin;
|
||||
|
||||
reload(target);
|
||||
yield once(gFront, "program-linked");
|
||||
yield promise.all([
|
||||
once(gFront, "program-linked"),
|
||||
once(panel.panelWin, EVENTS.SOURCES_SHOWN)
|
||||
]);
|
||||
|
||||
let vsEditor = yield ShadersEditorsView._getEditor("vs");
|
||||
let fsEditor = yield ShadersEditorsView._getEditor("fs");
|
||||
|
||||
vsEditor.replaceText("vec3", { line: 7, ch: 22 }, { line: 7, ch: 26 });
|
||||
let error = yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
|
||||
let [, error] = yield onceSpread(panel.panelWin, EVENTS.SHADER_COMPILED);
|
||||
|
||||
ok(error,
|
||||
"The new vertex shader source was compiled with errors.");
|
||||
@ -33,7 +36,7 @@ function ifWebGLSupported() {
|
||||
"An assignment error is contained in the linkage status.");
|
||||
|
||||
fsEditor.replaceText("vec4", { line: 2, ch: 14 }, { line: 2, ch: 18 });
|
||||
let error = yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
|
||||
let [, error] = yield onceSpread(panel.panelWin, EVENTS.SHADER_COMPILED);
|
||||
|
||||
ok(error,
|
||||
"The new fragment shader source was compiled with errors.");
|
||||
@ -50,11 +53,11 @@ function ifWebGLSupported() {
|
||||
yield ensurePixelIs(debuggee, { x: 511, y: 511 }, { r: 0, g: 255, b: 0, a: 255 }, true);
|
||||
|
||||
vsEditor.replaceText("vec4", { line: 7, ch: 22 }, { line: 7, ch: 26 });
|
||||
let error = yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
|
||||
let [, error] = yield onceSpread(panel.panelWin, EVENTS.SHADER_COMPILED);
|
||||
ok(!error, "The new vertex shader source was compiled successfully.");
|
||||
|
||||
fsEditor.replaceText("vec3", { line: 2, ch: 14 }, { line: 2, ch: 18 });
|
||||
let error = yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
|
||||
let [, error] = yield onceSpread(panel.panelWin, EVENTS.SHADER_COMPILED);
|
||||
ok(!error, "The new fragment shader source was compiled successfully.");
|
||||
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true);
|
||||
@ -63,9 +66,3 @@ function ifWebGLSupported() {
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
||||
|
||||
function once(aTarget, aEvent) {
|
||||
let deferred = promise.defer();
|
||||
aTarget.once(aEvent, (aName, aData) => deferred.resolve(aData));
|
||||
return deferred.promise;
|
||||
}
|
||||
|
@ -11,8 +11,13 @@ function ifWebGLSupported() {
|
||||
let { gFront, EVENTS, ShadersListView, ShadersEditorsView } = panel.panelWin;
|
||||
|
||||
reload(target);
|
||||
let firstProgramActor = yield once(gFront, "program-linked");
|
||||
let secondProgramActor = yield once(gFront, "program-linked");
|
||||
|
||||
yield promise.all([
|
||||
once(gFront, "program-linked"),
|
||||
once(gFront, "program-linked")
|
||||
]);
|
||||
|
||||
yield once(panel.panelWin, EVENTS.SOURCES_SHOWN)
|
||||
|
||||
let vsEditor = yield ShadersEditorsView._getEditor("vs");
|
||||
let fsEditor = yield ShadersEditorsView._getEditor("fs");
|
||||
@ -78,9 +83,3 @@ function ifWebGLSupported() {
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
||||
|
||||
function once(aTarget, aEvent) {
|
||||
let deferred = promise.defer();
|
||||
aTarget.once(aEvent, deferred.resolve);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
@ -9,8 +9,7 @@ function ifWebGLSupported() {
|
||||
let [target, debuggee, front] = yield initBackend(MULTIPLE_CONTEXTS_URL);
|
||||
front.setup({ reload: true });
|
||||
|
||||
let firstProgramActor = yield once(front, "program-linked");
|
||||
let secondProgramActor = yield once(front, "program-linked");
|
||||
let [firstProgramActor, secondProgramActor] = yield getPrograms(front, 2);
|
||||
|
||||
isnot(firstProgramActor, secondProgramActor,
|
||||
"Two distinct program actors were recevide from two separate contexts.");
|
||||
|
@ -10,8 +10,8 @@ function ifWebGLSupported() {
|
||||
let [target, debuggee, front] = yield initBackend(MULTIPLE_CONTEXTS_URL);
|
||||
front.setup({ reload: true });
|
||||
|
||||
let firstProgramActor = yield once(front, "program-linked");
|
||||
let secondProgramActor = yield once(front, "program-linked");
|
||||
let [firstProgramActor, secondProgramActor] = yield getPrograms(front, 2);
|
||||
|
||||
let firstFragmentShader = yield firstProgramActor.getFragmentShader();
|
||||
let secondFragmentShader = yield secondProgramActor.getFragmentShader();
|
||||
|
||||
|
@ -16,8 +16,7 @@ function ifWebGLSupported() {
|
||||
ok(true, "The cached programs behave correctly before the navigation.");
|
||||
|
||||
navigate(target, MULTIPLE_CONTEXTS_URL);
|
||||
let secondProgram = yield once(front, "program-linked");
|
||||
let thirdProgram = yield once(front, "program-linked");
|
||||
let [secondProgram, thirdProgram] = yield getPrograms(front, 2);
|
||||
yield checkSecondCachedPrograms(firstProgram, [secondProgram, thirdProgram]);
|
||||
yield checkHighlightingInTheSecondPage(secondProgram, thirdProgram);
|
||||
ok(true, "The cached programs behave correctly after the navigation.");
|
||||
|
@ -23,8 +23,7 @@ function ifWebGLSupported() {
|
||||
// 1. Perform a simple navigation.
|
||||
|
||||
navigate(target, MULTIPLE_CONTEXTS_URL);
|
||||
let secondProgram = yield once(front, "program-linked");
|
||||
let thirdProgram = yield once(front, "program-linked");
|
||||
let [secondProgram, thirdProgram] = yield getPrograms(front, 2);
|
||||
let programs = yield front.getPrograms();
|
||||
is(programs.length, 2,
|
||||
"The second and third programs should be returned by a call to getPrograms().");
|
||||
@ -65,8 +64,7 @@ function ifWebGLSupported() {
|
||||
is(programs.length, 0,
|
||||
"There should be no cached program actors yet.");
|
||||
|
||||
yield once(front, "program-linked");
|
||||
yield once(front, "program-linked");
|
||||
yield getPrograms(front, 2);
|
||||
yield globalCreated;
|
||||
let programs = yield front.getPrograms();
|
||||
is(programs.length, 2,
|
||||
|
@ -10,8 +10,7 @@ function ifWebGLSupported() {
|
||||
let [target, debuggee, front] = yield initBackend(OVERLAPPING_GEOMETRY_CANVAS_URL);
|
||||
front.setup({ reload: true });
|
||||
|
||||
let firstProgramActor = yield once(front, "program-linked");
|
||||
let secondProgramActor = yield once(front, "program-linked");
|
||||
let [firstProgramActor, secondProgramActor] = yield getPrograms(front, 2);
|
||||
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true);
|
||||
yield ensurePixelIs(debuggee, { x: 64, y: 64 }, { r: 0, g: 255, b: 255, a: 255 }, true);
|
||||
|
@ -48,7 +48,7 @@
|
||||
|
||||
window.onload = function() {
|
||||
canvas = document.querySelector("canvas");
|
||||
gl = canvas.getContext("webgl");
|
||||
gl = canvas.getContext("webgl", { preserveDrawingBuffer: true });
|
||||
gl.clearColor(0.0, 0.0, 0.0, 1.0);
|
||||
|
||||
initProgram(0);
|
||||
|
@ -42,7 +42,7 @@
|
||||
window.onload = function() {
|
||||
for (let i = 0; i < 2; i++) {
|
||||
canvas[i] = document.querySelector("#canvas" + (i + 1));
|
||||
gl[i] = canvas[i].getContext("webgl");
|
||||
gl[i] = canvas[i].getContext("webgl", { preserveDrawingBuffer: true });
|
||||
gl[i].clearColor(0.0, 0.0, 0.0, 1.0);
|
||||
|
||||
initProgram(i);
|
||||
|
@ -48,7 +48,7 @@
|
||||
|
||||
window.onload = function() {
|
||||
canvas = document.querySelector("canvas");
|
||||
gl = canvas.getContext("webgl");
|
||||
gl = canvas.getContext("webgl", { preserveDrawingBuffer: true });
|
||||
gl.clearColor(0.0, 0.0, 0.0, 1.0);
|
||||
|
||||
initProgram(0);
|
||||
|
@ -35,7 +35,7 @@
|
||||
|
||||
window.onload = function() {
|
||||
canvas = document.querySelector("canvas");
|
||||
gl = canvas.getContext("webgl");
|
||||
gl = canvas.getContext("webgl", { preserveDrawingBuffer: true });
|
||||
|
||||
let shaderProgram = gl.createProgram();
|
||||
let vertexShader, fragmentShader;
|
||||
|
@ -44,7 +44,7 @@
|
||||
|
||||
window.onload = function() {
|
||||
canvas = document.querySelector("canvas");
|
||||
gl = canvas.getContext("webgl");
|
||||
gl = canvas.getContext("webgl", { preserveDrawingBuffer: true });
|
||||
gl.clearColor(0.0, 0.0, 0.0, 1.0);
|
||||
|
||||
initProgram();
|
||||
|
@ -12,7 +12,7 @@ let gEnableLogging = Services.prefs.getBoolPref("devtools.debugger.log");
|
||||
Services.prefs.setBoolPref("devtools.debugger.log", true);
|
||||
|
||||
let { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
|
||||
let { Promise: promise } = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {});
|
||||
let { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||
let { gDevTools } = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
|
||||
let { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
let { DebuggerServer } = Cu.import("resource://gre/modules/devtools/dbg-server.jsm", {});
|
||||
@ -124,14 +124,14 @@ function once(aTarget, aEventName, aUseCapture = false) {
|
||||
let deferred = promise.defer();
|
||||
|
||||
for (let [add, remove] of [
|
||||
["on", "off"], // Use event emitter before DOM events for consistency
|
||||
["addEventListener", "removeEventListener"],
|
||||
["addListener", "removeListener"],
|
||||
["on", "off"]
|
||||
["addListener", "removeListener"]
|
||||
]) {
|
||||
if ((add in aTarget) && (remove in aTarget)) {
|
||||
aTarget[add](aEventName, function onEvent(...aArgs) {
|
||||
aTarget[remove](aEventName, onEvent, aUseCapture);
|
||||
deferred.resolve.apply(deferred, aArgs);
|
||||
deferred.resolve(...aArgs);
|
||||
}, aUseCapture);
|
||||
break;
|
||||
}
|
||||
@ -140,6 +140,16 @@ function once(aTarget, aEventName, aUseCapture = false) {
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
// Hack around `once`, as that only resolves to a single (first) argument
|
||||
// and discards the rest. `onceSpread` is similar, except resolves to an
|
||||
// array of all of the arguments in the handler. These should be consolidated
|
||||
// into the same function, but many tests will need to be changed.
|
||||
function onceSpread(aTarget, aEvent) {
|
||||
let deferred = promise.defer();
|
||||
aTarget.once(aEvent, (...args) => deferred.resolve(args));
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function observe(aNotificationName, aOwnsWeak = false) {
|
||||
info("Waiting for observer notification: '" + aNotificationName + ".");
|
||||
|
||||
@ -273,3 +283,27 @@ function teardown(aPanel) {
|
||||
removeTab(aPanel.target.tab)
|
||||
]);
|
||||
}
|
||||
|
||||
// Due to `program-linked` events firing synchronously, we cannot
|
||||
// just yield/chain them together, as then we miss all actors after the
|
||||
// first event since they're fired consecutively. This allows us to capture
|
||||
// all actors and returns an array containing them.
|
||||
//
|
||||
// Takes a `front` object that is an event emitter, the number of
|
||||
// programs that should be listened to and waited on, and an optional
|
||||
// `onAdd` function that calls with the entire actors array on program link
|
||||
function getPrograms(front, count, onAdd) {
|
||||
let actors = [];
|
||||
let deferred = promise.defer();
|
||||
front.on("program-linked", function onLink (actor) {
|
||||
if (actors.length !== count) {
|
||||
actors.push(actor);
|
||||
if (typeof onAdd === 'function') onAdd(actors)
|
||||
}
|
||||
if (actors.length === count) {
|
||||
front.off("program-linked", onLink);
|
||||
deferred.resolve(actors);
|
||||
}
|
||||
});
|
||||
return deferred.promise;
|
||||
}
|
||||
|
@ -77,6 +77,7 @@ this.VariablesView = function VariablesView(aParentNode, aFlags = {}) {
|
||||
|
||||
this._parent = aParentNode;
|
||||
this._parent.classList.add("variables-view-container");
|
||||
this._parent.classList.add("theme-body");
|
||||
this._appendEmptyNotice();
|
||||
|
||||
this._onSearchboxInput = this._onSearchboxInput.bind(this);
|
||||
|
@ -654,7 +654,7 @@ this.WidgetMethods = {
|
||||
* - relaxed: true if this container should allow dupes & degenerates
|
||||
* - attachment: some attached primitive/object for the item
|
||||
* - attributes: a batch of attributes set to the displayed element
|
||||
* - finalize: function invokde when the item is removed
|
||||
* - finalize: function invoked when the item is removed
|
||||
* @return Item
|
||||
* The item associated with the displayed element if an unstaged push,
|
||||
* undefined if the item was staged for a later commit.
|
||||
@ -733,6 +733,7 @@ this.WidgetMethods = {
|
||||
}
|
||||
this._widget.removeChild(aItem._target);
|
||||
this._untangleItem(aItem);
|
||||
if (!this.itemCount) this.empty();
|
||||
},
|
||||
|
||||
/**
|
||||
@ -1009,7 +1010,9 @@ this.WidgetMethods = {
|
||||
// a redundant selection event, so return early.
|
||||
if (targetElement != prevElement) {
|
||||
this._widget.selectedItem = targetElement;
|
||||
ViewHelpers.dispatchEvent(targetElement || prevElement, "select", aItem);
|
||||
let dispTarget = targetElement || prevElement;
|
||||
let dispName = this.suppressSelectionEvents ? "suppressed-select" : "select";
|
||||
ViewHelpers.dispatchEvent(dispTarget, dispName, aItem);
|
||||
}
|
||||
|
||||
// Updates this container to reflect the information provided by the
|
||||
@ -1044,6 +1047,15 @@ this.WidgetMethods = {
|
||||
set selectedValue(aValue)
|
||||
this.selectedItem = this._itemsByValue.get(aValue),
|
||||
|
||||
/**
|
||||
* Specifies if "select" events dispatched from the elements in this container
|
||||
* when their respective items are selected should be suppressed or not.
|
||||
*
|
||||
* If this flag is set to true, then consumers of this container won't
|
||||
* be normally notified when items are selected.
|
||||
*/
|
||||
suppressSelectionEvents: false,
|
||||
|
||||
/**
|
||||
* Focus this container the first time an element is inserted?
|
||||
*
|
||||
@ -1305,6 +1317,14 @@ this.WidgetMethods = {
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Shortcut function for getItemForPredicate which works on item attachments.
|
||||
* @see getItemForPredicate
|
||||
*/
|
||||
getItemForAttachment: function(aPredicate, aOwner = this) {
|
||||
return this.getItemForPredicate(e => aPredicate(e.attachment));
|
||||
},
|
||||
|
||||
/**
|
||||
* Finds the index of an item in the container.
|
||||
*
|
||||
|
@ -236,7 +236,13 @@ Editor.prototype = {
|
||||
|
||||
cm.on("focus", () => this.emit("focus"));
|
||||
cm.on("scroll", () => this.emit("scroll"));
|
||||
cm.on("change", () => this.emit("change"));
|
||||
cm.on("change", () => {
|
||||
this.emit("change");
|
||||
if (!this._lastDirty) {
|
||||
this._lastDirty = true;
|
||||
this.emit("dirty-change");
|
||||
}
|
||||
});
|
||||
cm.on("cursorActivity", (cm) => this.emit("cursorActivity"));
|
||||
|
||||
cm.on("gutterClick", (cm, line, gutter, ev) => {
|
||||
@ -614,6 +620,8 @@ Editor.prototype = {
|
||||
setClean: function () {
|
||||
let cm = editors.get(this);
|
||||
this.version = cm.changeGeneration();
|
||||
this._lastDirty = false;
|
||||
this.emit("dirty-change");
|
||||
return this.version;
|
||||
},
|
||||
|
||||
|
@ -234,7 +234,7 @@ StyleSheetEditor.prototype = {
|
||||
this.emit("source-editor-load");
|
||||
});
|
||||
|
||||
sourceEditor.on("change", this._onPropertyChange);
|
||||
sourceEditor.on("dirty-change", this._onPropertyChange);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -14,7 +14,6 @@ Components.utils.import("resource://gre/modules/NetUtil.jsm", tempScope);
|
||||
let FileUtils = tempScope.FileUtils;
|
||||
let NetUtil = tempScope.NetUtil;
|
||||
|
||||
|
||||
function test()
|
||||
{
|
||||
waitForExplicitFinish();
|
||||
@ -41,9 +40,22 @@ function test()
|
||||
|
||||
function runTests(editor)
|
||||
{
|
||||
editor.sourceEditor.once("dirty-change", () => {
|
||||
is(editor.sourceEditor.isClean(), false, "Editor is dirty.");
|
||||
ok(editor.summary.classList.contains("unsaved"),
|
||||
"Star icon is present in the corresponding summary.");
|
||||
});
|
||||
let beginCursor = {line: 0, ch: 0};
|
||||
editor.sourceEditor.replaceText("DIRTY TEXT", beginCursor, beginCursor);
|
||||
|
||||
editor.sourceEditor.once("dirty-change", () => {
|
||||
is(editor.sourceEditor.isClean(), true, "Editor is clean.");
|
||||
ok(!editor.summary.classList.contains("unsaved"),
|
||||
"Star icon is not present in the corresponding summary.");
|
||||
finish();
|
||||
});
|
||||
editor.saveToFile(null, function (file) {
|
||||
ok(file, "file should get saved directly when using a file:// URI");
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -3322,10 +3322,12 @@ JSTerm.prototype = {
|
||||
|
||||
iframe.addEventListener("load", function onIframeLoad(aEvent) {
|
||||
iframe.removeEventListener("load", onIframeLoad, true);
|
||||
iframe.style.visibility = "visible";
|
||||
deferred.resolve(iframe.contentWindow);
|
||||
}, true);
|
||||
|
||||
iframe.flex = 1;
|
||||
iframe.style.visibility = "hidden";
|
||||
iframe.setAttribute("src", VARIABLES_VIEW_URL);
|
||||
aOptions.targetElement.appendChild(iframe);
|
||||
}
|
||||
|
@ -111,6 +111,11 @@ BINPATH = bin
|
||||
endif
|
||||
DEFINES += -DBINPATH=$(BINPATH)
|
||||
|
||||
DEFINES += -DMOZ_ICU_VERSION=$(MOZ_ICU_VERSION)
|
||||
ifdef MOZ_SHARED_ICU
|
||||
DEFINES += -DMOZ_SHARED_ICU
|
||||
endif
|
||||
|
||||
libs::
|
||||
$(MAKE) -C $(DEPTH)/browser/locales langpack
|
||||
|
||||
|
@ -101,6 +101,27 @@
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#ifdef MOZ_SHARED_ICU
|
||||
#ifdef XP_WIN
|
||||
#ifdef MOZ_DEBUG
|
||||
@BINPATH@/icudtd@MOZ_ICU_VERSION@.dll
|
||||
@BINPATH@/icuind@MOZ_ICU_VERSION@.dll
|
||||
@BINPATH@/icuucd@MOZ_ICU_VERSION@.dll
|
||||
#else
|
||||
@BINPATH@/icudt@MOZ_ICU_VERSION@.dll
|
||||
@BINPATH@/icuin@MOZ_ICU_VERSION@.dll
|
||||
@BINPATH@/icuuc@MOZ_ICU_VERSION@.dll
|
||||
#endif
|
||||
#elif defined(XP_MACOSX)
|
||||
@BINPATH@/libicudata.@MOZ_ICU_VERSION@.dylib
|
||||
@BINPATH@/libicui18n.@MOZ_ICU_VERSION@.dylib
|
||||
@BINPATH@/libicuuc.@MOZ_ICU_VERSION@.dylib
|
||||
#elif defined(XP_UNIX)
|
||||
@BINPATH@/libicudata.so.@MOZ_ICU_VERSION@
|
||||
@BINPATH@/libicui18n.so.@MOZ_ICU_VERSION@
|
||||
@BINPATH@/libicuuc.so.@MOZ_ICU_VERSION@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
[browser]
|
||||
; [Base Browser Files]
|
||||
|
@ -129,8 +129,10 @@
|
||||
<!ENTITY debuggerUI.seMenuCondBreak "Add conditional breakpoint">
|
||||
<!ENTITY debuggerUI.seMenuCondBreak.key "B">
|
||||
|
||||
<!-- LOCALIZATION NOTE (debuggerUI.instruments.*): This is the text that
|
||||
- appears in the debugger's instruments pane tabs. -->
|
||||
<!-- LOCALIZATION NOTE (debuggerUI.tabs.*): This is the text that
|
||||
- appears in the debugger's side pane tabs. -->
|
||||
<!ENTITY debuggerUI.tabs.sources "Sources">
|
||||
<!ENTITY debuggerUI.tabs.callstack "Call Stack">
|
||||
<!ENTITY debuggerUI.tabs.variables "Variables">
|
||||
<!ENTITY debuggerUI.tabs.events "Events">
|
||||
|
||||
|
@ -69,10 +69,14 @@ noGlobalsText=No globals
|
||||
# when there are no scripts.
|
||||
noSourcesText=This page has no sources.
|
||||
|
||||
# LOCALIZATION NOTE (noEventsTExt): The text to display in the events tab
|
||||
# LOCALIZATION NOTE (noEventListenersText): The text to display in the events tab
|
||||
# when there are no events.
|
||||
noEventListenersText=No event listeners to display
|
||||
|
||||
# LOCALIZATION NOTE (noStackFramesText): The text to display in the call stack tab
|
||||
# when there are no stack frames.
|
||||
noStackFramesText=No stack frames to display
|
||||
|
||||
# LOCALIZATION NOTE (eventCheckboxTooltip): The tooltip text to display when
|
||||
# the user hovers over the checkbox used to toggle an event breakpoint.
|
||||
eventCheckboxTooltip=Toggle breaking on this event
|
||||
|
@ -247,7 +247,7 @@ Desktop browser's sync prefs.
|
||||
completeselectedindex="true"
|
||||
placeholder="&urlbar.emptytext;"
|
||||
tabscrolling="true"
|
||||
onclick="SelectionHelperUI.urlbarClick();"/>
|
||||
onclick="SelectionHelperUI.urlbarTextboxClick(this);"/>
|
||||
|
||||
<toolbarbutton id="go-button" class="urlbar-button"
|
||||
command="cmd_go"/>
|
||||
|
@ -34,10 +34,9 @@ var ChromeSelectionHandler = {
|
||||
this._domWinUtils = Util.getWindowUtils(window);
|
||||
this._contentWindow = window;
|
||||
this._targetElement = this._domWinUtils.elementFromPoint(aJson.xPos, aJson.yPos, true, false);
|
||||
|
||||
this._targetIsEditable = this._targetElement instanceof Components.interfaces.nsIDOMXULTextBoxElement;
|
||||
if (!this._targetIsEditable) {
|
||||
this._onFail("not an editable?");
|
||||
this._onFail("not an editable?", this._targetElement);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -344,9 +344,9 @@ var SelectionHelperUI = {
|
||||
observe: function (aSubject, aTopic, aData) {
|
||||
switch (aTopic) {
|
||||
case "attach_edit_session_to_content":
|
||||
let event = aSubject;
|
||||
this.attachEditSession(Browser.selectedTab.browser,
|
||||
event.clientX, event.clientY);
|
||||
// We receive this from text input bindings when this module
|
||||
// isn't accessible.
|
||||
this.chromeTextboxClick(aSubject);
|
||||
break;
|
||||
|
||||
case "apzc-transform-begin":
|
||||
@ -514,6 +514,40 @@ var SelectionHelperUI = {
|
||||
});
|
||||
},
|
||||
|
||||
/*
|
||||
* Event handler on the navbar text input. Called from navbar bindings
|
||||
* when focus is applied to the edit.
|
||||
*/
|
||||
urlbarTextboxClick: function(aEdit) {
|
||||
// workaround for bug 925457: taping browser chrome resets last tap
|
||||
// co-ordinates to 'undefined' so that we know not to shift the browser
|
||||
// when the keyboard is up in SelectionHandler's _calcNewContentPosition().
|
||||
Browser.selectedTab.browser.messageManager.sendAsyncMessage("Browser:ResetLastPos", {
|
||||
xPos: null,
|
||||
yPos: null
|
||||
});
|
||||
|
||||
if (InputSourceHelper.isPrecise || !aEdit.textLength) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Enable selection when there's text in the control
|
||||
let innerRect = aEdit.inputField.getBoundingClientRect();
|
||||
this.attachEditSession(ChromeSelectionHandler,
|
||||
innerRect.left,
|
||||
innerRect.top);
|
||||
},
|
||||
|
||||
/*
|
||||
* Click handler for chrome pages loaded into the browser (about:config).
|
||||
* Called from the text input bindings via the attach_edit_session_to_content
|
||||
* observer.
|
||||
*/
|
||||
chromeTextboxClick: function (aEvent) {
|
||||
this.attachEditSession(Browser.selectedTab.browser,
|
||||
aEvent.clientX, aEvent.clientY);
|
||||
},
|
||||
|
||||
/*
|
||||
* Handy debug routines that work independent of selection. They
|
||||
* make use of the selection overlay for drawing points.
|
||||
@ -835,20 +869,10 @@ var SelectionHelperUI = {
|
||||
* Event handlers for document events
|
||||
*/
|
||||
|
||||
urlbarClick: function() {
|
||||
// Workaround for bug 925457: taping browser chrome resets last tap
|
||||
// co-ordinates to 'undefined' so that we know not to shift the browser
|
||||
// when the keyboard is up (in SelectionHandler._calcNewContentPosition())
|
||||
Browser.selectedTab.browser.messageManager.sendAsyncMessage("Browser:ResetLastPos", {
|
||||
xPos: null,
|
||||
yPos: null
|
||||
});
|
||||
},
|
||||
|
||||
/*
|
||||
* Handles taps that move the current caret around in text edits,
|
||||
* clear active selection and focus when neccessary, or change
|
||||
* modes.
|
||||
* modes. Only active afer SelectionHandlerUI is initialized.
|
||||
*/
|
||||
_onClick: function(aEvent) {
|
||||
if (this.layerMode == kChromeLayer && this._targetIsEditable) {
|
||||
|
@ -9,6 +9,10 @@
|
||||
min-width: 50px;
|
||||
}
|
||||
|
||||
#sources-pane > tabs {
|
||||
-moz-border-end: 1px solid #222426; /* Match the sources list's dark margin. */
|
||||
}
|
||||
|
||||
#sources-and-editor-splitter {
|
||||
-moz-border-start-color: transparent;
|
||||
}
|
||||
@ -20,7 +24,7 @@
|
||||
-moz-border-end: 1px solid #222426; /* Match the sources list's dark margin. */
|
||||
}
|
||||
|
||||
#sources-toolbar .devtools-toolbarbutton {
|
||||
#sources-toolbar > #sources-controls > .devtools-toolbarbutton {
|
||||
min-width: 32px;
|
||||
}
|
||||
|
||||
@ -87,15 +91,23 @@
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.list-widget-item:not(.selected):not(.empty):hover {
|
||||
.theme-light .list-widget-item:not(.selected):not(.empty):hover {
|
||||
background: linear-gradient(rgba(255,255,255,0.9), rgba(255,255,255,0.85)), Highlight;
|
||||
}
|
||||
|
||||
.list-widget-item.selected.light {
|
||||
.theme-light .list-widget-item.selected.light {
|
||||
background: linear-gradient(rgba(255,255,255,0.85), rgba(255,255,255,0.8)), Highlight;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.theme-dark .list-widget-item:not(.selected):not(.empty):hover {
|
||||
background: linear-gradient(rgba(255,255,255,0.1), rgba(255,255,255,0.05));
|
||||
}
|
||||
|
||||
.theme-dark .list-widget-item.selected.light {
|
||||
background: linear-gradient(rgba(255,255,255,0.05), rgba(255,255,255,0.025));
|
||||
}
|
||||
|
||||
.list-widget-item.selected {
|
||||
background: Highlight;
|
||||
color: HighlightText;
|
||||
@ -106,21 +118,52 @@
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
/* Stack frames view */
|
||||
/* Breadcrumbs stack frames view */
|
||||
|
||||
.breadcrumbs-widget-item {
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
.dbg-stackframe-details {
|
||||
-moz-padding-start: 4px;
|
||||
}
|
||||
|
||||
.dbg-stackframe-menuitem[checked] {
|
||||
margin-top: 3px;
|
||||
margin-bottom: 3px;
|
||||
outline: 1px solid #eee;
|
||||
font-weight: 600;
|
||||
/* Classic stack frames view */
|
||||
|
||||
.dbg-classic-stackframe {
|
||||
display: block;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.dbg-stackframe-menuitem-details {
|
||||
-moz-padding-start: 16px;
|
||||
.dbg-classic-stackframe-title {
|
||||
font-weight: 600;
|
||||
color: #046;
|
||||
}
|
||||
|
||||
.dbg-classic-stackframe-details:-moz-locale-dir(ltr) {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.dbg-classic-stackframe-details:-moz-locale-dir(rtl) {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.dbg-classic-stackframe-details-url {
|
||||
max-width: 90%;
|
||||
text-align: end;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.dbg-classic-stackframe-details-sep {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.dbg-classic-stackframe-details-line {
|
||||
color: #58b;
|
||||
}
|
||||
|
||||
#callstack-list .side-menu-widget-item.selected label {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Sources and breakpoints view */
|
||||
@ -180,8 +223,9 @@
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
#instruments-pane > tabpanels > tabpanel {
|
||||
background: #fff;
|
||||
#instruments-pane .side-menu-widget-container,
|
||||
#instruments-pane .side-menu-widget-empty-notice-container {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
/* Watch expressions view */
|
||||
@ -203,6 +247,7 @@
|
||||
|
||||
.dbg-expression-input {
|
||||
-moz-padding-start: 2px !important;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
/* Event listeners view */
|
||||
@ -227,6 +272,10 @@
|
||||
color: #666;
|
||||
}
|
||||
|
||||
#event-listeners .side-menu-widget-item.selected {
|
||||
background: none !important;
|
||||
}
|
||||
|
||||
/* Searchbox and the search operations help panel */
|
||||
|
||||
#searchbox {
|
||||
@ -380,6 +429,11 @@
|
||||
|
||||
/* Toolbar controls */
|
||||
|
||||
.devtools-sidebar-tabs > tabs > tab {
|
||||
min-height: 25px !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
#resumption-panel-desc {
|
||||
width: 200px;
|
||||
}
|
||||
@ -468,12 +522,17 @@
|
||||
max-height: 80vh;
|
||||
}
|
||||
|
||||
#body[layout=vertical] #sources-pane > tabs {
|
||||
-moz-border-end: none;
|
||||
}
|
||||
|
||||
#body[layout=vertical] #instruments-pane {
|
||||
margin: 0 !important;
|
||||
/* To prevent all the margin hacks to hide the sidebar. */
|
||||
}
|
||||
|
||||
#body[layout=vertical] .side-menu-widget-container {
|
||||
#body[layout=vertical] .side-menu-widget-container,
|
||||
#body[layout=vertical] .side-menu-widget-empty-notice-container {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
|
@ -312,6 +312,10 @@ box.requests-menu-status[code^="5"] {
|
||||
|
||||
/* SideMenuWidget */
|
||||
|
||||
.side-menu-widget-container {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.side-menu-widget-item[odd] {
|
||||
background: rgba(255,255,255,0.05);
|
||||
}
|
||||
@ -363,10 +367,6 @@ box.requests-menu-status[code^="5"] {
|
||||
-moz-padding-start: 3px;
|
||||
}
|
||||
|
||||
.variable-or-property:not(:focus) > .title > .token-string {
|
||||
color: #10c !important;
|
||||
}
|
||||
|
||||
/* Headers tabpanel */
|
||||
|
||||
#headers-summary-status,
|
||||
|
@ -281,15 +281,17 @@
|
||||
|
||||
/* SideMenuWidget container */
|
||||
|
||||
.side-menu-widget-container[with-arrows=true]:-moz-locale-dir(ltr) {
|
||||
.side-menu-widget-container:-moz-locale-dir(ltr),
|
||||
.side-menu-widget-empty-notice-container:-moz-locale-dir(ltr) {
|
||||
box-shadow: inset -1px 0 0 #222426;
|
||||
}
|
||||
|
||||
.side-menu-widget-container[with-arrows=true]:-moz-locale-dir(rtl) {
|
||||
.side-menu-widget-container:-moz-locale-dir(rtl),
|
||||
.side-menu-widget-empty-notice-container:-moz-locale-dir(rtl) {
|
||||
box-shadow: inset 1px 0 0 #222426;
|
||||
}
|
||||
|
||||
.side-menu-widget-container[with-arrows=true] .side-menu-widget-group {
|
||||
.side-menu-widget-group {
|
||||
/* To allow visibility of the dark margin shadow. */
|
||||
-moz-margin-end: 1px;
|
||||
}
|
||||
@ -328,7 +330,9 @@
|
||||
|
||||
.side-menu-widget-item[theme="light"] {
|
||||
border-top: 1px solid hsla(210,8%,75%,.25);
|
||||
border-bottom: 1px solid hsla(210,16%,76%,.1);
|
||||
margin-top: -1px;
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
|
||||
.side-menu-widget-item[theme="dark"]:last-of-type {
|
||||
@ -339,15 +343,11 @@
|
||||
box-shadow: inset 0 -1px 0 hsla(210,8%,75%,.25);
|
||||
}
|
||||
|
||||
.side-menu-widget-item[theme="dark"].selected {
|
||||
.side-menu-widget-item.selected {
|
||||
background: linear-gradient(hsl(206,61%,40%), hsl(206,61%,31%)) repeat-x top left !important;
|
||||
box-shadow: inset 0 1px 0 hsla(210,40%,83%,.15);
|
||||
}
|
||||
|
||||
.side-menu-widget-item[theme="light"].selected {
|
||||
/* Nothing here yet */
|
||||
}
|
||||
|
||||
.side-menu-widget-item.selected > .side-menu-widget-item-arrow {
|
||||
background-size: auto, 1px 100%;
|
||||
background-repeat: no-repeat;
|
||||
@ -432,10 +432,6 @@
|
||||
|
||||
/* VariablesView */
|
||||
|
||||
.variables-view-container {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.variables-view-empty-notice {
|
||||
color: GrayText;
|
||||
padding: 2px;
|
||||
@ -445,11 +441,6 @@
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.variables-view-scope:focus > .title {
|
||||
background: Highlight;
|
||||
color: HighlightText;
|
||||
}
|
||||
|
||||
.variables-view-scope > .variables-view-element-details:not(:empty) {
|
||||
-moz-margin-start: 2px;
|
||||
-moz-margin-end: 1px;
|
||||
@ -458,13 +449,12 @@
|
||||
/* Generic traits applied to both variables and properties */
|
||||
|
||||
.variable-or-property {
|
||||
transition: background 1s ease-in-out;
|
||||
color: #000;
|
||||
transition: background 1s ease-in-out, color 1s ease-in-out;
|
||||
}
|
||||
|
||||
.variable-or-property[changed] {
|
||||
background: rgba(255,255,0,0.65);
|
||||
transition-duration: 0.4s;
|
||||
color: black;
|
||||
transition-duration: .4s;
|
||||
}
|
||||
|
||||
.variable-or-property > .title > .value {
|
||||
@ -473,12 +463,6 @@
|
||||
-moz-padding-end: 4px;
|
||||
}
|
||||
|
||||
.variable-or-property:focus > .title {
|
||||
background: Highlight;
|
||||
color: HighlightText;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.variable-or-property[editable] > .title > .value {
|
||||
cursor: text;
|
||||
}
|
||||
@ -495,52 +479,22 @@
|
||||
}
|
||||
|
||||
.variables-view-variable:not(:last-child) {
|
||||
border-bottom: 1px solid #eee;
|
||||
border-bottom: 1px solid rgba(128, 128, 128, .15);
|
||||
}
|
||||
|
||||
.variables-view-variable > .title > .name {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.variables-view-variable:not(:focus) > .title > .name {
|
||||
color: #048;
|
||||
}
|
||||
|
||||
.variables-view-property:not(:focus) > .title > .name {
|
||||
color: #881090;
|
||||
}
|
||||
|
||||
/* Token value colors */
|
||||
|
||||
.variable-or-property:not(:focus) > .title > .token-undefined {
|
||||
color: #bbb;
|
||||
}
|
||||
|
||||
.variable-or-property:not(:focus) > .title > .token-null {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.variable-or-property:not(:focus) > .title > .token-boolean {
|
||||
color: #10c;
|
||||
}
|
||||
|
||||
.variable-or-property:not(:focus) > .title > .token-number {
|
||||
color: #c00;
|
||||
}
|
||||
|
||||
.variable-or-property:not(:focus) > .title > .token-string {
|
||||
color: #282;
|
||||
}
|
||||
|
||||
.variable-or-property:not(:focus) > .title > .token-other {
|
||||
color: #333;
|
||||
.variable-or-property:focus > .title > label {
|
||||
color: inherit !important;
|
||||
}
|
||||
|
||||
/* Custom configurable/enumerable/writable or frozen/sealed/extensible
|
||||
* variables and properties */
|
||||
|
||||
.variable-or-property[non-enumerable]:not([self]):not([exception]):not([return]):not([scope]) > .title > .name {
|
||||
opacity: 0.5;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.variable-or-property[non-configurable] > .title > .name {
|
||||
@ -551,6 +505,10 @@
|
||||
border-bottom: 1px dashed #f99;
|
||||
}
|
||||
|
||||
.variable-or-property[safe-getter] > .title > .name {
|
||||
border-bottom: 1px dashed #8b0;
|
||||
}
|
||||
|
||||
.variable-or-property-non-writable-icon {
|
||||
background: url("chrome://browser/skin/identity-icons-https.png") no-repeat;
|
||||
width: 16px;
|
||||
@ -577,27 +535,6 @@
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* Special variables and properties */
|
||||
|
||||
.variable-or-property[safe-getter] > .title > .name {
|
||||
border-bottom: 1px dashed #8b0;
|
||||
}
|
||||
|
||||
.variable-or-property[exception]:not(:focus) > .title > .name {
|
||||
color: #a00;
|
||||
text-shadow: 0 0 8px #fcc;
|
||||
}
|
||||
|
||||
.variable-or-property[return]:not(:focus) > .title > .name {
|
||||
color: #0a0;
|
||||
text-shadow: 0 0 8px #cfc;
|
||||
}
|
||||
|
||||
.variable-or-property[scope]:not(:focus) > .title > .name {
|
||||
color: #00a;
|
||||
text-shadow: 0 0 8px #ccf;
|
||||
}
|
||||
|
||||
/* Aligned values */
|
||||
|
||||
.variables-view-container[aligned-values] .title > .separator {
|
||||
@ -634,7 +571,7 @@
|
||||
.variable-or-property[non-configurable] > tooltip > label[value=configurable],
|
||||
.variable-or-property[non-writable] > tooltip > label[value=writable],
|
||||
.variable-or-property[non-extensible] > tooltip > label[value=extensible] {
|
||||
color: #f44;
|
||||
color: #800;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
@ -680,14 +617,13 @@
|
||||
.element-name-input {
|
||||
-moz-margin-start: -2px !important;
|
||||
-moz-margin-end: 2px !important;
|
||||
color: #048;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.element-value-input,
|
||||
.element-name-input {
|
||||
border: 1px solid #999 !important;
|
||||
box-shadow: 1px 2px 4px #aaa;
|
||||
border: 1px solid rgba(128, 128, 128, .5) !important;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
/* Variables and properties searching */
|
||||
|
@ -3594,11 +3594,16 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
|
||||
#navigator-toolbox[inFullscreen]:not(:-moz-lwtheme)::before {
|
||||
height: calc(@tabHeight@ + 11px) !important;
|
||||
}
|
||||
#main-window[inFullscreen][privatebrowsingmode=temporary],
|
||||
#main-window[inFullscreen]:-moz-lwtheme {
|
||||
/* This additional padding matches the change in height in the pseudo-element
|
||||
* above. The rules combined force the top 22px of the background image to
|
||||
* be hidden, so there image doesn't jump around with the loss of the titlebar */
|
||||
* above. */
|
||||
padding-top: 11px;
|
||||
}
|
||||
#main-window[inFullscreen]:not([privatebrowsingmode=temporary]):-moz-lwtheme {
|
||||
/* In combination with the previous rule, forces the top 22px of the
|
||||
* background image to be hidden, so the image doesn't jump around with
|
||||
* the loss of the titlebar. */
|
||||
background-position: right -11px;
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,10 @@
|
||||
min-width: 50px;
|
||||
}
|
||||
|
||||
#sources-pane > tabs {
|
||||
-moz-border-end: 1px solid #222426; /* Match the sources list's dark margin. */
|
||||
}
|
||||
|
||||
#sources-and-editor-splitter {
|
||||
-moz-border-start-color: transparent;
|
||||
}
|
||||
@ -22,7 +26,7 @@
|
||||
-moz-border-end: 1px solid #222426; /* Match the sources list's dark margin. */
|
||||
}
|
||||
|
||||
#sources-toolbar .devtools-toolbarbutton {
|
||||
#sources-toolbar > #sources-controls > .devtools-toolbarbutton {
|
||||
min-width: 32px;
|
||||
}
|
||||
|
||||
@ -89,15 +93,23 @@
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.list-widget-item:not(.selected):not(.empty):hover {
|
||||
.theme-light .list-widget-item:not(.selected):not(.empty):hover {
|
||||
background: linear-gradient(rgba(255,255,255,0.9), rgba(255,255,255,0.85)), Highlight;
|
||||
}
|
||||
|
||||
.list-widget-item.selected.light {
|
||||
.theme-light .list-widget-item.selected.light {
|
||||
background: linear-gradient(rgba(255,255,255,0.85), rgba(255,255,255,0.8)), Highlight;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.theme-dark .list-widget-item:not(.selected):not(.empty):hover {
|
||||
background: linear-gradient(rgba(255,255,255,0.1), rgba(255,255,255,0.05));
|
||||
}
|
||||
|
||||
.theme-dark .list-widget-item.selected.light {
|
||||
background: linear-gradient(rgba(255,255,255,0.05), rgba(255,255,255,0.025));
|
||||
}
|
||||
|
||||
.list-widget-item.selected {
|
||||
background: Highlight;
|
||||
color: HighlightText;
|
||||
@ -108,21 +120,52 @@
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
/* Stack frames view */
|
||||
/* Breadcrumbs stack frames view */
|
||||
|
||||
.breadcrumbs-widget-item {
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
.dbg-stackframe-details {
|
||||
-moz-padding-start: 4px;
|
||||
}
|
||||
|
||||
.dbg-stackframe-menuitem[checked] {
|
||||
margin-top: 3px;
|
||||
margin-bottom: 3px;
|
||||
outline: 1px solid #eee;
|
||||
font-weight: 600;
|
||||
/* Classic stack frames view */
|
||||
|
||||
.dbg-classic-stackframe {
|
||||
display: block;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.dbg-stackframe-menuitem-details {
|
||||
-moz-padding-start: 16px;
|
||||
.dbg-classic-stackframe-title {
|
||||
font-weight: 600;
|
||||
color: #046;
|
||||
}
|
||||
|
||||
.dbg-classic-stackframe-details:-moz-locale-dir(ltr) {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.dbg-classic-stackframe-details:-moz-locale-dir(rtl) {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.dbg-classic-stackframe-details-url {
|
||||
max-width: 90%;
|
||||
text-align: end;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.dbg-classic-stackframe-details-sep {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.dbg-classic-stackframe-details-line {
|
||||
color: #58b;
|
||||
}
|
||||
|
||||
#callstack-list .side-menu-widget-item.selected label {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Sources and breakpoints view */
|
||||
@ -182,8 +225,9 @@
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
#instruments-pane > tabpanels > tabpanel {
|
||||
background: #fff;
|
||||
#instruments-pane .side-menu-widget-container,
|
||||
#instruments-pane .side-menu-widget-empty-notice-container {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
/* Watch expressions view */
|
||||
@ -205,6 +249,7 @@
|
||||
|
||||
.dbg-expression-input {
|
||||
-moz-padding-start: 2px !important;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
/* Event listeners view */
|
||||
@ -229,6 +274,10 @@
|
||||
color: #666;
|
||||
}
|
||||
|
||||
#event-listeners .side-menu-widget-item.selected {
|
||||
background: none !important;
|
||||
}
|
||||
|
||||
/* Searchbox and the search operations help panel */
|
||||
|
||||
#searchbox {
|
||||
@ -382,6 +431,11 @@
|
||||
|
||||
/* Toolbar controls */
|
||||
|
||||
.devtools-sidebar-tabs > tabs > tab {
|
||||
min-height: 1em !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
#resumption-panel-desc {
|
||||
width: 200px;
|
||||
}
|
||||
@ -470,12 +524,17 @@
|
||||
max-height: 80vh;
|
||||
}
|
||||
|
||||
#body[layout=vertical] #sources-pane > tabs {
|
||||
-moz-border-end: none;
|
||||
}
|
||||
|
||||
#body[layout=vertical] #instruments-pane {
|
||||
margin: 0 !important;
|
||||
/* To prevent all the margin hacks to hide the sidebar. */
|
||||
}
|
||||
|
||||
#body[layout=vertical] .side-menu-widget-container {
|
||||
#body[layout=vertical] .side-menu-widget-container,
|
||||
#body[layout=vertical] .side-menu-widget-empty-notice-container {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
|
@ -312,6 +312,10 @@ box.requests-menu-status[code^="5"] {
|
||||
|
||||
/* SideMenuWidget */
|
||||
|
||||
.side-menu-widget-container {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.side-menu-widget-item[odd] {
|
||||
background: rgba(255,255,255,0.05);
|
||||
}
|
||||
@ -363,10 +367,6 @@ box.requests-menu-status[code^="5"] {
|
||||
-moz-padding-start: 3px;
|
||||
}
|
||||
|
||||
.variable-or-property:not(:focus) > .title > .token-string {
|
||||
color: #10c !important;
|
||||
}
|
||||
|
||||
/* Headers tabpanel */
|
||||
|
||||
#headers-summary-status,
|
||||
|
@ -281,15 +281,17 @@
|
||||
|
||||
/* SideMenuWidget container */
|
||||
|
||||
.side-menu-widget-container[with-arrows=true]:-moz-locale-dir(ltr) {
|
||||
.side-menu-widget-container:-moz-locale-dir(ltr),
|
||||
.side-menu-widget-empty-notice-container:-moz-locale-dir(ltr) {
|
||||
box-shadow: inset -1px 0 0 #222426;
|
||||
}
|
||||
|
||||
.side-menu-widget-container[with-arrows=true]:-moz-locale-dir(rtl) {
|
||||
.side-menu-widget-container:-moz-locale-dir(rtl),
|
||||
.side-menu-widget-empty-notice-container:-moz-locale-dir(rtl) {
|
||||
box-shadow: inset 1px 0 0 #222426;
|
||||
}
|
||||
|
||||
.side-menu-widget-container[with-arrows=true] .side-menu-widget-group {
|
||||
.side-menu-widget-group {
|
||||
/* To allow visibility of the dark margin shadow. */
|
||||
-moz-margin-end: 1px;
|
||||
}
|
||||
@ -328,7 +330,9 @@
|
||||
|
||||
.side-menu-widget-item[theme="light"] {
|
||||
border-top: 1px solid hsla(210,8%,75%,.25);
|
||||
border-bottom: 1px solid hsla(210,16%,76%,.1);
|
||||
margin-top: -1px;
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
|
||||
.side-menu-widget-item[theme="dark"]:last-of-type {
|
||||
@ -339,15 +343,11 @@
|
||||
box-shadow: inset 0 -1px 0 hsla(210,8%,75%,.25);
|
||||
}
|
||||
|
||||
.side-menu-widget-item[theme="dark"].selected {
|
||||
.side-menu-widget-item.selected {
|
||||
background: linear-gradient(hsl(206,61%,40%), hsl(206,61%,31%)) repeat-x top left !important;
|
||||
box-shadow: inset 0 1px 0 hsla(210,40%,83%,.15);
|
||||
}
|
||||
|
||||
.side-menu-widget-item[theme="light"].selected {
|
||||
/* Nothing here yet */
|
||||
}
|
||||
|
||||
.side-menu-widget-item.selected > .side-menu-widget-item-arrow {
|
||||
background-size: auto, 1px 100%;
|
||||
background-repeat: no-repeat;
|
||||
@ -426,10 +426,6 @@
|
||||
|
||||
/* VariablesView */
|
||||
|
||||
.variables-view-container {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.variables-view-empty-notice {
|
||||
color: GrayText;
|
||||
padding: 2px;
|
||||
@ -439,11 +435,6 @@
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.variables-view-scope:focus > .title {
|
||||
background: Highlight;
|
||||
color: HighlightText;
|
||||
}
|
||||
|
||||
.variables-view-scope > .variables-view-element-details:not(:empty) {
|
||||
-moz-margin-start: 2px;
|
||||
-moz-margin-end: 1px;
|
||||
@ -452,13 +443,12 @@
|
||||
/* Generic traits applied to both variables and properties */
|
||||
|
||||
.variable-or-property {
|
||||
transition: background 1s ease-in-out;
|
||||
color: #000;
|
||||
transition: background 1s ease-in-out, color 1s ease-in-out;
|
||||
}
|
||||
|
||||
.variable-or-property[changed] {
|
||||
background: rgba(255,255,0,0.65);
|
||||
transition-duration: 0.4s;
|
||||
color: black;
|
||||
transition-duration: .4s;
|
||||
}
|
||||
|
||||
.variable-or-property > .title > .value {
|
||||
@ -467,12 +457,6 @@
|
||||
-moz-padding-end: 4px;
|
||||
}
|
||||
|
||||
.variable-or-property:focus > .title {
|
||||
background: Highlight;
|
||||
color: HighlightText;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.variable-or-property[editable] > .title > .value {
|
||||
cursor: text;
|
||||
}
|
||||
@ -489,52 +473,22 @@
|
||||
}
|
||||
|
||||
.variables-view-variable:not(:last-child) {
|
||||
border-bottom: 1px solid #eee;
|
||||
border-bottom: 1px solid rgba(128, 128, 128, .15);
|
||||
}
|
||||
|
||||
.variables-view-variable > .title > .name {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.variables-view-variable:not(:focus) > .title > .name {
|
||||
color: #048;
|
||||
}
|
||||
|
||||
.variables-view-property:not(:focus) > .title > .name {
|
||||
color: #881090;
|
||||
}
|
||||
|
||||
/* Token value colors */
|
||||
|
||||
.variable-or-property:not(:focus) > .title > .token-undefined {
|
||||
color: #bbb;
|
||||
}
|
||||
|
||||
.variable-or-property:not(:focus) > .title > .token-null {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.variable-or-property:not(:focus) > .title > .token-boolean {
|
||||
color: #10c;
|
||||
}
|
||||
|
||||
.variable-or-property:not(:focus) > .title > .token-number {
|
||||
color: #c00;
|
||||
}
|
||||
|
||||
.variable-or-property:not(:focus) > .title > .token-string {
|
||||
color: #282;
|
||||
}
|
||||
|
||||
.variable-or-property:not(:focus) > .title > .token-other {
|
||||
color: #333;
|
||||
.variable-or-property:focus > .title > label {
|
||||
color: inherit !important;
|
||||
}
|
||||
|
||||
/* Custom configurable/enumerable/writable or frozen/sealed/extensible
|
||||
* variables and properties */
|
||||
|
||||
.variable-or-property[non-enumerable]:not([self]):not([exception]):not([return]):not([scope]) > .title > .name {
|
||||
opacity: 0.5;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.variable-or-property[non-configurable] > .title > .name {
|
||||
@ -545,6 +499,10 @@
|
||||
border-bottom: 1px dashed #f99;
|
||||
}
|
||||
|
||||
.variable-or-property[safe-getter] > .title > .name {
|
||||
border-bottom: 1px dashed #8b0;
|
||||
}
|
||||
|
||||
.variable-or-property-non-writable-icon {
|
||||
background: url("chrome://browser/skin/identity-icons-https.png") no-repeat;
|
||||
width: 16px;
|
||||
@ -571,27 +529,6 @@
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* Special variables and properties */
|
||||
|
||||
.variable-or-property[safe-getter] > .title > .name {
|
||||
border-bottom: 1px dashed #8b0;
|
||||
}
|
||||
|
||||
.variable-or-property[exception]:not(:focus) > .title > .name {
|
||||
color: #a00;
|
||||
text-shadow: 0 0 8px #fcc;
|
||||
}
|
||||
|
||||
.variable-or-property[return]:not(:focus) > .title > .name {
|
||||
color: #0a0;
|
||||
text-shadow: 0 0 8px #cfc;
|
||||
}
|
||||
|
||||
.variable-or-property[scope]:not(:focus) > .title > .name {
|
||||
color: #00a;
|
||||
text-shadow: 0 0 8px #ccf;
|
||||
}
|
||||
|
||||
/* Aligned values */
|
||||
|
||||
.variables-view-container[aligned-values] .title > .separator {
|
||||
@ -674,14 +611,13 @@
|
||||
.element-name-input {
|
||||
-moz-margin-start: -2px !important;
|
||||
-moz-margin-end: 2px !important;
|
||||
color: #048;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.element-value-input,
|
||||
.element-name-input {
|
||||
border: 1px solid #999 !important;
|
||||
box-shadow: 1px 2px 4px #aaa;
|
||||
border: 1px solid rgba(128, 128, 128, .5) !important;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
/* Variables and properties searching */
|
||||
|
@ -51,7 +51,8 @@
|
||||
background-color: rgba(0,0,0,0.5);
|
||||
}
|
||||
|
||||
.theme-bg-contrast { /* contrast bg color to attract attention on a container */
|
||||
.theme-bg-contrast,
|
||||
.variable-or-property[changed] { /* contrast bg color to attract attention on a container */
|
||||
background: #a18650;
|
||||
}
|
||||
|
||||
@ -73,7 +74,9 @@
|
||||
.theme-comment,
|
||||
.cm-s-mozilla .cm-meta,
|
||||
.cm-s-mozilla .cm-hr,
|
||||
.cm-s-mozilla .cm-comment { /* grey */
|
||||
.cm-s-mozilla .cm-comment,
|
||||
.variable-or-property .token-undefined,
|
||||
.variable-or-property .token-null { /* grey */
|
||||
color: #5c6773;
|
||||
}
|
||||
|
||||
@ -88,7 +91,9 @@
|
||||
}
|
||||
|
||||
.theme-fg-color1,
|
||||
.cm-s-mozilla .cm-number { /* green */
|
||||
.cm-s-mozilla .cm-number,
|
||||
.variable-or-property .token-number,
|
||||
.variable-or-property[return] > .title > .name { /* green */
|
||||
color: #5c9966;
|
||||
}
|
||||
|
||||
@ -97,14 +102,18 @@
|
||||
.cm-s-mozilla .cm-variable,
|
||||
.cm-s-mozilla .cm-def,
|
||||
.cm-s-mozilla .cm-property,
|
||||
.cm-s-mozilla .cm-qualifier { /* blue */
|
||||
.cm-s-mozilla .cm-qualifier,
|
||||
.variables-view-variable > .title > .name,
|
||||
.variable-or-property[scope] > .title > .name { /* blue */
|
||||
color: #3689b2;
|
||||
}
|
||||
|
||||
.theme-fg-color3,
|
||||
.cm-s-mozilla .cm-builtin,
|
||||
.cm-s-mozilla .cm-tag,
|
||||
.cm-s-mozilla .cm-header { /* pink/lavender */
|
||||
.cm-s-mozilla .cm-header,
|
||||
.variables-view-property > .title > .name,
|
||||
.variable-or-property[safe-getter] > .title > .name { /* pink/lavender */
|
||||
color: #a673bf;
|
||||
}
|
||||
|
||||
@ -120,14 +129,17 @@
|
||||
|
||||
.theme-fg-color6,
|
||||
.cm-s-mozilla .cm-string,
|
||||
.cm-s-mozilla .cm-string-2 { /* Orange */
|
||||
.cm-s-mozilla .cm-string-2,
|
||||
.variable-or-property .token-string { /* Orange */
|
||||
color: #b26b47;
|
||||
}
|
||||
|
||||
.theme-fg-color7,
|
||||
.cm-s-mozilla .cm-atom,
|
||||
.cm-s-mozilla .cm-quote,
|
||||
.cm-s-mozilla .cm-error { /* Red */
|
||||
.cm-s-mozilla .cm-error,
|
||||
.variable-or-property .token-boolean,
|
||||
.variable-or-property[exception] > .title > .name { /* Red */
|
||||
color: #bf5656;
|
||||
}
|
||||
|
||||
@ -148,6 +160,12 @@
|
||||
box-shadow: 0 0 0 1px rgba(0,0,0,0.5);
|
||||
}
|
||||
|
||||
.variables-view-scope:focus > .title,
|
||||
.variable-or-property:focus > .title {
|
||||
background: #3689b2; /* fg-color2 */
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* CodeMirror specific styles.
|
||||
* Best effort to match the existing theme, some of the colors
|
||||
* are duplicated here to prevent weirdness in the main theme. */
|
||||
|
@ -51,7 +51,8 @@
|
||||
background: #EFEFEF;
|
||||
}
|
||||
|
||||
.theme-bg-contrast { /* contrast bg color to attract attention on a container */
|
||||
.theme-bg-contrast,
|
||||
.variable-or-property[changed] { /* contrast bg color to attract attention on a container */
|
||||
background: #a18650;
|
||||
}
|
||||
|
||||
@ -72,7 +73,9 @@
|
||||
.theme-comment,
|
||||
.cm-s-mozilla .cm-meta,
|
||||
.cm-s-mozilla .cm-hr,
|
||||
.cm-s-mozilla .cm-comment { /* grey */
|
||||
.cm-s-mozilla .cm-comment,
|
||||
.variable-or-property .token-undefined,
|
||||
.variable-or-property .token-null { /* grey */
|
||||
color: hsl(90,2%,46%);
|
||||
}
|
||||
|
||||
@ -87,7 +90,9 @@
|
||||
}
|
||||
|
||||
.theme-fg-color1,
|
||||
.cm-s-mozilla .cm-number { /* green */
|
||||
.cm-s-mozilla .cm-number,
|
||||
.variable-or-property .token-number,
|
||||
.variable-or-property[return] > .title > .name { /* green */
|
||||
color: hsl(72,100%,27%);
|
||||
}
|
||||
|
||||
@ -96,14 +101,18 @@
|
||||
.cm-s-mozilla .cm-builtin,
|
||||
.cm-s-mozilla .cm-def,
|
||||
.cm-s-mozilla .cm-property,
|
||||
.cm-s-mozilla .cm-qualifier { /* blue */
|
||||
.cm-s-mozilla .cm-qualifier,
|
||||
.variables-view-variable > .title > .name,
|
||||
.variable-or-property[scope] > .title > .name { /* blue */
|
||||
color: hsl(208,56%,40%);
|
||||
}
|
||||
|
||||
.theme-fg-color3,
|
||||
.cm-s-mozilla .cm-variable,
|
||||
.cm-s-mozilla .cm-tag,
|
||||
.cm-s-mozilla .cm-header { /* dark blue */
|
||||
.cm-s-mozilla .cm-header,
|
||||
.variables-view-property > .title > .name,
|
||||
.variable-or-property[safe-getter] > .title > .name { /* dark blue */
|
||||
color: hsl(208,81%,21%)
|
||||
}
|
||||
|
||||
@ -119,14 +128,17 @@
|
||||
|
||||
.theme-fg-color6,
|
||||
.cm-s-mozilla .cm-string,
|
||||
.cm-s-mozilla .cm-string-2 { /* Orange */
|
||||
.cm-s-mozilla .cm-string-2,
|
||||
.variable-or-property .token-string { /* Orange */
|
||||
color: hsl(24,85%,39%);
|
||||
}
|
||||
|
||||
.theme-fg-color7,
|
||||
.cm-s-mozilla .cm-atom,
|
||||
.cm-s-mozilla .cm-quote,
|
||||
.cm-s-mozilla .cm-error { /* Red */
|
||||
.cm-s-mozilla .cm-error,
|
||||
.variable-or-property .token-boolean,
|
||||
.variable-or-property[exception] > .title > .name { /* Red */
|
||||
color: #bf5656;
|
||||
}
|
||||
|
||||
@ -147,6 +159,12 @@
|
||||
box-shadow: 0 0 0 1px #EFEFEF;
|
||||
}
|
||||
|
||||
.variables-view-scope:focus > .title,
|
||||
.variable-or-property:focus > .title {
|
||||
background: hsl(208,56%,40%); /* fg-color2 */
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* CodeMirror specific styles.
|
||||
* Best effort to match the existing theme, some of the colors
|
||||
* are duplicated here to prevent weirdness in the main theme. */
|
||||
|
@ -260,11 +260,15 @@
|
||||
}
|
||||
|
||||
.devtools-sidebar-tabs > tabs > tab {
|
||||
background-size: calc(100% - 2px) 100%, 1px 100%;
|
||||
background-size: calc(100% - 1px) 100%, 1px 100%;
|
||||
background-repeat: no-repeat;
|
||||
background-position: 1px, 0;
|
||||
}
|
||||
|
||||
.devtools-sidebar-tabs > tabs > tab:not(:last-of-type) {
|
||||
background-size: calc(100% - 2px) 100%, 1px 100%;
|
||||
}
|
||||
|
||||
.devtools-sidebar-tabs:-moz-locale-dir(rtl) > tabs > tab {
|
||||
background-position: calc(100% - 1px), 100%;
|
||||
}
|
||||
|
@ -291,11 +291,11 @@ a {
|
||||
.inlined-variables-view iframe {
|
||||
display: block;
|
||||
flex: 1;
|
||||
margin-top: 5px;
|
||||
margin-bottom: 15px;
|
||||
-moz-margin-end: 15px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 0 12px #dfdfdf;
|
||||
border: 1px solid rgba(128, 128, 128, .5);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
#webconsole-sidebar > tabs {
|
||||
@ -354,6 +354,10 @@ a {
|
||||
background: #131c26; /* mainBackgroundColor */
|
||||
}
|
||||
|
||||
.theme-dark .inlined-variables-view iframe {
|
||||
border-color: #333;
|
||||
}
|
||||
|
||||
.theme-light .jsterm-input-container {
|
||||
background-color: #fff; /* mainBackgroundColor */
|
||||
border-color: ThreeDShadow;
|
||||
@ -370,3 +374,8 @@ a {
|
||||
.theme-light .navigation-marker .url {
|
||||
background: #fff; /* mainBackgroundColor */
|
||||
}
|
||||
|
||||
.theme-light .inlined-variables-view iframe {
|
||||
border-color: #ccc;
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,10 @@
|
||||
min-width: 50px;
|
||||
}
|
||||
|
||||
#sources-pane > tabs {
|
||||
-moz-border-end: 1px solid #222426; /* Match the sources list's dark margin. */
|
||||
}
|
||||
|
||||
#sources-and-editor-splitter {
|
||||
-moz-border-start-color: transparent;
|
||||
}
|
||||
@ -20,7 +24,7 @@
|
||||
-moz-border-end: 1px solid #222426; /* Match the sources list's dark margin. */
|
||||
}
|
||||
|
||||
#sources-toolbar .devtools-toolbarbutton {
|
||||
#sources-toolbar > #sources-controls > .devtools-toolbarbutton {
|
||||
min-width: 32px;
|
||||
}
|
||||
|
||||
@ -87,15 +91,23 @@
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.list-widget-item:not(.selected):not(.empty):hover {
|
||||
.theme-light .list-widget-item:not(.selected):not(.empty):hover {
|
||||
background: linear-gradient(rgba(255,255,255,0.9), rgba(255,255,255,0.85)), Highlight;
|
||||
}
|
||||
|
||||
.list-widget-item.selected.light {
|
||||
.theme-light .list-widget-item.selected.light {
|
||||
background: linear-gradient(rgba(255,255,255,0.85), rgba(255,255,255,0.8)), Highlight;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.theme-dark .list-widget-item:not(.selected):not(.empty):hover {
|
||||
background: linear-gradient(rgba(255,255,255,0.1), rgba(255,255,255,0.05));
|
||||
}
|
||||
|
||||
.theme-dark .list-widget-item.selected.light {
|
||||
background: linear-gradient(rgba(255,255,255,0.05), rgba(255,255,255,0.025));
|
||||
}
|
||||
|
||||
.list-widget-item.selected {
|
||||
background: Highlight;
|
||||
color: HighlightText;
|
||||
@ -106,21 +118,52 @@
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
/* Stack frames view */
|
||||
/* Breadcrumbs stack frames view */
|
||||
|
||||
.breadcrumbs-widget-item {
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
.dbg-stackframe-details {
|
||||
-moz-padding-start: 4px;
|
||||
}
|
||||
|
||||
.dbg-stackframe-menuitem[checked] {
|
||||
margin-top: 3px;
|
||||
margin-bottom: 3px;
|
||||
outline: 1px solid #eee;
|
||||
font-weight: 600;
|
||||
/* Classic stack frames view */
|
||||
|
||||
.dbg-classic-stackframe {
|
||||
display: block;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.dbg-stackframe-menuitem-details {
|
||||
-moz-padding-start: 16px;
|
||||
.dbg-classic-stackframe-title {
|
||||
font-weight: 600;
|
||||
color: #046;
|
||||
}
|
||||
|
||||
.dbg-classic-stackframe-details:-moz-locale-dir(ltr) {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.dbg-classic-stackframe-details:-moz-locale-dir(rtl) {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.dbg-classic-stackframe-details-url {
|
||||
max-width: 90%;
|
||||
text-align: end;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.dbg-classic-stackframe-details-sep {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.dbg-classic-stackframe-details-line {
|
||||
color: #58b;
|
||||
}
|
||||
|
||||
#callstack-list .side-menu-widget-item.selected label {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Sources and breakpoints view */
|
||||
@ -180,8 +223,9 @@
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
#instruments-pane > tabpanels > tabpanel {
|
||||
background: #fff;
|
||||
#instruments-pane .side-menu-widget-container,
|
||||
#instruments-pane .side-menu-widget-empty-notice-container {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
/* Watch expressions view */
|
||||
@ -203,6 +247,7 @@
|
||||
|
||||
.dbg-expression-input {
|
||||
-moz-padding-start: 2px !important;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
/* Event listeners view */
|
||||
@ -227,6 +272,10 @@
|
||||
color: #666;
|
||||
}
|
||||
|
||||
#event-listeners .side-menu-widget-item.selected {
|
||||
background: none !important;
|
||||
}
|
||||
|
||||
/* Searchbox and the search operations help panel */
|
||||
|
||||
#searchbox {
|
||||
@ -380,6 +429,11 @@
|
||||
|
||||
/* Toolbar controls */
|
||||
|
||||
.devtools-sidebar-tabs > tabs > tab {
|
||||
min-height: 25px !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
#resumption-panel-desc {
|
||||
width: 200px;
|
||||
}
|
||||
@ -473,12 +527,17 @@
|
||||
max-height: 80vh;
|
||||
}
|
||||
|
||||
#body[layout=vertical] #sources-pane > tabs {
|
||||
-moz-border-end: none;
|
||||
}
|
||||
|
||||
#body[layout=vertical] #instruments-pane {
|
||||
margin: 0 !important;
|
||||
/* To prevent all the margin hacks to hide the sidebar. */
|
||||
}
|
||||
|
||||
#body[layout=vertical] .side-menu-widget-container {
|
||||
#body[layout=vertical] .side-menu-widget-container,
|
||||
#body[layout=vertical] .side-menu-widget-empty-notice-container {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
|
@ -312,6 +312,10 @@ box.requests-menu-status[code^="5"] {
|
||||
|
||||
/* SideMenuWidget */
|
||||
|
||||
.side-menu-widget-container {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.side-menu-widget-item[odd] {
|
||||
background: rgba(255,255,255,0.05);
|
||||
}
|
||||
@ -363,10 +367,6 @@ box.requests-menu-status[code^="5"] {
|
||||
-moz-padding-start: 3px;
|
||||
}
|
||||
|
||||
.variable-or-property:not(:focus) > .title > .token-string {
|
||||
color: #10c !important;
|
||||
}
|
||||
|
||||
/* Headers tabpanel */
|
||||
|
||||
#headers-summary-status,
|
||||
|
@ -285,15 +285,17 @@
|
||||
|
||||
/* SideMenuWidget container */
|
||||
|
||||
.side-menu-widget-container[with-arrows=true]:-moz-locale-dir(ltr) {
|
||||
.side-menu-widget-container:-moz-locale-dir(ltr),
|
||||
.side-menu-widget-empty-notice-container:-moz-locale-dir(ltr) {
|
||||
box-shadow: inset -1px 0 0 #222426;
|
||||
}
|
||||
|
||||
.side-menu-widget-container[with-arrows=true]:-moz-locale-dir(rtl) {
|
||||
.side-menu-widget-container:-moz-locale-dir(rtl),
|
||||
.side-menu-widget-empty-notice-container:-moz-locale-dir(rtl) {
|
||||
box-shadow: inset 1px 0 0 #222426;
|
||||
}
|
||||
|
||||
.side-menu-widget-container[with-arrows=true] .side-menu-widget-group {
|
||||
.side-menu-widget-group {
|
||||
/* To allow visibility of the dark margin shadow. */
|
||||
-moz-margin-end: 1px;
|
||||
}
|
||||
@ -332,7 +334,9 @@
|
||||
|
||||
.side-menu-widget-item[theme="light"] {
|
||||
border-top: 1px solid hsla(210,8%,75%,.25);
|
||||
border-bottom: 1px solid hsla(210,16%,76%,.1);
|
||||
margin-top: -1px;
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
|
||||
.side-menu-widget-item[theme="dark"]:last-of-type {
|
||||
@ -343,15 +347,11 @@
|
||||
box-shadow: inset 0 -1px 0 hsla(210,8%,75%,.25);
|
||||
}
|
||||
|
||||
.side-menu-widget-item[theme="dark"].selected {
|
||||
.side-menu-widget-item.selected {
|
||||
background: linear-gradient(hsl(206,61%,40%), hsl(206,61%,31%)) repeat-x top left !important;
|
||||
box-shadow: inset 0 1px 0 hsla(210,40%,83%,.15);
|
||||
}
|
||||
|
||||
.side-menu-widget-item[theme="light"].selected {
|
||||
/* Nothing here yet */
|
||||
}
|
||||
|
||||
.side-menu-widget-item.selected > .side-menu-widget-item-arrow {
|
||||
background-size: auto, 1px 100%;
|
||||
background-repeat: no-repeat;
|
||||
@ -429,10 +429,6 @@
|
||||
|
||||
/* VariablesView */
|
||||
|
||||
.variables-view-container {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.variables-view-empty-notice {
|
||||
color: GrayText;
|
||||
padding: 2px;
|
||||
@ -442,11 +438,6 @@
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.variables-view-scope:focus > .title {
|
||||
background: Highlight;
|
||||
color: HighlightText;
|
||||
}
|
||||
|
||||
.variables-view-scope > .variables-view-element-details:not(:empty) {
|
||||
-moz-margin-start: 2px;
|
||||
-moz-margin-end: 1px;
|
||||
@ -455,13 +446,12 @@
|
||||
/* Generic traits applied to both variables and properties */
|
||||
|
||||
.variable-or-property {
|
||||
transition: background 1s ease-in-out;
|
||||
color: #000;
|
||||
transition: background 1s ease-in-out, color 1s ease-in-out;
|
||||
}
|
||||
|
||||
.variable-or-property[changed] {
|
||||
background: rgba(255,255,0,0.65);
|
||||
transition-duration: 0.4s;
|
||||
color: black;
|
||||
transition-duration: .4s;
|
||||
}
|
||||
|
||||
.variable-or-property > .title > .value {
|
||||
@ -470,12 +460,6 @@
|
||||
-moz-padding-end: 4px;
|
||||
}
|
||||
|
||||
.variable-or-property:focus > .title {
|
||||
background: Highlight;
|
||||
color: HighlightText;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.variable-or-property[editable] > .title > .value {
|
||||
cursor: text;
|
||||
}
|
||||
@ -492,52 +476,22 @@
|
||||
}
|
||||
|
||||
.variables-view-variable:not(:last-child) {
|
||||
border-bottom: 1px solid #eee;
|
||||
border-bottom: 1px solid rgba(128, 128, 128, .15);
|
||||
}
|
||||
|
||||
.variables-view-variable > .title > .name {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.variables-view-variable:not(:focus) > .title > .name {
|
||||
color: #048;
|
||||
}
|
||||
|
||||
.variables-view-property:not(:focus) > .title > .name {
|
||||
color: #881090;
|
||||
}
|
||||
|
||||
/* Token value colors */
|
||||
|
||||
.variable-or-property:not(:focus) > .title > .token-undefined {
|
||||
color: #bbb;
|
||||
}
|
||||
|
||||
.variable-or-property:not(:focus) > .title > .token-null {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.variable-or-property:not(:focus) > .title > .token-boolean {
|
||||
color: #10c;
|
||||
}
|
||||
|
||||
.variable-or-property:not(:focus) > .title > .token-number {
|
||||
color: #c00;
|
||||
}
|
||||
|
||||
.variable-or-property:not(:focus) > .title > .token-string {
|
||||
color: #282;
|
||||
}
|
||||
|
||||
.variable-or-property:not(:focus) > .title > .token-other {
|
||||
color: #333;
|
||||
.variable-or-property:focus > .title > label {
|
||||
color: inherit !important;
|
||||
}
|
||||
|
||||
/* Custom configurable/enumerable/writable or frozen/sealed/extensible
|
||||
* variables and properties */
|
||||
|
||||
.variable-or-property[non-enumerable]:not([self]):not([exception]):not([return]):not([scope]) > .title > .name {
|
||||
opacity: 0.5;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.variable-or-property[non-configurable] > .title > .name {
|
||||
@ -548,6 +502,10 @@
|
||||
border-bottom: 1px dashed #f99;
|
||||
}
|
||||
|
||||
.variable-or-property[safe-getter] > .title > .name {
|
||||
border-bottom: 1px dashed #8b0;
|
||||
}
|
||||
|
||||
.variable-or-property-non-writable-icon {
|
||||
background: url("chrome://browser/skin/identity-icons-https.png") no-repeat;
|
||||
width: 16px;
|
||||
@ -574,27 +532,6 @@
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* Special variables and properties */
|
||||
|
||||
.variable-or-property[safe-getter] > .title > .name {
|
||||
border-bottom: 1px dashed #8b0;
|
||||
}
|
||||
|
||||
.variable-or-property[exception]:not(:focus) > .title > .name {
|
||||
color: #a00;
|
||||
text-shadow: 0 0 8px #fcc;
|
||||
}
|
||||
|
||||
.variable-or-property[return]:not(:focus) > .title > .name {
|
||||
color: #0a0;
|
||||
text-shadow: 0 0 8px #cfc;
|
||||
}
|
||||
|
||||
.variable-or-property[scope]:not(:focus) > .title > .name {
|
||||
color: #00a;
|
||||
text-shadow: 0 0 8px #ccf;
|
||||
}
|
||||
|
||||
/* Aligned values */
|
||||
|
||||
.variables-view-container[aligned-values] .title > .separator {
|
||||
@ -677,14 +614,13 @@
|
||||
.element-name-input {
|
||||
-moz-margin-start: -2px !important;
|
||||
-moz-margin-end: 2px !important;
|
||||
color: #048;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.element-value-input,
|
||||
.element-name-input {
|
||||
border: 1px solid #999 !important;
|
||||
box-shadow: 1px 2px 4px #aaa;
|
||||
border: 1px solid rgba(128, 128, 128, .5) !important;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
/* Variables and properties searching */
|
||||
|
31
build/autoconf/icu.m4
Normal file
31
build/autoconf/icu.m4
Normal file
@ -0,0 +1,31 @@
|
||||
dnl This Source Code Form is subject to the terms of the Mozilla Public
|
||||
dnl License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
dnl Set the MOZ_ICU_VERSION variable to denote the current version of the
|
||||
dnl ICU library, and also the MOZ_SHARED_ICU which would be true if we are
|
||||
dnl linking against a shared library of ICU, either one that we build from
|
||||
dnl our copy of ICU or the system provided library.
|
||||
|
||||
AC_DEFUN([MOZ_CONFIG_ICU], [
|
||||
icudir="$_topsrcdir/intl/icu/source"
|
||||
if test ! -d "$icudir"; then
|
||||
icudir="$_topsrcdir/../../intl/icu/source"
|
||||
if test ! -d "$icudir"; then
|
||||
AC_MSG_ERROR([Cannot find the ICU directory])
|
||||
fi
|
||||
fi
|
||||
|
||||
version=`sed -n 's/^[[:space:]]*#[[:space:]]*define[[:space:]][[:space:]]*U_ICU_VERSION_MAJOR_NUM[[:space:]][[:space:]]*\([0-9][0-9]*\)[[:space:]]*$/\1/p' "$icudir/common/unicode/uvernum.h"`
|
||||
if test x"$version" = x; then
|
||||
AC_MSG_ERROR([cannot determine icu version number from uvernum.h header file $lineno])
|
||||
fi
|
||||
MOZ_ICU_VERSION="$version"
|
||||
|
||||
if test -n "${JS_SHARED_LIBRARY}${MOZ_NATIVE_ICU}"; then
|
||||
MOZ_SHARED_ICU=1
|
||||
fi
|
||||
|
||||
AC_SUBST(MOZ_ICU_VERSION)
|
||||
AC_SUBST(MOZ_SHARED_ICU)
|
||||
])
|
@ -4,14 +4,12 @@
|
||||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.ArrayList;
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
import org.mozilla.gecko.gfx.GeckoLayerClient;
|
||||
import org.mozilla.gecko.gfx.GeckoLayerClient.DrawListener;
|
||||
import org.mozilla.gecko.mozglue.GeckoLoader;
|
||||
import org.mozilla.gecko.sqlite.SQLiteBridge;
|
||||
import org.mozilla.gecko.util.GeckoEventListener;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Instrumentation;
|
||||
@ -24,112 +22,65 @@ import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewConfiguration;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.ArrayList;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import com.jayway.android.robotium.solo.Solo;
|
||||
|
||||
import static org.mozilla.gecko.FennecNativeDriver.LogLevel;
|
||||
|
||||
public class FennecNativeActions implements Actions {
|
||||
private static final String LOGTAG = "FennecNativeActions";
|
||||
|
||||
private Solo mSolo;
|
||||
private Instrumentation mInstr;
|
||||
private Activity mGeckoApp;
|
||||
private Assert mAsserter;
|
||||
|
||||
// Objects for reflexive access of fennec classes.
|
||||
private ClassLoader mClassLoader;
|
||||
private Class mApiClass;
|
||||
private Class mEventListenerClass;
|
||||
private Class mDrawListenerClass;
|
||||
private Method mRegisterEventListener;
|
||||
private Method mUnregisterEventListener;
|
||||
private Method mBroadcastEvent;
|
||||
private Method mPreferencesGetEvent;
|
||||
private Method mPreferencesObserveEvent;
|
||||
private Method mPreferencesRemoveObserversEvent;
|
||||
private Method mSetDrawListener;
|
||||
private Method mQuerySql;
|
||||
private Object mRobocopApi;
|
||||
|
||||
private static final String LOGTAG = "FennecNativeActions";
|
||||
|
||||
public FennecNativeActions(Activity activity, Solo robocop, Instrumentation instrumentation, Assert asserter) {
|
||||
mSolo = robocop;
|
||||
mInstr = instrumentation;
|
||||
mGeckoApp = activity;
|
||||
mAsserter = asserter;
|
||||
// Set up reflexive access of java classes and methods.
|
||||
try {
|
||||
mClassLoader = activity.getClassLoader();
|
||||
|
||||
mApiClass = mClassLoader.loadClass("org.mozilla.gecko.RobocopAPI");
|
||||
mEventListenerClass = mClassLoader.loadClass("org.mozilla.gecko.util.GeckoEventListener");
|
||||
mDrawListenerClass = mClassLoader.loadClass("org.mozilla.gecko.gfx.GeckoLayerClient$DrawListener");
|
||||
|
||||
mRegisterEventListener = mApiClass.getMethod("registerEventListener", String.class, mEventListenerClass);
|
||||
mUnregisterEventListener = mApiClass.getMethod("unregisterEventListener", String.class, mEventListenerClass);
|
||||
mBroadcastEvent = mApiClass.getMethod("broadcastEvent", String.class, String.class);
|
||||
mPreferencesGetEvent = mApiClass.getMethod("preferencesGetEvent", Integer.TYPE, String[].class);
|
||||
mPreferencesObserveEvent = mApiClass.getMethod("preferencesObserveEvent", Integer.TYPE, String[].class);
|
||||
mPreferencesRemoveObserversEvent = mApiClass.getMethod("preferencesRemoveObserversEvent", Integer.TYPE);
|
||||
mSetDrawListener = mApiClass.getMethod("setDrawListener", mDrawListenerClass);
|
||||
mQuerySql = mApiClass.getMethod("querySql", String.class, String.class);
|
||||
|
||||
mRobocopApi = mApiClass.getConstructor(Activity.class).newInstance(activity);
|
||||
} catch (Exception e) {
|
||||
FennecNativeDriver.log(LogLevel.ERROR, e);
|
||||
}
|
||||
}
|
||||
|
||||
class wakeInvocationHandler implements InvocationHandler {
|
||||
private final GeckoEventExpecter mEventExpecter;
|
||||
|
||||
public wakeInvocationHandler(GeckoEventExpecter expecter) {
|
||||
mEventExpecter = expecter;
|
||||
}
|
||||
|
||||
public Object invoke(Object proxy, Method method, Object[] args) {
|
||||
String methodName = method.getName();
|
||||
//Depending on the method, return a completely different type.
|
||||
if(methodName.equals("toString")) {
|
||||
return this.toString();
|
||||
}
|
||||
if(methodName.equals("equals")) {
|
||||
return
|
||||
args[0] == null ? false :
|
||||
this.toString().equals(args[0].toString());
|
||||
}
|
||||
if(methodName.equals("clone")) {
|
||||
return this;
|
||||
}
|
||||
if(methodName.equals("hashCode")) {
|
||||
return 314;
|
||||
}
|
||||
FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG,
|
||||
"Waking up on "+methodName);
|
||||
mEventExpecter.notifyOfEvent(args);
|
||||
return null;
|
||||
}
|
||||
GeckoLoader.loadSQLiteLibs(activity, activity.getApplication().getPackageResourcePath());
|
||||
}
|
||||
|
||||
class GeckoEventExpecter implements RepeatedEventExpecter {
|
||||
private final String mGeckoEvent;
|
||||
private Object[] mRegistrationParams;
|
||||
private boolean mEventEverReceived;
|
||||
private String mEventData;
|
||||
private BlockingQueue<String> mEventDataQueue;
|
||||
private static final int MAX_WAIT_MS = 90000;
|
||||
|
||||
GeckoEventExpecter(String geckoEvent, Object[] registrationParams) {
|
||||
private volatile boolean mIsRegistered;
|
||||
|
||||
private final String mGeckoEvent;
|
||||
private final GeckoEventListener mListener;
|
||||
|
||||
private volatile boolean mEventEverReceived;
|
||||
private String mEventData;
|
||||
private BlockingQueue<String> mEventDataQueue;
|
||||
|
||||
GeckoEventExpecter(final String geckoEvent) {
|
||||
if (TextUtils.isEmpty(geckoEvent)) {
|
||||
throw new IllegalArgumentException("geckoEvent must not be empty");
|
||||
}
|
||||
if (registrationParams == null || registrationParams.length == 0) {
|
||||
throw new IllegalArgumentException("registrationParams must not be empty");
|
||||
}
|
||||
|
||||
mGeckoEvent = geckoEvent;
|
||||
mRegistrationParams = registrationParams;
|
||||
mEventDataQueue = new LinkedBlockingQueue<String>();
|
||||
|
||||
final GeckoEventExpecter expecter = this;
|
||||
mListener = new GeckoEventListener() {
|
||||
@Override
|
||||
public void handleMessage(final String event, final JSONObject message) {
|
||||
FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG,
|
||||
"handleMessage called for: " + event + "; expecting: " + mGeckoEvent);
|
||||
mAsserter.is(event, mGeckoEvent, "Given message occurred for registered event");
|
||||
|
||||
expecter.notifyOfEvent(message);
|
||||
}
|
||||
};
|
||||
|
||||
GeckoAppShell.registerEventListener(mGeckoEvent, mListener);
|
||||
mIsRegistered = true;
|
||||
}
|
||||
|
||||
public void blockForEvent() {
|
||||
@ -137,9 +88,10 @@ public class FennecNativeActions implements Actions {
|
||||
}
|
||||
|
||||
private void blockForEvent(long millis, boolean failOnTimeout) {
|
||||
if (mRegistrationParams == null) {
|
||||
if (!mIsRegistered) {
|
||||
throw new IllegalStateException("listener not registered");
|
||||
}
|
||||
|
||||
try {
|
||||
mEventData = mEventDataQueue.poll(millis, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException ie) {
|
||||
@ -161,12 +113,13 @@ public class FennecNativeActions implements Actions {
|
||||
}
|
||||
|
||||
public void blockUntilClear(long millis) {
|
||||
if (mRegistrationParams == null) {
|
||||
if (!mIsRegistered) {
|
||||
throw new IllegalStateException("listener not registered");
|
||||
}
|
||||
if (millis <= 0) {
|
||||
throw new IllegalArgumentException("millis must be > 0");
|
||||
}
|
||||
|
||||
// wait for at least one event
|
||||
try {
|
||||
mEventData = mEventDataQueue.poll(MAX_WAIT_MS, TimeUnit.MILLISECONDS);
|
||||
@ -205,139 +158,82 @@ public class FennecNativeActions implements Actions {
|
||||
}
|
||||
|
||||
public void unregisterListener() {
|
||||
if (mRegistrationParams == null) {
|
||||
if (!mIsRegistered) {
|
||||
throw new IllegalStateException("listener not registered");
|
||||
}
|
||||
try {
|
||||
FennecNativeDriver.log(LogLevel.INFO, "EventExpecter: no longer listening for "+mGeckoEvent);
|
||||
mUnregisterEventListener.invoke(mRobocopApi, mRegistrationParams);
|
||||
mRegistrationParams = null;
|
||||
} catch (IllegalAccessException e) {
|
||||
FennecNativeDriver.log(LogLevel.ERROR, e);
|
||||
} catch (InvocationTargetException e) {
|
||||
FennecNativeDriver.log(LogLevel.ERROR, e);
|
||||
}
|
||||
|
||||
FennecNativeDriver.log(LogLevel.INFO,
|
||||
"EventExpecter: no longer listening for " + mGeckoEvent);
|
||||
|
||||
GeckoAppShell.unregisterEventListener(mGeckoEvent, mListener);
|
||||
mIsRegistered = false;
|
||||
}
|
||||
|
||||
public synchronized boolean eventReceived() {
|
||||
public boolean eventReceived() {
|
||||
return mEventEverReceived;
|
||||
}
|
||||
|
||||
void notifyOfEvent(Object[] args) {
|
||||
void notifyOfEvent(final JSONObject message) {
|
||||
FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG,
|
||||
"received event " + mGeckoEvent);
|
||||
synchronized (this) {
|
||||
mEventEverReceived = true;
|
||||
}
|
||||
"received event " + mGeckoEvent);
|
||||
|
||||
mEventEverReceived = true;
|
||||
|
||||
try {
|
||||
mEventDataQueue.put(args[1].toString());
|
||||
mEventDataQueue.put(message.toString());
|
||||
} catch (InterruptedException e) {
|
||||
FennecNativeDriver.log(LogLevel.ERROR,
|
||||
"EventExpecter dropped event: "+args[1].toString());
|
||||
FennecNativeDriver.log(LogLevel.ERROR, e);
|
||||
"EventExpecter dropped event: " + message.toString(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public RepeatedEventExpecter expectGeckoEvent(String geckoEvent) {
|
||||
FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG,
|
||||
"waiting for "+geckoEvent);
|
||||
try {
|
||||
Object[] finalParams = new Object[2];
|
||||
finalParams[0] = geckoEvent;
|
||||
GeckoEventExpecter expecter = new GeckoEventExpecter(geckoEvent, finalParams);
|
||||
wakeInvocationHandler wIH = new wakeInvocationHandler(expecter);
|
||||
Object proxy = Proxy.newProxyInstance(mClassLoader, new Class[] { mEventListenerClass }, wIH);
|
||||
finalParams[1] = proxy;
|
||||
|
||||
mRegisterEventListener.invoke(mRobocopApi, finalParams);
|
||||
return expecter;
|
||||
} catch (IllegalAccessException e) {
|
||||
FennecNativeDriver.log(LogLevel.ERROR, e);
|
||||
} catch (InvocationTargetException e) {
|
||||
FennecNativeDriver.log(LogLevel.ERROR, e);
|
||||
}
|
||||
return null;
|
||||
public RepeatedEventExpecter expectGeckoEvent(final String geckoEvent) {
|
||||
FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG, "waiting for " + geckoEvent);
|
||||
return new GeckoEventExpecter(geckoEvent);
|
||||
}
|
||||
|
||||
public void sendGeckoEvent(String geckoEvent, String data) {
|
||||
try {
|
||||
mBroadcastEvent.invoke(mRobocopApi, geckoEvent, data);
|
||||
} catch (IllegalAccessException e) {
|
||||
FennecNativeDriver.log(LogLevel.ERROR, e);
|
||||
} catch (InvocationTargetException e) {
|
||||
FennecNativeDriver.log(LogLevel.ERROR, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendPreferencesEvent(Method method, int requestId, String[] prefNames) {
|
||||
try {
|
||||
method.invoke(mRobocopApi, requestId, prefNames);
|
||||
} catch (IllegalAccessException e) {
|
||||
FennecNativeDriver.log(LogLevel.ERROR, e);
|
||||
} catch (InvocationTargetException e) {
|
||||
FennecNativeDriver.log(LogLevel.ERROR, e);
|
||||
}
|
||||
public void sendGeckoEvent(final String geckoEvent, final String data) {
|
||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent(geckoEvent, data));
|
||||
}
|
||||
|
||||
public void sendPreferencesGetEvent(int requestId, String[] prefNames) {
|
||||
sendPreferencesEvent(mPreferencesGetEvent, requestId, prefNames);
|
||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createPreferencesGetEvent(requestId, prefNames));
|
||||
}
|
||||
|
||||
public void sendPreferencesObserveEvent(int requestId, String[] prefNames) {
|
||||
sendPreferencesEvent(mPreferencesObserveEvent, requestId, prefNames);
|
||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createPreferencesObserveEvent(requestId, prefNames));
|
||||
}
|
||||
|
||||
public void sendPreferencesRemoveObserversEvent(int requestId) {
|
||||
try {
|
||||
mPreferencesRemoveObserversEvent.invoke(mRobocopApi, requestId);
|
||||
} catch (IllegalAccessException e) {
|
||||
FennecNativeDriver.log(LogLevel.ERROR, e);
|
||||
} catch (InvocationTargetException e) {
|
||||
FennecNativeDriver.log(LogLevel.ERROR, e);
|
||||
}
|
||||
}
|
||||
|
||||
class DrawListenerProxy implements InvocationHandler {
|
||||
private final PaintExpecter mPaintExpecter;
|
||||
|
||||
DrawListenerProxy(PaintExpecter paintExpecter) {
|
||||
mPaintExpecter = paintExpecter;
|
||||
}
|
||||
|
||||
public Object invoke(Object proxy, Method method, Object[] args) {
|
||||
String methodName = method.getName();
|
||||
if ("drawFinished".equals(methodName)) {
|
||||
FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG,
|
||||
"Received drawFinished notification");
|
||||
mPaintExpecter.notifyOfEvent(args);
|
||||
} else if ("toString".equals(methodName)) {
|
||||
return "DrawListenerProxy";
|
||||
} else if ("equals".equals(methodName)) {
|
||||
return false;
|
||||
} else if ("hashCode".equals(methodName)) {
|
||||
return 0;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createPreferencesRemoveObserversEvent(requestId));
|
||||
}
|
||||
|
||||
class PaintExpecter implements RepeatedEventExpecter {
|
||||
private boolean mPaintDone;
|
||||
private boolean mListening;
|
||||
private static final int MAX_WAIT_MS = 90000;
|
||||
|
||||
PaintExpecter() throws IllegalAccessException, InvocationTargetException {
|
||||
Object proxy = Proxy.newProxyInstance(mClassLoader, new Class[] { mDrawListenerClass }, new DrawListenerProxy(this));
|
||||
mSetDrawListener.invoke(mRobocopApi, proxy);
|
||||
private boolean mPaintDone;
|
||||
private boolean mListening;
|
||||
|
||||
private final GeckoLayerClient mLayerClient;
|
||||
|
||||
PaintExpecter() {
|
||||
final PaintExpecter expecter = this;
|
||||
mLayerClient = GeckoAppShell.getLayerView().getLayerClient();
|
||||
mLayerClient.setDrawListener(new DrawListener() {
|
||||
@Override
|
||||
public void drawFinished() {
|
||||
FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG,
|
||||
"Received drawFinished notification");
|
||||
expecter.notifyOfEvent();
|
||||
}
|
||||
});
|
||||
mListening = true;
|
||||
}
|
||||
|
||||
void notifyOfEvent(Object[] args) {
|
||||
synchronized (this) {
|
||||
mPaintDone = true;
|
||||
this.notifyAll();
|
||||
}
|
||||
private synchronized void notifyOfEvent() {
|
||||
mPaintDone = true;
|
||||
this.notifyAll();
|
||||
}
|
||||
|
||||
private synchronized void blockForEvent(long millis, boolean failOnTimeout) {
|
||||
@ -431,23 +327,16 @@ public class FennecNativeActions implements Actions {
|
||||
if (!mListening) {
|
||||
throw new IllegalStateException("listener not registered");
|
||||
}
|
||||
try {
|
||||
FennecNativeDriver.log(LogLevel.INFO, "PaintExpecter: no longer listening for events");
|
||||
mListening = false;
|
||||
mSetDrawListener.invoke(mRobocopApi, (Object)null);
|
||||
} catch (Exception e) {
|
||||
FennecNativeDriver.log(LogLevel.ERROR, e);
|
||||
}
|
||||
|
||||
FennecNativeDriver.log(LogLevel.INFO,
|
||||
"PaintExpecter: no longer listening for events");
|
||||
mLayerClient.setDrawListener(null);
|
||||
mListening = false;
|
||||
}
|
||||
}
|
||||
|
||||
public RepeatedEventExpecter expectPaint() {
|
||||
try {
|
||||
return new PaintExpecter();
|
||||
} catch (Exception e) {
|
||||
FennecNativeDriver.log(LogLevel.ERROR, e);
|
||||
return null;
|
||||
}
|
||||
return new PaintExpecter();
|
||||
}
|
||||
|
||||
public void sendSpecialKey(SpecialKey button) {
|
||||
@ -495,14 +384,7 @@ public class FennecNativeActions implements Actions {
|
||||
mSolo.drag(startingX, endingX, startingY, endingY, 10);
|
||||
}
|
||||
|
||||
public Cursor querySql(String dbPath, String sql) {
|
||||
try {
|
||||
return (Cursor)mQuerySql.invoke(mRobocopApi, dbPath, sql);
|
||||
} catch(InvocationTargetException ex) {
|
||||
Log.e(LOGTAG, "Error invoking method", ex);
|
||||
} catch(IllegalAccessException ex) {
|
||||
Log.e(LOGTAG, "Error using field", ex);
|
||||
}
|
||||
return null;
|
||||
public Cursor querySql(final String dbPath, final String sql) {
|
||||
return new SQLiteBridge(dbPath).rawQuery(sql, null);
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,10 @@
|
||||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import org.mozilla.gecko.gfx.LayerView;
|
||||
import org.mozilla.gecko.gfx.PanningPerfAPI;
|
||||
import org.mozilla.gecko.util.GeckoEventListener;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.DataOutputStream;
|
||||
@ -20,11 +24,6 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.opengl.GLSurfaceView;
|
||||
import android.view.View;
|
||||
@ -46,18 +45,6 @@ public class FennecNativeDriver implements Driver {
|
||||
private static String mLogFile = null;
|
||||
private static LogLevel mLogLevel = LogLevel.INFO;
|
||||
|
||||
// Objects for reflexive access of fennec classes.
|
||||
private ClassLoader mClassLoader;
|
||||
private Class mApiClass;
|
||||
private Class mEventListenerClass;
|
||||
private Method mRegisterEventListener;
|
||||
private Method mGetPixels;
|
||||
private Method mStartFrameRecording;
|
||||
private Method mStopFrameRecording;
|
||||
private Method mStartCheckerboardRecording;
|
||||
private Method mStopCheckerboardRecording;
|
||||
private Object mRobocopApi;
|
||||
|
||||
public enum LogLevel {
|
||||
DEBUG(1),
|
||||
INFO(2),
|
||||
@ -83,25 +70,6 @@ public class FennecNativeDriver implements Driver {
|
||||
|
||||
// Set up table of fennec_ids.
|
||||
mLocators = convertTextToTable(getFile(mRootPath + "/fennec_ids.txt"));
|
||||
|
||||
// Set up reflexive access of java classes and methods.
|
||||
try {
|
||||
mClassLoader = activity.getClassLoader();
|
||||
|
||||
mApiClass = mClassLoader.loadClass("org.mozilla.gecko.RobocopAPI");
|
||||
mEventListenerClass = mClassLoader.loadClass("org.mozilla.gecko.util.GeckoEventListener");
|
||||
|
||||
mRegisterEventListener = mApiClass.getMethod("registerEventListener", String.class, mEventListenerClass);
|
||||
mGetPixels = mApiClass.getMethod("getViewPixels", View.class);
|
||||
mStartFrameRecording = mApiClass.getDeclaredMethod("startFrameTimeRecording");
|
||||
mStopFrameRecording = mApiClass.getDeclaredMethod("stopFrameTimeRecording");
|
||||
mStartCheckerboardRecording = mApiClass.getDeclaredMethod("startCheckerboardRecording");
|
||||
mStopCheckerboardRecording = mApiClass.getDeclaredMethod("stopCheckerboardRecording");
|
||||
|
||||
mRobocopApi = mApiClass.getConstructor(Activity.class).newInstance(activity);
|
||||
} catch (Exception e) {
|
||||
log(LogLevel.ERROR, e);
|
||||
}
|
||||
}
|
||||
|
||||
//Information on the location of the Gecko Frame.
|
||||
@ -172,99 +140,59 @@ public class FennecNativeDriver implements Driver {
|
||||
}
|
||||
|
||||
public void startFrameRecording() {
|
||||
try {
|
||||
mStartFrameRecording.invoke(null);
|
||||
} catch (IllegalAccessException e) {
|
||||
log(LogLevel.ERROR, e);
|
||||
} catch (InvocationTargetException e) {
|
||||
log(LogLevel.ERROR, e);
|
||||
}
|
||||
PanningPerfAPI.startFrameTimeRecording();
|
||||
}
|
||||
|
||||
public int stopFrameRecording() {
|
||||
try {
|
||||
List<Long> frames = (List<Long>)mStopFrameRecording.invoke(null);
|
||||
int badness = 0;
|
||||
for (int i = 1; i < frames.size(); i++) {
|
||||
long frameTime = frames.get(i) - frames.get(i - 1);
|
||||
int delay = (int)(frameTime - FRAME_TIME_THRESHOLD);
|
||||
// for each frame we miss, add the square of the delay. This
|
||||
// makes large delays much worse than small delays.
|
||||
if (delay > 0) {
|
||||
badness += delay * delay;
|
||||
}
|
||||
final List<Long> frames = PanningPerfAPI.stopFrameTimeRecording();
|
||||
int badness = 0;
|
||||
for (int i = 1; i < frames.size(); i++) {
|
||||
long frameTime = frames.get(i) - frames.get(i - 1);
|
||||
int delay = (int)(frameTime - FRAME_TIME_THRESHOLD);
|
||||
// for each frame we miss, add the square of the delay. This
|
||||
// makes large delays much worse than small delays.
|
||||
if (delay > 0) {
|
||||
badness += delay * delay;
|
||||
}
|
||||
// Don't do any averaging of the numbers because really we want to
|
||||
// know how bad the jank was at its worst
|
||||
return badness;
|
||||
} catch (IllegalAccessException e) {
|
||||
log(LogLevel.ERROR, e);
|
||||
} catch (InvocationTargetException e) {
|
||||
log(LogLevel.ERROR, e);
|
||||
}
|
||||
|
||||
// higher values are worse, and the test failing is the worst!
|
||||
return Integer.MAX_VALUE;
|
||||
// Don't do any averaging of the numbers because really we want to
|
||||
// know how bad the jank was at its worst
|
||||
return badness;
|
||||
}
|
||||
|
||||
public void startCheckerboardRecording() {
|
||||
try {
|
||||
mStartCheckerboardRecording.invoke(null);
|
||||
} catch (IllegalAccessException e) {
|
||||
log(LogLevel.ERROR, e);
|
||||
} catch (InvocationTargetException e) {
|
||||
log(LogLevel.ERROR, e);
|
||||
}
|
||||
PanningPerfAPI.startCheckerboardRecording();
|
||||
}
|
||||
|
||||
public float stopCheckerboardRecording() {
|
||||
try {
|
||||
List<Float> checkerboard = (List<Float>)mStopCheckerboardRecording.invoke(null);
|
||||
float total = 0;
|
||||
for (float val : checkerboard) {
|
||||
total += val;
|
||||
}
|
||||
return total * 100.0f;
|
||||
} catch (IllegalAccessException e) {
|
||||
log(LogLevel.ERROR, e);
|
||||
} catch (InvocationTargetException e) {
|
||||
log(LogLevel.ERROR, e);
|
||||
final List<Float> checkerboard = PanningPerfAPI.stopCheckerboardRecording();
|
||||
float total = 0;
|
||||
for (float val : checkerboard) {
|
||||
total += val;
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
return total * 100.0f;
|
||||
}
|
||||
|
||||
private View getSurfaceView() {
|
||||
ArrayList<View> views = mSolo.getCurrentViews();
|
||||
try {
|
||||
Class c = Class.forName("org.mozilla.gecko.gfx.LayerView");
|
||||
for (View v : views) {
|
||||
if (c.isInstance(v)) {
|
||||
return v;
|
||||
}
|
||||
private LayerView getSurfaceView() {
|
||||
final LayerView layerView = mSolo.getView(LayerView.class, 0);
|
||||
|
||||
if (layerView == null) {
|
||||
log(LogLevel.WARN, "getSurfaceView could not find LayerView");
|
||||
for (final View v : mSolo.getViews()) {
|
||||
log(LogLevel.WARN, " View: " + v);
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
log(LogLevel.ERROR, e);
|
||||
}
|
||||
log(LogLevel.WARN, "getSurfaceView could not find LayerView");
|
||||
for (View v : views) {
|
||||
log(LogLevel.WARN, v.toString());
|
||||
}
|
||||
return null;
|
||||
return layerView;
|
||||
}
|
||||
|
||||
public PaintedSurface getPaintedSurface() {
|
||||
View view = getSurfaceView();
|
||||
final LayerView view = getSurfaceView();
|
||||
if (view == null) {
|
||||
return null;
|
||||
}
|
||||
IntBuffer pixelBuffer;
|
||||
try {
|
||||
pixelBuffer = (IntBuffer)mGetPixels.invoke(mRobocopApi, view);
|
||||
} catch (Exception e) {
|
||||
log(LogLevel.ERROR, e);
|
||||
return null;
|
||||
}
|
||||
|
||||
final IntBuffer pixelBuffer = view.getPixels();
|
||||
|
||||
// now we need to (1) flip the image, because GL likes to do things up-side-down,
|
||||
// and (2) rearrange the bits from AGBR-8888 to ARGB-8888.
|
||||
@ -312,27 +240,6 @@ public class FennecNativeDriver implements Driver {
|
||||
public int mScrollHeight=0;
|
||||
public int mPageHeight=10;
|
||||
|
||||
class scrollHandler implements InvocationHandler {
|
||||
public scrollHandler(){};
|
||||
public Object invoke(Object proxy, Method method, Object[] args) {
|
||||
try {
|
||||
// Disect the JSON object into the appropriate variables
|
||||
JSONObject jo = ((JSONObject)args[1]);
|
||||
mScrollHeight = jo.getInt("y");
|
||||
mHeight = jo.getInt("cheight");
|
||||
// We don't want a height of 0. That means it's a bad response.
|
||||
if (mHeight > 0) {
|
||||
mPageHeight = jo.getInt("height");
|
||||
}
|
||||
|
||||
} catch( Throwable e) {
|
||||
FennecNativeDriver.log(FennecNativeDriver.LogLevel.WARN,
|
||||
"WARNING: ScrollReceived, but read wrong!");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public int getScrollHeight() {
|
||||
return mScrollHeight;
|
||||
}
|
||||
@ -344,20 +251,23 @@ public class FennecNativeDriver implements Driver {
|
||||
}
|
||||
|
||||
public void setupScrollHandling() {
|
||||
//Setup scrollHandler to catch "robocop:scroll" events.
|
||||
try {
|
||||
Class [] interfaces = new Class[1];
|
||||
interfaces[0] = mEventListenerClass;
|
||||
Object[] finalParams = new Object[2];
|
||||
finalParams[0] = "robocop:scroll";
|
||||
finalParams[1] = Proxy.newProxyInstance(mClassLoader, interfaces, new scrollHandler());
|
||||
mRegisterEventListener.invoke(mRobocopApi, finalParams);
|
||||
} catch (IllegalAccessException e) {
|
||||
log(LogLevel.ERROR, e);
|
||||
} catch (InvocationTargetException e) {
|
||||
log(LogLevel.ERROR, e);
|
||||
}
|
||||
|
||||
GeckoAppShell.registerEventListener("robocop:scroll", new GeckoEventListener() {
|
||||
@Override
|
||||
public void handleMessage(final String event, final JSONObject message) {
|
||||
try {
|
||||
mScrollHeight = message.getInt("y");
|
||||
mHeight = message.getInt("cheight");
|
||||
// We don't want a height of 0. That means it's a bad response.
|
||||
if (mHeight > 0) {
|
||||
mPageHeight = message.getInt("height");
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
FennecNativeDriver.log(FennecNativeDriver.LogLevel.WARN,
|
||||
"WARNING: ScrollReceived, but message does not contain " +
|
||||
"expected fields: " + e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -27,3 +27,6 @@ if CONFIG['HOST_OS_ARCH'] != 'WINNT':
|
||||
|
||||
if CONFIG['GKMEDIAS_SHARED_LIBRARY']:
|
||||
DEFINES['GKMEDIAS_SHARED_LIBRARY'] = True
|
||||
|
||||
if CONFIG['MOZ_SHARED_ICU']:
|
||||
DEFINES['MOZ_SHARED_ICU'] = True
|
||||
|
@ -1131,7 +1131,7 @@ kvm.h
|
||||
spawn.h
|
||||
err.h
|
||||
xlocale.h
|
||||
#if MOZ_NATIVE_ICU==1
|
||||
#ifdef MOZ_SHARED_ICU
|
||||
unicode/locid.h
|
||||
unicode/numsys.h
|
||||
unicode/ucal.h
|
||||
|
127
configure.in
127
configure.in
@ -3896,6 +3896,17 @@ if test -n "$MOZ_NATIVE_FFI"; then
|
||||
MOZ_JS_STATIC_LIBS="$MOZ_JS_STATIC_LIBS $MOZ_FFI_LIBS"
|
||||
fi
|
||||
|
||||
# split JS out by default to avoid VS2005 PGO crash (bug 591836).
|
||||
if test "$OS_ARCH" = "WINNT"; then
|
||||
JS_SHARED_LIBRARY=1
|
||||
fi
|
||||
|
||||
MOZ_ARG_ENABLE_BOOL(shared-js,
|
||||
[ --enable-shared-js
|
||||
Create a shared JavaScript library.],
|
||||
JS_SHARED_LIBRARY=1,
|
||||
JS_SHARED_LIBRARY=)
|
||||
|
||||
dnl ========================================================
|
||||
dnl System ICU Support
|
||||
dnl ========================================================
|
||||
@ -3961,7 +3972,7 @@ MOZ_MEDIA_NAVIGATOR=
|
||||
MOZ_OMX_PLUGIN=
|
||||
MOZ_VP8=
|
||||
MOZ_VP8_ERROR_CONCEALMENT=
|
||||
MOZ_VP8_ENCODER=
|
||||
MOZ_VP8_ENCODER=1
|
||||
MOZ_WEBSPEECH=1
|
||||
VPX_AS=
|
||||
VPX_ASFLAGS=
|
||||
@ -5127,7 +5138,6 @@ if test -n "$MOZ_WEBRTC"; then
|
||||
AC_DEFINE(MOZ_WEBRTC_ASSERT_ALWAYS)
|
||||
MOZ_RAW=1
|
||||
MOZ_VP8=1
|
||||
MOZ_VP8_ENCODER=1
|
||||
MOZ_VP8_ERROR_CONCEALMENT=1
|
||||
|
||||
dnl enable once Signaling lands
|
||||
@ -5464,7 +5474,7 @@ if test -n "$MOZ_VP8" -a -z "$MOZ_NATIVE_LIBVPX"; then
|
||||
;;
|
||||
*:x86)
|
||||
if $CC -E -dM -</dev/null | grep -q __ELF__; then
|
||||
VPX_ASFLAGS="-f elf32 -rnasm -pnasm"
|
||||
VPX_ASFLAGS="-f elf32 -rnasm -pnasm -DPIC"
|
||||
VPX_X86_ASM=1
|
||||
fi
|
||||
;;
|
||||
@ -7727,19 +7737,7 @@ dnl =
|
||||
dnl ========================================================
|
||||
MOZ_ARG_HEADER(Static build options)
|
||||
|
||||
# split JS out by default to avoid VS2005 PGO crash (bug 591836).
|
||||
if test "$OS_ARCH" = "WINNT"; then
|
||||
ENABLE_SHARED_JS=1
|
||||
fi
|
||||
|
||||
MOZ_ARG_ENABLE_BOOL(shared-js,
|
||||
[ --enable-shared-js
|
||||
Create a shared JavaScript library.],
|
||||
ENABLE_SHARED_JS=1,
|
||||
ENABLE_SHARED_JS=)
|
||||
|
||||
if test -n "$ENABLE_SHARED_JS"; then
|
||||
JS_SHARED_LIBRARY=1
|
||||
if test -n "$JS_SHARED_LIBRARY"; then
|
||||
MOZ_JS_LIBS="$MOZ_JS_SHARED_LIBS"
|
||||
else
|
||||
MOZ_JS_LIBS="$MOZ_JS_STATIC_LIBS"
|
||||
@ -8788,6 +8786,81 @@ HAVE_SYS_MOUNT_H
|
||||
|
||||
AC_SUBST(STLPORT_LIBS)
|
||||
|
||||
MOZ_ARG_WITH_STRING(intl-api,
|
||||
[ --with-intl-api, --with-intl-api=build, --without-intl-api
|
||||
Determine the status of the ECMAScript Internationalization API. The first
|
||||
(or lack of any of these) builds and exposes the API. The second builds it
|
||||
but doesn't use ICU or expose the API to script. The third doesn't build
|
||||
ICU at all.],
|
||||
_INTL_API=$withval,
|
||||
_INTL_API=yes)
|
||||
|
||||
WITH_INTL="--with-intl-api=$_INTL_API"
|
||||
ENABLE_INTL_API=
|
||||
case "$_INTL_API" in
|
||||
no)
|
||||
;;
|
||||
build)
|
||||
ENABLE_INTL_API=1
|
||||
;;
|
||||
yes)
|
||||
ENABLE_INTL_API=1
|
||||
;;
|
||||
*)
|
||||
AC_MSG_ERROR([Invalid value passed to --with-intl-api: $_INTL_API])
|
||||
;;
|
||||
esac
|
||||
|
||||
if test -n "$ENABLE_INTL_API"; then
|
||||
if test "$MOZ_BUILD_APP" = "browser"; then
|
||||
WITH_INTL="--with-intl-api"
|
||||
else
|
||||
# Internationalization isn't built or exposed by default in non-desktop
|
||||
# builds. Bugs to enable:
|
||||
#
|
||||
# Android: bug 864843
|
||||
# B2G: bug 866301
|
||||
WITH_INTL="--without-intl-api"
|
||||
ENABLE_INTL_API=
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl Settings for the implementation of the ECMAScript Internationalization API
|
||||
if test -n "$ENABLE_INTL_API"; then
|
||||
AC_DEFINE(ENABLE_INTL_API)
|
||||
|
||||
MOZ_CONFIG_ICU()
|
||||
|
||||
dnl Build ICU as a shared library for shared js builds.
|
||||
if test -z "$MOZ_NATIVE_ICU" -a -n "$JS_SHARED_LIBRARY"; then
|
||||
case "$OS_TARGET" in
|
||||
WINNT)
|
||||
ICU_LIB_NAMES="icuin icuuc icudt"
|
||||
DBG_SUFFIX=
|
||||
if test -n "$MOZ_DEBUG"; then
|
||||
DBG_SUFFIX=d
|
||||
fi
|
||||
MOZ_ICU_LIBS='$(foreach lib,$(ICU_LIB_NAMES),$(DEPTH)/js/src/intl/icu/target/lib/$(LIB_PREFIX)$(lib)$(DBG_SUFFIX).$(LIB_SUFFIX))'
|
||||
;;
|
||||
Darwin)
|
||||
ICU_LIB_NAMES="icui18n icuuc icudata"
|
||||
MOZ_ICU_LIBS='$(foreach lib,$(ICU_LIB_NAMES),$(DEPTH)/js/src/intl/icu/target/lib/$(DLL_PREFIX)$(lib).$(MOZ_ICU_VERSION)$(DLL_SUFFIX))'
|
||||
;;
|
||||
Linux|DragonFly|FreeBSD|NetBSD|OpenBSD)
|
||||
ICU_LIB_NAMES="icui18n icuuc icudata"
|
||||
MOZ_ICU_LIBS='$(foreach lib,$(ICU_LIB_NAMES),$(DEPTH)/js/src/intl/icu/target/lib/$(DLL_PREFIX)$(lib)$(DLL_SUFFIX).$(MOZ_ICU_VERSION))'
|
||||
;;
|
||||
*)
|
||||
AC_MSG_ERROR([ECMAScript Internationalization API is not yet supported on this platform])
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_SUBST(DBG_SUFFIX)
|
||||
AC_SUBST(ENABLE_INTL_API)
|
||||
AC_SUBST(ICU_LIB_NAMES)
|
||||
AC_SUBST(MOZ_ICU_LIBS)
|
||||
|
||||
export WRITE_MOZINFO=1
|
||||
AC_OUTPUT()
|
||||
unset WRITE_MOZINFO
|
||||
@ -8966,7 +9039,7 @@ fi
|
||||
# Run jemalloc configure script
|
||||
|
||||
if test -z "$MOZ_NATIVE_JEMALLOC" -a "$MOZ_MEMORY" && test -n "$MOZ_JEMALLOC3" -o -n "$MOZ_REPLACE_MALLOC"; then
|
||||
ac_configure_args="$_SUBDIR_CONFIG_ARGS --build=$build --host=$target --enable-stats --with-jemalloc-prefix=je_"
|
||||
ac_configure_args="--build=$build --host=$target --enable-stats --with-jemalloc-prefix=je_"
|
||||
if test -n "$MOZ_REPLACE_MALLOC"; then
|
||||
# When using replace_malloc, we always want memalign and valloc exported from jemalloc.
|
||||
ac_configure_args="$ac_configure_args ac_cv_func_memalign=yes"
|
||||
@ -9161,26 +9234,6 @@ dist=$MOZ_BUILD_ROOT/dist
|
||||
ac_configure_args="$_SUBDIR_CONFIG_ARGS"
|
||||
ac_configure_args="$ac_configure_args --enable-threadsafe"
|
||||
|
||||
MOZ_ARG_WITH_STRING(intl-api,
|
||||
[ --with-intl-api, --with-intl-api=build, --without-intl-api
|
||||
Determine the status of the ECMAScript Internationalization API. The first
|
||||
(or lack of any of these) builds and exposes the API. The second builds it
|
||||
but doesn't use ICU or expose the API to script. The third doesn't build
|
||||
ICU at all.],
|
||||
WITH_INTL="--with-intl-api=$withval"
|
||||
)
|
||||
if test -z "$WITH_INTL"; then
|
||||
if test "$MOZ_BUILD_APP" = "browser"; then
|
||||
WITH_INTL="--with-intl-api"
|
||||
else
|
||||
# Internationalization isn't built or exposed by default in non-desktop
|
||||
# builds. Bugs to enable:
|
||||
#
|
||||
# Android: bug 864843
|
||||
# B2G: bug 866301
|
||||
WITH_INTL="--without-intl-api"
|
||||
fi
|
||||
fi
|
||||
ac_configure_args="$ac_configure_args $WITH_INTL"
|
||||
|
||||
if test "$BUILD_CTYPES"; then
|
||||
|
@ -171,9 +171,11 @@ static const char* const gWebMTypes[3] = {
|
||||
nullptr
|
||||
};
|
||||
|
||||
static char const *const gWebMCodecs[5] = {
|
||||
static char const *const gWebMCodecs[7] = {
|
||||
"vp8",
|
||||
"vp8.0",
|
||||
"vp9",
|
||||
"vp9.0",
|
||||
"vorbis",
|
||||
"opus",
|
||||
nullptr
|
||||
|
@ -421,6 +421,18 @@ bool OmxDecoder::TryLoad() {
|
||||
|
||||
// read audio metadata
|
||||
if (mAudioSource.get()) {
|
||||
// For RTSP, we don't read the audio source for now.
|
||||
// The metadata of RTSP will be obtained through SDP at connection time.
|
||||
if (mResource->GetRtspPointer()) {
|
||||
sp<MetaData> meta = mAudioSource->getFormat();
|
||||
if (!meta->findInt32(kKeyChannelCount, &mAudioChannels) ||
|
||||
!meta->findInt32(kKeySampleRate, &mAudioSampleRate)) {
|
||||
NS_WARNING("Couldn't get audio metadata from OMX decoder");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// To reliably get the channel and sample rate data we need to read from the
|
||||
// audio source until we get a INFO_FORMAT_CHANGE status
|
||||
status_t err = mAudioSource->read(&mAudioBuffer);
|
||||
|
@ -62,6 +62,15 @@ public:
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Override FindStartTime() to return null pointer.
|
||||
// For Rtsp, we don't have the first video frame in DECODING_METADATA state.
|
||||
// It will be available until player request Play() and media decoder enters
|
||||
// DECODING state.
|
||||
virtual VideoData* FindStartTime(int64_t& aOutStartTime)
|
||||
MOZ_FINAL MOZ_OVERRIDE {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
// A pointer to RtspMediaResource for calling the Rtsp specific function.
|
||||
// The lifetime of mRtspResource is controlled by MediaDecoder. MediaDecoder
|
||||
|
@ -163,7 +163,7 @@ WebMReader::WebMReader(AbstractMediaDecoder* aDecoder)
|
||||
#endif
|
||||
// Zero these member vars to avoid crashes in VP8 destroy and Vorbis clear
|
||||
// functions when destructor is called before |Init|.
|
||||
memset(&mVP8, 0, sizeof(vpx_codec_ctx_t));
|
||||
memset(&mVPX, 0, sizeof(vpx_codec_ctx_t));
|
||||
memset(&mVorbisBlock, 0, sizeof(vorbis_block));
|
||||
memset(&mVorbisDsp, 0, sizeof(vorbis_dsp_state));
|
||||
memset(&mVorbisInfo, 0, sizeof(vorbis_info));
|
||||
@ -177,7 +177,7 @@ WebMReader::~WebMReader()
|
||||
mVideoPackets.Reset();
|
||||
mAudioPackets.Reset();
|
||||
|
||||
vpx_codec_destroy(&mVP8);
|
||||
vpx_codec_destroy(&mVPX);
|
||||
|
||||
vorbis_block_clear(&mVorbisBlock);
|
||||
vorbis_dsp_clear(&mVorbisDsp);
|
||||
@ -194,9 +194,6 @@ WebMReader::~WebMReader()
|
||||
|
||||
nsresult WebMReader::Init(MediaDecoderReader* aCloneDonor)
|
||||
{
|
||||
if (vpx_codec_dec_init(&mVP8, vpx_codec_vp8_dx(), nullptr, 0)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
vorbis_info_init(&mVorbisInfo);
|
||||
vorbis_comment_init(&mVorbisComment);
|
||||
@ -285,6 +282,18 @@ nsresult WebMReader::ReadMetadata(MediaInfo* aInfo,
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
vpx_codec_iface_t* dx = nullptr;
|
||||
mVideoCodec = nestegg_track_codec_id(mContext, track);
|
||||
if (mVideoCodec == NESTEGG_CODEC_VP8) {
|
||||
dx = vpx_codec_vp8_dx();
|
||||
} else if (mVideoCodec == NESTEGG_CODEC_VP9) {
|
||||
dx = vpx_codec_vp9_dx();
|
||||
}
|
||||
if (!dx || vpx_codec_dec_init(&mVPX, dx, nullptr, 0)) {
|
||||
Cleanup();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Picture region, taking into account cropping, before scaling
|
||||
// to the display size.
|
||||
nsIntRect pictureRect(params.crop_left,
|
||||
@ -868,7 +877,11 @@ bool WebMReader::DecodeVideoFrame(bool &aKeyframeSkip,
|
||||
vpx_codec_stream_info_t si;
|
||||
memset(&si, 0, sizeof(si));
|
||||
si.sz = sizeof(si);
|
||||
vpx_codec_peek_stream_info(vpx_codec_vp8_dx(), data, length, &si);
|
||||
if (mVideoCodec == NESTEGG_CODEC_VP8) {
|
||||
vpx_codec_peek_stream_info(vpx_codec_vp8_dx(), data, length, &si);
|
||||
} else if (mVideoCodec == NESTEGG_CODEC_VP9) {
|
||||
vpx_codec_peek_stream_info(vpx_codec_vp9_dx(), data, length, &si);
|
||||
}
|
||||
if (aKeyframeSkip && (!si.is_kf || tstamp_usecs < aTimeThreshold)) {
|
||||
// Skipping to next keyframe...
|
||||
parsed++; // Assume 1 frame per chunk.
|
||||
@ -879,7 +892,7 @@ bool WebMReader::DecodeVideoFrame(bool &aKeyframeSkip,
|
||||
aKeyframeSkip = false;
|
||||
}
|
||||
|
||||
if (vpx_codec_decode(&mVP8, data, length, nullptr, 0)) {
|
||||
if (vpx_codec_decode(&mVPX, data, length, nullptr, 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -894,7 +907,7 @@ bool WebMReader::DecodeVideoFrame(bool &aKeyframeSkip,
|
||||
vpx_codec_iter_t iter = nullptr;
|
||||
vpx_image_t *img;
|
||||
|
||||
while ((img = vpx_codec_get_frame(&mVP8, &iter))) {
|
||||
while ((img = vpx_codec_get_frame(&mVPX, &iter))) {
|
||||
NS_ASSERTION(img->fmt == IMG_FMT_I420, "WebM image format is not I420");
|
||||
|
||||
// Chroma shifts are rounded down as per the decoding examples in the VP8 SDK
|
||||
|
@ -181,7 +181,7 @@ private:
|
||||
nestegg* mContext;
|
||||
|
||||
// VP8 decoder state
|
||||
vpx_codec_ctx_t mVP8;
|
||||
vpx_codec_ctx_t mVPX;
|
||||
|
||||
// Vorbis decoder state
|
||||
vorbis_info mVorbisInfo;
|
||||
@ -234,6 +234,8 @@ private:
|
||||
|
||||
// Codec ID of audio track
|
||||
int mAudioCodec;
|
||||
// Codec ID of video track
|
||||
int mVideoCodec;
|
||||
|
||||
};
|
||||
|
||||
|
@ -1256,6 +1256,7 @@ Navigator::GetGamepads(nsTArray<nsRefPtr<Gamepad> >& aGamepads,
|
||||
}
|
||||
NS_ENSURE_TRUE_VOID(mWindow->GetDocShell());
|
||||
nsGlobalWindow* win = static_cast<nsGlobalWindow*>(mWindow.get());
|
||||
win->SetHasGamepadEventListener(true);
|
||||
win->GetGamepads(aGamepads);
|
||||
}
|
||||
#endif
|
||||
|
@ -66,11 +66,6 @@
|
||||
}
|
||||
|
||||
var tests = [
|
||||
function() {
|
||||
ok(!("getDataStores" in navigator), "getDataStores should not exist");
|
||||
runTest();
|
||||
},
|
||||
|
||||
// Permissions
|
||||
function() {
|
||||
SpecialPowers.pushPermissions(
|
||||
@ -83,7 +78,13 @@
|
||||
function() {
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.promise.enabled", true],
|
||||
["dom.datastore.enabled", true],
|
||||
["dom.testing.ignore_ipc_principal", true]]}, runTest);
|
||||
["dom.testing.ignore_ipc_principal", true],
|
||||
["dom.testing.datastore_enabled_for_hosted_apps", false]]}, runTest);
|
||||
},
|
||||
|
||||
function() {
|
||||
ok(!("getDataStores" in navigator), "getDataStores should not exist");
|
||||
runTest();
|
||||
},
|
||||
|
||||
function() {
|
||||
|
46
dom/indexedDB/test/unit/test_cursor_cycle.js
Normal file
46
dom/indexedDB/test/unit/test_cursor_cycle.js
Normal file
@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
var testGenerator = testSteps();
|
||||
|
||||
function testSteps()
|
||||
{
|
||||
const Bob = { ss: "237-23-7732", name: "Bob" };
|
||||
|
||||
let request = indexedDB.open(this.window ? window.location.pathname : "Splendid Test", 1);
|
||||
request.onerror = errorHandler;
|
||||
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||
let event = yield undefined;
|
||||
|
||||
let db = event.target.result;
|
||||
event.target.onsuccess = continueToNextStep;
|
||||
|
||||
let objectStore = db.createObjectStore("foo", { keyPath: "ss" });
|
||||
objectStore.createIndex("name", "name", { unique: true });
|
||||
objectStore.add(Bob);
|
||||
yield undefined;
|
||||
|
||||
// This direct eval causes locals to be aliased, and thus allocated on
|
||||
// the scope chain. Comment it out (and the workarounds below) and
|
||||
// the test passes. Bug 943409.
|
||||
eval('');
|
||||
|
||||
db.transaction("foo", "readwrite").objectStore("foo")
|
||||
.index("name").openCursor().onsuccess = function(event) {
|
||||
event.target.transaction.oncomplete = continueToNextStep;
|
||||
let cursor = event.target.result;
|
||||
if (cursor) {
|
||||
let objectStore = event.target.transaction.objectStore("foo");
|
||||
objectStore.delete(Bob.ss)
|
||||
.onsuccess = function(event) { cursor.continue(); };
|
||||
}
|
||||
};
|
||||
yield undefined;
|
||||
finishTest();
|
||||
|
||||
objectStore = null; // Bug 943409 workaround.
|
||||
|
||||
yield undefined;
|
||||
}
|
@ -35,6 +35,11 @@ function testSteps()
|
||||
let objectStore = db.createObjectStore("foo", { keyPath: "ss" });
|
||||
objectStore.createIndex("name", "name", { unique: true });
|
||||
|
||||
// This direct eval causes locals to be aliased, and thus allocated on
|
||||
// the scope chain. Comment it out (and the workarounds below) and
|
||||
// the test passes. Bug 943409.
|
||||
eval('');
|
||||
|
||||
for (let i = 0; i < objectStoreData.length - 1; i++) {
|
||||
objectStore.add(objectStoreData[i]);
|
||||
}
|
||||
@ -111,5 +116,8 @@ function testSteps()
|
||||
is(sawRemoved, false, "Didn't see item that was removed");
|
||||
|
||||
finishTest();
|
||||
|
||||
objectStore = null; // Bug 943409 workaround.
|
||||
|
||||
yield undefined;
|
||||
}
|
||||
|
@ -34,6 +34,9 @@ function testSteps()
|
||||
|
||||
event.target.onsuccess = continueToNextStep;
|
||||
|
||||
// Bug 943409.
|
||||
eval('');
|
||||
|
||||
for (let objectStoreIndex in objectStoreData) {
|
||||
const objectStoreInfo = objectStoreData[objectStoreIndex];
|
||||
let objectStore = db.createObjectStore(objectStoreInfo.name,
|
||||
@ -137,6 +140,8 @@ function testSteps()
|
||||
.objectStore(objectStoreName).clear()
|
||||
.onsuccess = continueToNextStep;
|
||||
yield undefined;
|
||||
|
||||
objectStore = index = null; // Bug 943409 workaround.
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,9 @@ function testSteps()
|
||||
let db = event.target.result;
|
||||
db.onerror = errorHandler;
|
||||
|
||||
// Bug 943409.
|
||||
eval('');
|
||||
|
||||
for each (let autoIncrement in [false, true]) {
|
||||
let objectStore =
|
||||
db.createObjectStore(autoIncrement, { keyPath: "id",
|
||||
@ -159,9 +162,13 @@ function testSteps()
|
||||
|
||||
is(event.target.result, indexCount,
|
||||
"Correct number of entries in index");
|
||||
|
||||
index = event = null; // Bug 943409 workaround.
|
||||
}
|
||||
objectStore = event = null; // Bug 943409 workaround.
|
||||
}
|
||||
|
||||
finishTest();
|
||||
event = db = request = null; // Bug 943409 workaround.
|
||||
yield undefined;
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ support-files =
|
||||
[test_create_index.js]
|
||||
[test_create_index_with_integer_keys.js]
|
||||
[test_create_objectStore.js]
|
||||
[test_cursor_cycle.js]
|
||||
[test_cursor_mutation.js]
|
||||
[test_cursor_update_updates_indexes.js]
|
||||
[test_cursors.js]
|
||||
|
@ -132,19 +132,29 @@ void nsPluginTag::InitMime(const char* const* aMimeTypes,
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < aVariantCount; i++) {
|
||||
if (!aMimeTypes[i] || !nsPluginHost::IsTypeWhitelisted(aMimeTypes[i])) {
|
||||
if (!aMimeTypes[i]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsAutoCString mimeType(aMimeTypes[i]);
|
||||
|
||||
// Convert the MIME type, which is case insensitive, to lowercase in order
|
||||
// to properly handle a mixed-case type.
|
||||
ToLowerCase(mimeType);
|
||||
|
||||
if (!nsPluginHost::IsTypeWhitelisted(mimeType.get())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Look for certain special plugins.
|
||||
if (nsPluginHost::IsJavaMIMEType(aMimeTypes[i])) {
|
||||
if (nsPluginHost::IsJavaMIMEType(mimeType.get())) {
|
||||
mIsJavaPlugin = true;
|
||||
} else if (strcmp(aMimeTypes[i], "application/x-shockwave-flash") == 0) {
|
||||
} else if (mimeType.EqualsLiteral("application/x-shockwave-flash")) {
|
||||
mIsFlashPlugin = true;
|
||||
}
|
||||
|
||||
// Fill in our MIME type array.
|
||||
mMimeTypes.AppendElement(nsCString(aMimeTypes[i]));
|
||||
mMimeTypes.AppendElement(mimeType);
|
||||
|
||||
// Now fill in the MIME descriptions.
|
||||
if (aMimeDescriptions && aMimeDescriptions[i]) {
|
||||
|
8
dom/plugins/test/mochitest/mixed_case_mime.sjs
Normal file
8
dom/plugins/test/mochitest/mixed_case_mime.sjs
Normal file
@ -0,0 +1,8 @@
|
||||
function handleRequest(request, response)
|
||||
{
|
||||
response.processAsync();
|
||||
response.setHeader("Content-Type", "application/x-Second-Test", false);
|
||||
|
||||
response.write("Hello world.\n");
|
||||
response.finish();
|
||||
}
|
@ -11,6 +11,7 @@ support-files =
|
||||
loremipsum_file.txt
|
||||
loremipsum_nocache.txt
|
||||
loremipsum_nocache.txt^headers^
|
||||
mixed_case_mime.sjs
|
||||
neverending.sjs
|
||||
npruntime_identifiers_subpage.html
|
||||
plugin-stream-referer.sjs
|
||||
@ -41,6 +42,7 @@ support-files =
|
||||
[test_instance_unparent2.html]
|
||||
[test_instance_unparent3.html]
|
||||
[test_instantiation.html]
|
||||
[test_mixed_case_mime.html]
|
||||
[test_multipleinstanceobjects.html]
|
||||
[test_newstreamondestroy.html]
|
||||
[test_npn_asynccall.html]
|
||||
|
29
dom/plugins/test/mochitest/test_mixed_case_mime.html
Normal file
29
dom/plugins/test/mochitest/test_mixed_case_mime.html
Normal file
@ -0,0 +1,29 @@
|
||||
<body>
|
||||
<head>
|
||||
<title>Test mixed case mimetype for plugins</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
<script>
|
||||
SimpleTest.expectAssertions(0, 1);
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED, "Second Test Plug-in");
|
||||
|
||||
function frameLoaded() {
|
||||
var contentDocument = document.getElementById('testframe').contentDocument;
|
||||
ok(contentDocument.body.innerHTML.length > 0, "Frame content shouldn't be empty.");
|
||||
ok(contentDocument.plugins.length > 0, "Frame content should have a plugin.");
|
||||
var plugin = contentDocument.plugins[0];
|
||||
is(plugin.type.toLowerCase(), "application/x-second-test", "Should have loaded the second test plugin.");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
|
||||
<iframe id="testframe" name="testframe" onload="frameLoaded()" src="mixed_case_mime.sjs"></iframe>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -24,7 +24,7 @@
|
||||
<string>Second plug-in for testing purposes.</string>
|
||||
<key>WebPluginMIMETypes</key>
|
||||
<dict>
|
||||
<key>application/x-second-test</key>
|
||||
<key>application/x-Second-Test</key>
|
||||
<dict>
|
||||
<key>WebPluginExtensions</key>
|
||||
<array>
|
||||
|
@ -29,7 +29,7 @@ BEGIN
|
||||
VALUE "FileOpenName", "Second test type"
|
||||
VALUE "FileVersion", "1.0"
|
||||
VALUE "InternalName", "npsecondtest"
|
||||
VALUE "MIMEType", "application/x-second-test"
|
||||
VALUE "MIMEType", "application/x-Second-Test"
|
||||
VALUE "OriginalFilename", "npsecondtest.dll"
|
||||
VALUE "ProductName", "Second Test Plug-in"
|
||||
VALUE "ProductVersion", "1.0"
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user