Merge m-c to graphics

MozReview-Commit-ID: 5zsIClrx1FB
This commit is contained in:
Kartikaya Gupta 2017-04-21 10:01:47 -04:00
commit 2e1380aecf
1928 changed files with 131826 additions and 75643 deletions

View File

@ -21,6 +21,16 @@ jobs:
mozilla-aurora: [{hour: 7, minute: 45}] # Buildbot uses minute 40
# No default
- name: nightly-desktop-osx
job:
type: decision-task
treeherder-symbol: Nd-OSX
triggered-by: nightly
target-tasks-method: nightly_macosx
run-on-projects:
- date
when: [] # never (hook only)
- name: nightly-android
job:
type: decision-task

View File

@ -4,6 +4,7 @@
* 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/. */
#include "mozilla-config.h"
#include "AccessibleHandler.h"
import "ocidl.idl";

View File

@ -20,7 +20,7 @@ export:: $(MIDL_GENERATED_FILES)
$(MIDL_GENERATED_FILES): midl_done
midl_done: HandlerData.acf HandlerData.idl
$(MIDL) $(MIDL_FLAGS) $(DEFINES) -I $(IA2DIR) -I $(MSAADIR) -Oicf -acf $(srcdir)/HandlerData.acf $(srcdir)/HandlerData.idl
$(MIDL) $(MIDL_FLAGS) $(DEFINES) -I $(topobjdir) -I $(DIST)/include -I $(IA2DIR) -I $(MSAADIR) -Oicf -acf $(srcdir)/HandlerData.acf $(srcdir)/HandlerData.idl
touch $@
INSTALL_TARGETS += midl

View File

@ -1613,6 +1613,9 @@ pref("browser.formautofill.experimental", false);
pref("browser.formautofill.enabled", false);
pref("browser.formautofill.loglevel", "Warn");
// Whether or not to restore a session with lazy-browser tabs.
pref("browser.sessionstore.restore_tabs_lazily", true);
// Enable safebrowsing v4 tables (suffixed by "-proto") update.
#ifdef NIGHTLY_BUILD
pref("urlclassifier.malwareTable", "goog-malware-shavar,goog-unwanted-shavar,goog-malware-proto,goog-unwanted-proto,test-malware-simple,test-unwanted-simple");

View File

@ -636,7 +636,8 @@ var FullScreen = {
}
}
ToolbarIconColor.inferFromText();
ToolbarIconColor.inferFromText("fullscreen", aEnterFS);
// For Lion fullscreen, all fullscreen controls are hidden, don't
// bother to touch them. If we don't stop here, the following code

View File

@ -247,7 +247,8 @@ var TabsInTitlebar = {
menubar.style.paddingBottom = "";
}
ToolbarIconColor.inferFromText();
ToolbarIconColor.inferFromText("tabsintitlebar", TabsInTitlebar.enabled);
if (CustomizationHandler.isCustomizing()) {
gCustomizeMode.updateLWTStyling();
}

View File

@ -5408,8 +5408,6 @@ function setToolbarVisibility(toolbar, isVisible, persist = true) {
PlacesToolbarHelper.init();
BookmarkingUI.onToolbarVisibilityChange();
if (isVisible)
ToolbarIconColor.inferFromText();
}
var TabletModeUpdater = {
@ -7686,7 +7684,7 @@ var gIdentityHandler = {
let tooltiptext = gNavigatorBundle.getString("permissions.remove.tooltip");
button.setAttribute("tooltiptext", tooltiptext);
button.addEventListener("command", () => {
let browser = gBrowser.selectedBrowser;
let browser = gBrowser.selectedBrowser;
// Only resize the window if the reload hint was previously hidden.
this._handleHeightChange(() => this._permissionList.removeChild(container),
this._permissionReloadHint.hasAttribute("hidden"));
@ -8219,8 +8217,8 @@ var MousePosTracker = {
handleEvent(event) {
var fullZoom = this._windowUtils.fullZoom;
this._x = event.clientX / fullZoom;
this._y = event.clientY / fullZoom;
this._x = event.screenX / fullZoom - window.mozInnerScreenX;
this._y = event.screenY / fullZoom - window.mozInnerScreenY;
this._listeners.forEach(function(listener) {
try {
@ -8253,18 +8251,25 @@ var MousePosTracker = {
};
var ToolbarIconColor = {
_windowState: {
"active": false,
"fullscreen": false,
"tabsintitlebar": false
},
init() {
this._initialized = true;
window.addEventListener("activate", this);
window.addEventListener("deactivate", this);
window.addEventListener("toolbarvisibilitychange", this);
Services.obs.addObserver(this, "lightweight-theme-styling-update");
// If the window isn't active now, we assume that it has never been active
// before and will soon become active such that inferFromText will be
// called from the initial activate event.
if (Services.focus.activeWindow == window)
this.inferFromText();
if (Services.focus.activeWindow == window) {
this.inferFromText("activate");
}
},
uninit() {
@ -8272,14 +8277,18 @@ var ToolbarIconColor = {
window.removeEventListener("activate", this);
window.removeEventListener("deactivate", this);
window.removeEventListener("toolbarvisibilitychange", this);
Services.obs.removeObserver(this, "lightweight-theme-styling-update");
},
handleEvent(event) {
switch (event.type) {
case "activate":
case "activate": // falls through
case "deactivate":
this.inferFromText();
this.inferFromText(event.type);
break;
case "toolbarvisibilitychange":
this.inferFromText(event.type, event.visible);
break;
}
},
@ -8289,32 +8298,66 @@ var ToolbarIconColor = {
case "lightweight-theme-styling-update":
// inferFromText needs to run after LightweightThemeConsumer.jsm's
// lightweight-theme-styling-update observer.
setTimeout(() => { this.inferFromText(); }, 0);
setTimeout(() => {
this.inferFromText(aTopic);
}, 0);
break;
}
},
inferFromText() {
// a cache of luminance values for each toolbar
// to avoid unnecessary calls to getComputedStyle
_toolbarLuminanceCache: new Map(),
inferFromText(reason, reasonValue) {
if (!this._initialized)
return;
function parseRGB(aColorString) {
let rgb = aColorString.match(/^rgba?\((\d+), (\d+), (\d+)/);
rgb.shift();
return rgb.map(x => parseInt(x));
}
switch (reason) {
case "activate": // falls through
case "deactivate":
this._windowState.active = (reason === "activate");
break;
case "fullscreen":
this._windowState.fullscreen = reasonValue;
break;
case "lightweight-theme-styling-update":
// theme change, we'll need to recalculate all color values
this._toolbarLuminanceCache.clear();
break;
case "toolbarvisibilitychange":
// toolbar changes dont require reset of the cached color values
break;
case "tabsintitlebar":
this._windowState.tabsintitlebar = reasonValue;
break;
}
let toolbarSelector = "#navigator-toolbox > toolbar:not([collapsed=true]):not(#addon-bar)";
if (AppConstants.platform == "macosx")
toolbarSelector += ":not([type=menubar])";
// The getComputedStyle calls and setting the brighttext are separated in
// two loops to avoid flushing layout and making it dirty repeatedly.
let luminances = new Map;
let cachedLuminances = this._toolbarLuminanceCache;
let luminances = new Map();
for (let toolbar of document.querySelectorAll(toolbarSelector)) {
let [r, g, b] = parseRGB(getComputedStyle(toolbar).color);
let luminance = 0.2125 * r + 0.7154 * g + 0.0721 * b;
// toolbars *should* all have ids, but guard anyway to avoid blowing up
let cacheKey = toolbar.id && toolbar.id + JSON.stringify(this._windowState);
// lookup cached luminance value for this toolbar in this window state
let luminance = cacheKey && cachedLuminances.get(cacheKey);
if (isNaN(luminance)) {
let [r, g, b] = parseRGB(getComputedStyle(toolbar).color);
luminance = 0.2125 * r + 0.7154 * g + 0.0721 * b;
if (cacheKey) {
cachedLuminances.set(cacheKey, luminance);
}
}
luminances.set(toolbar, luminance);
}

View File

@ -2034,7 +2034,8 @@
"addProgressListener", "removeProgressListener", "audioPlaybackStarted",
"audioPlaybackStopped", "adjustPriority", "pauseMedia", "stopMedia",
"blockMedia", "resumeMedia", "mute", "unmute", "blockedPopups", "lastURI",
"purgeSessionHistory", "stopScroll", "startScroll"
"purgeSessionHistory", "stopScroll", "startScroll",
"userTypedValue", "userTypedClear"
]</field>
<method name="_createLazyBrowser">
@ -2052,11 +2053,51 @@
switch (name) {
case "permitUnload":
getter = () => {
return function() {
return () => {
return { permitUnload: true, timedOut: false };
};
};
break;
case "reload":
case "reloadWithFlags":
getter = () => {
return (params) => {
// Wait for load handler to be instantiated before
// initializing the reload.
aTab.addEventListener("SSTabRestoring", () => {
browser[name](params);
}, { once: true });
gBrowser._insertBrowser(aTab);
};
};
break;
case "isRemoteBrowser":
getter = () => {
return browser.getAttribute("remote") == "true";
};
break;
case "audioMuted":
getter = () => {
return false;
};
break;
case "currentURI":
getter = () => {
let url = SessionStore.getLazyTabValue(aTab, "url");
return Services.io.newURI(url);
};
break;
case "contentTitle":
getter = () => {
return SessionStore.getLazyTabValue(aTab, "title");
};
break;
case "userTypedValue":
case "userTypedClear":
getter = () => {
return SessionStore.getLazyTabValue(aTab, name);
};
break;
default:
getter = () => {
this._insertBrowser(aTab);
@ -2084,9 +2125,8 @@
<![CDATA[
"use strict";
// If browser is already inserted, or aTab doesn't have a
// browser, don't do anything.
if (aTab.linkedPanel || !aTab.linkedBrowser) {
// If browser is already inserted don't do anything.
if (aTab.linkedPanel) {
return;
}
@ -4876,7 +4916,8 @@
tab.linkedBrowser &&
tab.linkedBrowser.isRemoteBrowser) {
label += " - e10s";
if (Services.appinfo.maxWebProcessCount > 1) {
if (tab.linkedBrowser.frameLoader &&
Services.appinfo.maxWebProcessCount > 1) {
label += " (" + tab.linkedBrowser.frameLoader.tabParent.osPid + ")";
}
}
@ -7245,6 +7286,11 @@
<parameter name="aMuteReason"/>
<body>
<![CDATA[
// Do not attempt to toggle mute state if browser is lazy.
if (!this.linkedPanel) {
return;
}
let tabContainer = this.parentNode;
let browser = this.linkedBrowser;
let modifiedAttrs = [];

View File

@ -254,8 +254,6 @@ var whitelist = new Set([
{file: "resource://gre/modules/addons/AddonLogging.jsm"},
// Bug 1351637
{file: "resource://gre/modules/sdk/bootstrap.js"},
// Bug 1351657
{file: "resource://gre/res/langGroups.properties", platforms: ["macosx"]},
].filter(item =>
("isFromDevTools" in item) == isDevtools &&

View File

@ -0,0 +1,7 @@
"use strict";
module.exports = {
"extends": [
"plugin:mozilla/browser-test"
]
};

View File

@ -0,0 +1,2 @@
[DEFAULT]
[browser_toolbariconcolor_restyles.js]

View File

@ -0,0 +1,43 @@
"use strict";
/**
* Ensure redundant style flushes are not triggered when switching between windows
*/
add_task(function* test_toolbar_element_restyles_on_activation() {
let restyles = {
win1: {},
win2: {}
};
// create a window and snapshot the elementsStyled
let win1 = yield BrowserTestUtils.openNewBrowserWindow();
yield new Promise(resolve => waitForFocus(resolve, win1));
// create a 2nd window and snapshot the elementsStyled
let win2 = yield BrowserTestUtils.openNewBrowserWindow();
yield new Promise(resolve => waitForFocus(resolve, win2));
let utils1 = SpecialPowers.getDOMWindowUtils(win1);
restyles.win1.initial = utils1.elementsRestyled;
let utils2 = SpecialPowers.getDOMWindowUtils(win2);
restyles.win2.initial = utils2.elementsRestyled;
// switch back to 1st window, and snapshot elementsStyled
win1.focus();
restyles.win1.activate = utils1.elementsRestyled;
restyles.win2.deactivate = utils2.elementsRestyled;
// switch back to 2nd window, and snapshot elementsStyled
win2.focus();
restyles.win2.activate = utils2.elementsRestyled;
restyles.win1.deactivate = utils1.elementsRestyled;
is(restyles.win1.activate - restyles.win1.deactivate, 0,
"No elements restyled when re-activating/deactivating a window");
is(restyles.win2.activate - restyles.win2.deactivate, 0,
"No elements restyled when re-activating/deactivating a window");
yield BrowserTestUtils.closeWindow(win1);
yield BrowserTestUtils.closeWindow(win2);
});

View File

@ -35,6 +35,7 @@ BROWSER_CHROME_MANIFESTS += [
'content/test/urlbar/browser.ini',
'content/test/webextensions/browser.ini',
'content/test/webrtc/browser.ini',
'content/test/windows/browser.ini',
]
if CONFIG['MOZ_UPDATER']:

View File

@ -1492,7 +1492,8 @@ var CustomizableUIInternal = {
let anchor = aNode;
if (area != CustomizableUI.AREA_PANEL) {
let wrapper = this.wrapWidget(aWidget.id).forWindow(ownerWindow);
if (wrapper && wrapper.anchor) {
if (wrapper && !wrapper.overflowed && wrapper.anchor) {
this.hidePanelForNode(aNode);
anchor = wrapper.anchor;
}
@ -4118,7 +4119,9 @@ OverflowableToolbar.prototype = {
return new Promise(resolve => {
let doc = this._panel.ownerDocument;
this._panel.hidden = false;
let contextMenu = doc.getElementById(this._panel.getAttribute("context"));
let mainViewId = this._panel.querySelector("panelmultiview").getAttribute("mainViewId");
let mainView = doc.getElementById(mainViewId);
let contextMenu = doc.getElementById(mainView.getAttribute("context"));
gELS.addSystemEventListener(contextMenu, "command", this, true);
let anchor = doc.getAnonymousElementByAttribute(this._chevron, "class", "toolbarbutton-icon");
this._panel.openPopup(anchor || this._chevron);

View File

@ -377,13 +377,17 @@
role="group"
type="arrow"
noautofocus="true"
context="toolbar-context-menu"
position="bottomcenter topright"
hidden="true">
<vbox id="widget-overflow-scroller">
<vbox id="widget-overflow-list" class="widget-overflow-list"
overflowfortoolbar="nav-bar"/>
</vbox>
<panelmultiview mainViewId="widget-overflow-mainView">
<panelview id="widget-overflow-mainView"
context="toolbar-context-menu">
<vbox id="widget-overflow-scroller">
<vbox id="widget-overflow-list" class="widget-overflow-list"
overflowfortoolbar="nav-bar"/>
</vbox>
</panelview>
</panelmultiview>
</panel>
<panel id="customization-tipPanel"

View File

@ -431,8 +431,9 @@ const PanelUI = {
return;
}
if (aPlacementArea == CustomizableUI.AREA_PANEL) {
this.multiView.showSubView(aViewId, aAnchor);
let container = aAnchor.closest("panelmultiview");
if (container) {
container.showSubView(aViewId, aAnchor);
} else if (!aAnchor.open) {
aAnchor.open = true;

View File

@ -178,6 +178,14 @@
<body><![CDATA[
Task.spawn(function*() {
let viewNode = this.querySelector("#" + aViewId);
if (!viewNode) {
viewNode = document.getElementById(aViewId);
if (viewNode) {
this._subViews.appendChild(viewNode);
} else {
throw new Error(`Subview ${aViewId} doesn't exist!`);
}
}
viewNode.setAttribute("current", true);
// Emit the ViewShowing event so that the widget definition has a chance
// to lazily populate the subview with things.

View File

@ -149,6 +149,7 @@ skip-if = os == "mac"
[browser_bootstrapped_custom_toolbar.js]
[browser_customizemode_contextmenu_menubuttonstate.js]
[browser_exit_background_customize_mode.js]
[browser_overflow_use_subviews.js]
[browser_panel_toggle.js]
[browser_panelUINotifications.js]
[browser_switch_to_customize_mode.js]

View File

@ -0,0 +1,69 @@
"use strict";
const kOverflowPanel = document.getElementById("widget-overflow");
var gOriginalWidth;
registerCleanupFunction(function*() {
kOverflowPanel.removeAttribute("animate");
window.resizeTo(gOriginalWidth, window.outerHeight);
CustomizableUI.reset();
});
/**
* This checks that subview-compatible items show up as subviews rather than
* re-anchored panels. If we ever remove the character encoding widget, please
* replace this test with another subview - don't remove it.
*/
add_task(async function check_character_encoding_subview_in_overflow() {
kOverflowPanel.setAttribute("animate", "false");
gOriginalWidth = window.outerWidth;
CustomizableUI.addWidgetToArea("developer-button", CustomizableUI.AREA_NAVBAR);
let navbar = document.getElementById(CustomizableUI.AREA_NAVBAR);
ok(!navbar.hasAttribute("overflowing"), "Should start with a non-overflowing toolbar.");
window.resizeTo(400, window.outerHeight);
await waitForCondition(() => navbar.hasAttribute("overflowing"));
let chevron = document.getElementById("nav-bar-overflow-button");
let shownPanelPromise = promisePanelElementShown(window, kOverflowPanel);
chevron.click();
await shownPanelPromise;
let developerView = document.getElementById("PanelUI-developer");
let button = document.getElementById("developer-button");
let subviewShownPromise = subviewShown(developerView);
button.click();
await subviewShownPromise;
is(developerView.closest("panel"), kOverflowPanel, "Should be inside the panel");
kOverflowPanel.hidePopup();
await Promise.resolve(); // wait for popup to hide fully.
CustomizableUI.reset();
});
/**
* This checks that non-subview-compatible items still work correctly.
* Ideally we should make the downloads panel and bookmarks/library item
* proper subview items, then this test can go away, and potentially we can
* simplify some of the subview anchoring code.
*/
add_task(async function check_downloads_panel_in_overflow() {
let navbar = document.getElementById(CustomizableUI.AREA_NAVBAR);
ok(navbar.hasAttribute("overflowing"), "Should still be overflowing");
let chevron = document.getElementById("nav-bar-overflow-button");
let shownPanelPromise = promisePanelElementShown(window, kOverflowPanel);
chevron.click();
await shownPanelPromise;
let button = document.getElementById("downloads-button");
button.click();
await waitForCondition(() => {
let panel = document.getElementById("downloadsPanel");
return panel && panel.state != "closed";
});
let downloadsPanel = document.getElementById("downloadsPanel");
isnot(downloadsPanel.state, "closed", "Should be attempting to show the downloads panel.");
downloadsPanel.hidePopup();
});

View File

@ -1859,7 +1859,7 @@ BrowserGlue.prototype = {
Services.prefs.clearUserPref("browser.tabs.animate");
Services.prefs.clearUserPref("browser.fullscreen.animate");
Services.prefs.clearUserPref("browser.tabs.animate");
Services.prefs.clearUserPref("alerts.disableSlidingEffect");
}
// Update the migration version.

View File

@ -334,6 +334,10 @@ this.SessionStore = {
SessionStoreInternal.deleteTabValue(aTab, aKey);
},
getLazyTabValue(aTab, aKey) {
return SessionStoreInternal.getLazyTabValue(aTab, aKey);
},
getGlobalValue: function ss_getGlobalValue(aKey) {
return SessionStoreInternal.getGlobalValue(aKey);
},
@ -1871,6 +1875,15 @@ var SessionStoreInternal = {
if (browser.frameLoader) {
this._lastKnownFrameLoader.set(browser.permanentKey, browser.frameLoader);
}
// Only restore if browser has been lazy.
if (aTab.__SS_lazyData && !browser.__SS_restoreState && TabStateCache.get(browser)) {
let tabState = TabState.clone(aTab);
this.restoreTab(aTab, tabState);
}
// The browser has been inserted now, so lazy data is no longer relevant.
delete aTab.__SS_lazyData;
},
/**
@ -2545,6 +2558,19 @@ var SessionStoreInternal = {
}
},
/**
* Retrieves data specific to lazy-browser tabs. If tab is not lazy,
* will return undefined.
*
* @param aTab (xul:tab)
* The tabbrowser-tab the data is for.
* @param aKey (string)
* The key which maps to the desired data.
*/
getLazyTabValue(aTab, aKey) {
return (aTab.__SS_lazyData || {})[aKey];
},
getGlobalValue: function ssi_getGlobalValue(aKey) {
return this._globalState.get(aKey);
},
@ -3272,6 +3298,9 @@ var SessionStoreInternal = {
let numVisibleTabs = 0;
let createLazyBrowser = this._prefBranch.getBoolPref("sessionstore.restore_tabs_lazily") &&
this._prefBranch.getBoolPref("sessionstore.restore_on_demand");
for (var t = 0; t < newTabCount; t++) {
// When trying to restore into existing tab, we also take the userContextId
// into account if present.
@ -3280,7 +3309,8 @@ var SessionStoreInternal = {
(tabbrowser.tabs[t].getAttribute("usercontextid") == (userContextId || ""));
let tab = reuseExisting ? this._maybeUpdateBrowserRemoteness(tabbrowser.tabs[t])
: tabbrowser.addTab("about:blank",
{ skipAnimation: true,
{ createLazyBrowser,
skipAnimation: true,
userContextId,
skipBackgroundNotify: true });
@ -3595,9 +3625,7 @@ var SessionStoreInternal = {
tabbrowser.selectedBrowser == browser ||
loadArguments;
if (!willRestoreImmediately && !forceOnDemand) {
TabRestoreQueue.add(tab);
}
let isBrowserInserted = browser.isConnected;
// Increase the busy state counter before modifying the tab.
this._setWindowStateBusy(window);
@ -3665,14 +3693,6 @@ var SessionStoreInternal = {
// Save the index in case we updated it above.
tabData.index = activeIndex + 1;
// Start a new epoch to discard all frame script messages relating to a
// previous epoch. All async messages that are still on their way to chrome
// will be ignored and don't override any tab data set when restoring.
let epoch = this.startNextEpoch(browser);
// keep the data around to prevent dataloss in case
// a tab gets closed before it's been properly restored
browser.__SS_restoreState = TAB_STATE_NEEDS_RESTORE;
browser.setAttribute("pending", "true");
tab.setAttribute("pending", "true");
@ -3700,26 +3720,57 @@ var SessionStoreInternal = {
userTypedClear: tabData.userTypedClear || 0
});
this._sendRestoreHistory(browser, {tabData, epoch, loadArguments});
// Update tab label and icon to show something
// while we wait for the messages to be processed.
this.updateTabLabelAndIcon(tab, tabData);
// Restore tab attributes.
if ("attributes" in tabData) {
TabAttributes.set(tab, tabData.attributes);
}
// This could cause us to ignore MAX_CONCURRENT_TAB_RESTORES a bit, but
// it ensures each window will have its selected tab loaded.
if (willRestoreImmediately) {
this.restoreTabContent(tab, loadArguments, reloadInFreshProcess,
restoreContentReason);
} else if (!forceOnDemand) {
this.restoreNextTab();
if (isBrowserInserted) {
// Start a new epoch to discard all frame script messages relating to a
// previous epoch. All async messages that are still on their way to chrome
// will be ignored and don't override any tab data set when restoring.
let epoch = this.startNextEpoch(browser);
// Ensure that the tab will get properly restored in the event the tab
// crashes while restoring. But don't set this on lazy browsers as
// restoreTab will get called again when the browser is instantiated.
browser.__SS_restoreState = TAB_STATE_NEEDS_RESTORE;
this._sendRestoreHistory(browser, {tabData, epoch, loadArguments});
// This could cause us to ignore MAX_CONCURRENT_TAB_RESTORES a bit, but
// it ensures each window will have its selected tab loaded.
if (willRestoreImmediately) {
this.restoreTabContent(tab, loadArguments, reloadInFreshProcess,
restoreContentReason);
} else if (!forceOnDemand) {
TabRestoreQueue.add(tab);
this.restoreNextTab();
}
} else {
// __SS_lazyData holds data for lazy-browser tabs to proxy for
// data unobtainable from the unbound browser. This only applies to lazy
// browsers and will be removed once the browser is inserted in the document.
// This must preceed `updateTabLabelAndIcon` call for required data to be present.
let url = "about:blank";
let title = "";
if (activeIndex in tabData.entries) {
url = tabData.entries[activeIndex].url;
title = tabData.entries[activeIndex].title || url;
}
tab.__SS_lazyData = {
url,
title,
userTypedValue: tabData.userTypedValue || "",
userTypedClear: tabData.userTypedClear || 0
};
}
// Update tab label and icon to show something
// while we wait for the messages to be processed.
this.updateTabLabelAndIcon(tab, tabData);
// Decrease the busy state counter after we're done.
this._setWindowStateReady(window);
},

View File

@ -32,11 +32,27 @@ function test() {
"We still know that no load is ongoing");
is(gURLBar.value, "example.com",
"Address bar's value correctly restored");
// Change tabs to make sure address bar value gets updated
gBrowser.selectedTab = gBrowser.tabContainer.getItemAtIndex(0);
is(gURLBar.value, "about:mozilla",
"Address bar's value correctly updated");
runNextTest();
// Change tabs to make sure address bar value gets updated. If tab is
// lazy, wait for SSTabRestored to ensure address bar has time to update.
let tabToSelect = gBrowser.tabContainer.getItemAtIndex(0);
if (tabToSelect.linkedBrowser.isConnected) {
gBrowser.selectedTab = tabToSelect;
is(gURLBar.value, "about:mozilla",
"Address bar's value correctly updated");
runNextTest();
} else {
gBrowser.tabContainer.addEventListener("SSTabRestored",
function SSTabRestored(event) {
if (event.target == tabToSelect) {
gBrowser.tabContainer.removeEventListener("SSTabRestored", SSTabRestored, true);
is(gURLBar.value, "about:mozilla",
"Address bar's value correctly updated");
runNextTest();
}
}, true);
gBrowser.selectedTab = tabToSelect;
}
});
}
@ -60,15 +76,34 @@ function test() {
"No history entries still sets currentURI to about:blank");
is(browser.userTypedValue, "example.org",
"userTypedValue was correctly restored");
ok(!browser.didStartLoadSinceLastUserTyping(),
"We still know that no load is ongoing");
// didStartLoadSinceLastUserTyping does not exist on lazy tabs.
if (browser.didStartLoadSinceLastUserTyping) {
ok(!browser.didStartLoadSinceLastUserTyping(),
"We still know that no load is ongoing");
}
is(gURLBar.value, "about:mozilla",
"Address bar's value correctly restored");
// Change tabs to make sure address bar value gets updated
gBrowser.selectedTab = gBrowser.tabContainer.getItemAtIndex(1);
is(gURLBar.value, "example.org",
"Address bar's value correctly updated");
runNextTest();
// Change tabs to make sure address bar value gets updated. If tab is
// lazy, wait for SSTabRestored to ensure address bar has time to update.
let tabToSelect = gBrowser.tabContainer.getItemAtIndex(1);
if (tabToSelect.linkedBrowser.isConnected) {
gBrowser.selectedTab = tabToSelect;
is(gURLBar.value, "example.org",
"Address bar's value correctly updated");
runNextTest();
} else {
gBrowser.tabContainer.addEventListener("SSTabRestored",
function SSTabRestored(event) {
if (event.target == tabToSelect) {
gBrowser.tabContainer.removeEventListener("SSTabRestored", SSTabRestored, true);
is(gURLBar.value, "example.org",
"Address bar's value correctly updated");
runNextTest();
}
}, true);
gBrowser.selectedTab = tabToSelect;
}
});
}

View File

@ -5,10 +5,9 @@
var stateBackup = ss.getBrowserState();
function cleanup() {
// Reset the pref
try {
Services.prefs.clearUserPref("browser.sessionstore.restore_on_demand");
} catch (e) {}
// Reset the prefs
Services.prefs.clearUserPref("browser.sessionstore.restore_on_demand");
Services.prefs.clearUserPref("browser.sessionstore.restore_tabs_lazily");
ss.setBrowserState(stateBackup);
executeSoon(finish);
}
@ -20,6 +19,8 @@ function test() {
// Set the pref to true so we know exactly how many tabs should be restoring at
// any given time. This guarantees that a finishing load won't start another.
Services.prefs.setBoolPref("browser.sessionstore.restore_on_demand", true);
// Don't restore tabs lazily.
Services.prefs.setBoolPref("browser.sessionstore.restore_tabs_lazily", false);
let state = { windows: [{ tabs: [
{ entries: [{ url: "http://example.org/#1", triggeringPrincipal_base64 }] },

View File

@ -9,6 +9,8 @@ add_task(function* () {
// Set the pref to true so we know exactly how many tabs should be restoring at
// any given time. This guarantees that a finishing load won't start another.
Services.prefs.setBoolPref("browser.sessionstore.restore_on_demand", true);
// Don't restore tabs lazily.
Services.prefs.setBoolPref("browser.sessionstore.restore_tabs_lazily", false);
let state = { windows: [{ tabs: [
{ entries: [{ url: "http://example.org#1", triggeringPrincipal_base64 }], extData: { "uniq": r() } },
@ -92,5 +94,7 @@ add_task(function* () {
yield progressCallback();
// Cleanup.
Services.prefs.clearUserPref("browser.sessionstore.restore_on_demand");
Services.prefs.clearUserPref("browser.sessionstore.restore_tabs_lazily");
yield promiseBrowserState(stateBackup);
});

View File

@ -97,22 +97,26 @@ function test_setTabState() {
ss.setTabValue(tab, "baz", "qux");
}
function onSSTabRestored(aEvent) {
is(busyEventCount, 1);
is(readyEventCount, 1);
is(ss.getTabValue(tab, "baz"), "qux");
is(tab.linkedBrowser.currentURI.spec, "http://example.org/");
function onSSTabRestoring(aEvent) {
if (aEvent.target == tab) {
is(busyEventCount, 1);
is(readyEventCount, 1);
is(ss.getTabValue(tab, "baz"), "qux");
is(tab.linkedBrowser.currentURI.spec, "http://example.org/");
window.removeEventListener("SSWindowStateBusy", onSSWindowStateBusy);
window.removeEventListener("SSWindowStateReady", onSSWindowStateReady);
gBrowser.tabContainer.removeEventListener("SSTabRestored", onSSTabRestored);
window.removeEventListener("SSWindowStateBusy", onSSWindowStateBusy);
window.removeEventListener("SSWindowStateReady", onSSWindowStateReady);
gBrowser.tabContainer.removeEventListener("SSTabRestoring", onSSTabRestoring);
runNextTest();
runNextTest();
}
}
window.addEventListener("SSWindowStateBusy", onSSWindowStateBusy);
window.addEventListener("SSWindowStateReady", onSSWindowStateReady);
gBrowser.tabContainer.addEventListener("SSTabRestored", onSSTabRestored);
gBrowser.tabContainer.addEventListener("SSTabRestoring", onSSTabRestoring);
// Browser must be inserted in order to restore.
gBrowser._insertBrowser(tab);
ss.setTabState(tab, newTabState);
}
@ -137,23 +141,26 @@ function test_duplicateTab() {
ss.setTabValue(newTab, "baz", "qux");
}
function onSSTabRestored(aEvent) {
is(busyEventCount, 1);
is(readyEventCount, 1);
is(ss.getTabValue(newTab, "baz"), "qux");
is(newTab.linkedBrowser.currentURI.spec, "about:rights");
function onSSTabRestoring(aEvent) {
if (aEvent.target == newTab) {
is(busyEventCount, 1);
is(readyEventCount, 1);
is(ss.getTabValue(newTab, "baz"), "qux");
is(newTab.linkedBrowser.currentURI.spec, "about:rights");
window.removeEventListener("SSWindowStateBusy", onSSWindowStateBusy);
window.removeEventListener("SSWindowStateReady", onSSWindowStateReady);
gBrowser.tabContainer.removeEventListener("SSTabRestored", onSSTabRestored);
window.removeEventListener("SSWindowStateBusy", onSSWindowStateBusy);
window.removeEventListener("SSWindowStateReady", onSSWindowStateReady);
gBrowser.tabContainer.removeEventListener("SSTabRestoring", onSSTabRestoring);
runNextTest();
runNextTest();
}
}
window.addEventListener("SSWindowStateBusy", onSSWindowStateBusy);
window.addEventListener("SSWindowStateReady", onSSWindowStateReady);
gBrowser.tabContainer.addEventListener("SSTabRestored", onSSTabRestored);
gBrowser.tabContainer.addEventListener("SSTabRestoring", onSSTabRestoring);
gBrowser._insertBrowser(tab);
newTab = ss.duplicateTab(window, tab);
}

View File

@ -147,7 +147,6 @@ add_task(function* test_scroll_background_tabs() {
// The second tab should be the one we loaded URL at still
tab = newWin.gBrowser.tabs[1];
yield promiseTabRestoring(tab);
ok(tab.hasAttribute("pending"), "Tab should be pending");
browser = tab.linkedBrowser;

View File

@ -47,7 +47,6 @@ add_task(function* test_scroll_background_about_reader_tabs() {
// The second tab should be the one we loaded URL at still
tab = newWin.gBrowser.tabs[1];
yield promiseTabRestoring(tab);
ok(tab.hasAttribute("pending"), "Tab should be pending");
browser = tab.linkedBrowser;

View File

@ -94,18 +94,24 @@ function waitForBrowserState(aState, aSetStateCallback) {
let windowObserving = false;
let restoreHiddenTabs = Services.prefs.getBoolPref(
"browser.sessionstore.restore_hidden_tabs");
let restoreTabsLazily = Services.prefs.getBoolPref(
"browser.sessionstore.restore_tabs_lazily");
aState.windows.forEach(function(winState) {
winState.tabs.forEach(function(tabState) {
if (restoreHiddenTabs || !tabState.hidden)
if (!restoreTabsLazily && (restoreHiddenTabs || !tabState.hidden))
expectedTabsRestored++;
});
});
// There must be only hidden tabs and restoreHiddenTabs = false. We still
// If there are only hidden tabs and restoreHiddenTabs = false, we still
// expect one of them to be restored because it gets shown automatically.
if (!expectedTabsRestored)
// Otherwise if lazy tab restore there will only be one tab restored per window.
if (!expectedTabsRestored) {
expectedTabsRestored = 1;
} else if (restoreTabsLazily) {
expectedTabsRestored = aState.windows.length;
}
function onSSTabRestored(aEvent) {
if (++tabsRestored == expectedTabsRestored) {
@ -376,11 +382,11 @@ var gProgressListener = {
for (let win of BrowserWindowIterator()) {
for (let i = 0; i < win.gBrowser.tabs.length; i++) {
let browser = win.gBrowser.tabs[i].linkedBrowser;
if (!browser.__SS_restoreState)
if (browser.isConnected && !browser.__SS_restoreState)
wasRestored++;
else if (browser.__SS_restoreState == TAB_STATE_RESTORING)
isRestoring++;
else if (browser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE)
else if (browser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE || !browser.isConnected)
needsRestore++;
}
}

View File

@ -127,6 +127,7 @@ function defineCohort() {
setCohort("optedOut");
} else if (userOptedIn.e10s) {
setCohort("optedIn");
inMultiExperiment = true;
} else if (temporaryDisqualification != "") {
// Users who are disqualified by the backend (from multiprocessBlockPolicy)
// can be put into either the test or control groups, because e10s will
@ -185,7 +186,7 @@ function defineCohort() {
let multiUserSample = getUserSample(true);
for (let sampleName of Object.getOwnPropertyNames(BUCKETS)) {
if (multiUserSample < BUCKETS[sampleName]) {
setCohort(`${cohortPrefix}multiBucket${sampleName}`);
setCohort(`multiBucket${sampleName}`);
Preferences.set(PREF_E10S_PROCESSCOUNT + ".web", sampleName);
break;
}

View File

@ -10,7 +10,8 @@
- loaded as a stacked subdialog. -->
<link rel="stylesheet" href="chrome://global/skin/in-content/common.css" />
<link rel="stylesheet" href="chrome://browser/skin/preferences/in-content/dialog.css" />
<link rel="stylesheet" href="chrome://formautofill/content/editProfile.css" />
<link rel="stylesheet" href="chrome://formautofill-shared/skin/editProfile.css" />
<link rel="stylesheet" href="chrome://formautofill/skin/editProfile.css" />
<script src="chrome://formautofill/content/editProfile.js"></script>
</head>
<body>

View File

@ -0,0 +1,5 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
/* Linux specific rules */

View File

@ -0,0 +1,5 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
/* OSX specific rules */

View File

@ -0,0 +1,12 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
/* The save button should be on the left and cancel on the right for Windows */
#save {
order: 0;
}
#cancel {
order: 1;
}

View File

@ -1,3 +1,3 @@
This is the pdf.js project output, https://github.com/mozilla/pdf.js
Current extension version is: 1.8.229
Current extension version is: 1.8.243

View File

@ -90,7 +90,7 @@ var PdfjsChromeUtils = {
this._mmg.addMessageListener("PDFJS:Parent:removeEventListener", this);
this._mmg.addMessageListener("PDFJS:Parent:updateControlState", this);
// observer to handle shutdown
// Observer to handle shutdown.
Services.obs.addObserver(this, "quit-application");
}
},

View File

@ -45,6 +45,7 @@ var PdfjsContentUtils = {
this._mm = Cc["@mozilla.org/childprocessmessagemanager;1"].
getService(Ci.nsISyncMessageSender);
this._mm.addMessageListener("PDFJS:Child:refreshSettings", this);
Services.obs.addObserver(this, "quit-application");
}
},

View File

@ -961,12 +961,12 @@ var createBlob = function createBlob(data, contentType) {
if (typeof Blob !== 'undefined') {
return new Blob([data], { type: contentType });
}
warn('The "Blob" constructor is not supported.');
throw new Error('The "Blob" constructor is not supported.');
};
var createObjectURL = function createObjectURLClosure() {
var digits = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
return function createObjectURL(data, contentType, forceDataSchema) {
if (!forceDataSchema && typeof URL !== 'undefined' && URL.createObjectURL) {
return function createObjectURL(data, contentType, forceDataSchema = false) {
if (!forceDataSchema) {
var blob = createBlob(data, contentType);
return URL.createObjectURL(blob);
}
@ -3391,8 +3391,8 @@ var _UnsupportedManager = function UnsupportedManagerClosure() {
}();
var version, build;
{
exports.version = version = '1.8.229';
exports.build = build = '5ad3611c';
exports.version = version = '1.8.243';
exports.build = build = '96cb599e';
}
exports.getDocument = getDocument;
exports.PDFDataRangeTransport = PDFDataRangeTransport;
@ -4394,8 +4394,8 @@ if (!_util.globalScope.PDFJS) {
}
var PDFJS = _util.globalScope.PDFJS;
{
PDFJS.version = '1.8.229';
PDFJS.build = '5ad3611c';
PDFJS.version = '1.8.243';
PDFJS.build = '96cb599e';
}
PDFJS.pdfBug = false;
if (PDFJS.verbosity !== undefined) {
@ -6709,8 +6709,8 @@ exports.TilingPattern = TilingPattern;
"use strict";
var pdfjsVersion = '1.8.229';
var pdfjsBuild = '5ad3611c';
var pdfjsVersion = '1.8.243';
var pdfjsBuild = '96cb599e';
var pdfjsSharedUtil = __w_pdfjs_require__(0);
var pdfjsDisplayGlobal = __w_pdfjs_require__(8);
var pdfjsDisplayAPI = __w_pdfjs_require__(3);

View File

@ -961,12 +961,12 @@ var createBlob = function createBlob(data, contentType) {
if (typeof Blob !== 'undefined') {
return new Blob([data], { type: contentType });
}
warn('The "Blob" constructor is not supported.');
throw new Error('The "Blob" constructor is not supported.');
};
var createObjectURL = function createObjectURLClosure() {
var digits = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
return function createObjectURL(data, contentType, forceDataSchema) {
if (!forceDataSchema && typeof URL !== 'undefined' && URL.createObjectURL) {
return function createObjectURL(data, contentType, forceDataSchema = false) {
if (!forceDataSchema) {
var blob = createBlob(data, contentType);
return URL.createObjectURL(blob);
}
@ -36565,8 +36565,8 @@ exports.Type1Parser = Type1Parser;
"use strict";
var pdfjsVersion = '1.8.229';
var pdfjsBuild = '5ad3611c';
var pdfjsVersion = '1.8.243';
var pdfjsBuild = '96cb599e';
var pdfjsCoreWorker = __w_pdfjs_require__(17);
;
exports.WorkerMessageHandler = pdfjsCoreWorker.WorkerMessageHandler;

View File

@ -315,9 +315,18 @@ function getVisibleElements(scrollEl, views, sortByVisibility) {
function noContextMenuHandler(e) {
e.preventDefault();
}
function getPDFFileNameFromURL(url, defaultFilename) {
if (typeof defaultFilename === 'undefined') {
defaultFilename = 'document.pdf';
function isDataSchema(url) {
var i = 0,
ii = url.length;
while (i < ii && url[i].trim() === '') {
i++;
}
return url.substr(i, 5).toLowerCase() === 'data:';
}
function getPDFFileNameFromURL(url, defaultFilename = 'document.pdf') {
if (isDataSchema(url)) {
console.warn('getPDFFileNameFromURL: ' + 'ignoring "data:" URL for performance reasons.');
return defaultFilename;
}
var reURI = /^(?:(?:[^:]+:)?\/\/[^\/]+)?([^?#]*)(\?[^#]*)?(#.*)?$/;
var reFilename = /[^\/?#=]+\.pdf\b(?!.*\.pdf\b)/i;
@ -3869,11 +3878,14 @@ var PDFAttachmentViewer = function PDFAttachmentViewerClosure() {
});
this._renderedCapability.resolve();
},
_bindPdfLink: function PDFAttachmentViewer_bindPdfLink(button, content, filename) {
_bindPdfLink(button, content, filename) {
if (_pdfjs.PDFJS.disableCreateObjectURL) {
throw new Error('bindPdfLink: ' + 'Unsupported "PDFJS.disableCreateObjectURL" value.');
}
var blobUrl;
button.onclick = function () {
if (!blobUrl) {
blobUrl = (0, _pdfjs.createObjectURL)(content, 'application/pdf', _pdfjs.PDFJS.disableCreateObjectURL);
blobUrl = (0, _pdfjs.createObjectURL)(content, 'application/pdf');
}
var viewerUrl;
viewerUrl = blobUrl + '?' + encodeURIComponent(filename);
@ -3911,7 +3923,7 @@ var PDFAttachmentViewer = function PDFAttachmentViewerClosure() {
div.className = 'attachmentsItem';
var button = document.createElement('button');
button.textContent = filename;
if (/\.pdf$/i.test(filename)) {
if (/\.pdf$/i.test(filename) && !_pdfjs.PDFJS.disableCreateObjectURL) {
this._bindPdfLink(button, item.content, filename);
} else {
this._bindLink(button, item.content, filename);
@ -7630,7 +7642,7 @@ var pdfjsWebApp;
pdfjsWebApp = __webpack_require__(4);
}
{
window.FirefoxCom = __webpack_require__(10).FirefoxCom;
__webpack_require__(10);
__webpack_require__(9);
}
;

View File

@ -696,10 +696,6 @@
@RESPATH@/res/fonts/*
@RESPATH@/res/dtd/*
@RESPATH@/res/html/*
#if defined(XP_MACOSX)
; For SafariProfileMigrator.js.
@RESPATH@/res/langGroups.properties
#endif
@RESPATH@/res/language.properties
@RESPATH@/res/entityTables/*
#ifdef XP_MACOSX

View File

@ -98,8 +98,7 @@ let customizationListener = {
};
customizationListener.onWidgetAdded =
customizationListener.onWidgetRemoved =
customizationListener.onWidgetMoved =
customizationListener.onWidgetInstanceRemoved = function(aWidgetId) {
customizationListener.onWidgetMoved = function(aWidgetId) {
if (aWidgetId == "zoom-controls") {
for (let window of CustomizableUI.windows) {
updateZoomUI(window.gBrowser.selectedBrowser);

View File

@ -92,12 +92,22 @@ var BrowserHelper = {
},
increasePriority: function NP_BH_increasePriority(aBrowser) {
// Ignore if browser is lazy. Once the browser is instantiated, this will
// get taken care of by TabBrowserInserted and TabSelect handlers.
if (!aBrowser.isConnected) {
return;
}
aBrowser.adjustPriority(PRIORITY_DELTA);
_priorityBackup.set(aBrowser.permanentKey,
_priorityBackup.get(aBrowser.permanentKey) + PRIORITY_DELTA);
},
decreasePriority: function NP_BH_decreasePriority(aBrowser) {
// Ignore if browser is lazy. Once the browser is instantiated, this will
// get taken care of by TabBrowserInserted and TabSelect handlers.
if (!aBrowser.isConnected) {
return;
}
aBrowser.adjustPriority(PRIORITY_DELTA * -1);
_priorityBackup.set(aBrowser.permanentKey,
_priorityBackup.get(aBrowser.permanentKey) - PRIORITY_DELTA);

View File

@ -34,6 +34,7 @@ run-if = crashreporter
[browser_UsageTelemetry.js]
[browser_UsageTelemetry_private_and_restore.js]
[browser_UsageTelemetry_urlbar.js]
skip-if = (os == 'linux' && bits == 32 && debug) # bug 1356758
support-files =
usageTelemetrySearchSuggestions.sjs
usageTelemetrySearchSuggestions.xml

View File

@ -553,7 +553,7 @@ menuitem.bookmark-item {
/* Menu panel buttons */
%include ../shared/toolbarbuttons.inc.css
%include ../shared/toolbarbutton-icons.inc.css
%include ../shared/menupanel.inc.css
#main-window:not([customizing]) .toolbarbutton-1[disabled=true] > .toolbarbutton-icon,

View File

@ -726,7 +726,7 @@ toolbar .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker > .dropmarker-ic
-moz-box-align: center;
}
%include ../shared/toolbarbuttons.inc.css
%include ../shared/toolbarbutton-icons.inc.css
%include ../shared/menupanel.inc.css
@media not all and (min-resolution: 1.1dppx) {

View File

@ -578,7 +578,7 @@ menuitem.bookmark-item {
/* ::::: primary toolbar buttons ::::: */
%include ../shared/toolbarbuttons.inc.css
%include ../shared/toolbarbutton-icons.inc.css
#main-window:not([customizing]) .toolbarbutton-1[disabled=true] > .toolbarbutton-icon,
#main-window:not([customizing]) .toolbarbutton-1[disabled=true] > .toolbarbutton-menu-dropmarker,

View File

@ -7,7 +7,7 @@ console.assert(false, "Failing mozscreenshots assertion");
console.group("Grouped Message");
console.log("group message 1");
console.groupEnd("Grouped Message");
console.groupEnd();
console.count("counter");
console.count("counter");

View File

@ -504,6 +504,13 @@ set_config('HAVE_64BIT_BUILD', have_64_bit)
set_define('HAVE_64BIT_BUILD', have_64_bit)
add_old_configure_assignment('HAVE_64BIT_BUILD', have_64_bit)
@depends(host)
def host_os_kernel_major_version(host):
versions = host.raw_os.split('.')
version = ''.join(x for x in versions[0] if x.isdigit())
return version
set_config('HOST_MAJOR_VERSION', host_os_kernel_major_version)
# Autoconf needs these set
@depends(host)

View File

@ -61,6 +61,9 @@ check_and_add_gcc_warning('-Wc++14-compat', cxx_compiler)
check_and_add_gcc_warning('-Wc++14-compat-pedantic', cxx_compiler)
check_and_add_gcc_warning('-Wc++1z-compat', cxx_compiler)
# catches possible misuse of the comma operator
check_and_add_gcc_warning('-Wcomma', cxx_compiler)
# catches unintentional switch case fallthroughs
check_and_add_gcc_warning('-Wimplicit-fallthrough', cxx_compiler)

View File

@ -40,6 +40,10 @@ elif CONFIG['OS_TARGET'] in ('FreeBSD', 'OpenBSD', 'NetBSD'):
SOURCES += ['/nsprpub/pr/src/md/unix/%s.c' % CONFIG['OS_TARGET'].lower()]
elif CONFIG['OS_TARGET'] == 'Darwin':
OS_LIBS += ['-framework CoreServices']
if CONFIG['HOST_MAJOR_VERSION'] == '15':
DEFINES.update(
HAS_CONNECTX=True,
)
DEFINES.update(
DARWIN=True,
HAVE_BSD_FLOCK=True,

View File

@ -26,7 +26,7 @@ module.exports = createClass({
displayName: "multiE10SWarning",
onUpdatePreferenceClick() {
let message = Strings.GetStringFromName("multiProcessWarningConfirmUpdate");
let message = Strings.GetStringFromName("multiProcessWarningConfirmUpdate2");
if (window.confirm(message)) {
// Disable multi until at least the next experiment.
Services.prefs.setIntPref(MULTI_OPT_OUT_PREF,
@ -48,14 +48,14 @@ module.exports = createClass({
),
dom.div(
{},
Strings.GetStringFromName("multiProcessWarningMessage")
Strings.GetStringFromName("multiProcessWarningMessage2")
),
dom.button(
{
className: "update-button",
onClick: this.onUpdatePreferenceClick,
},
Strings.GetStringFromName("multiProcessWarningUpdateLink")
Strings.GetStringFromName("multiProcessWarningUpdateLink2")
)
);
},

View File

@ -31,6 +31,7 @@ const Strings = Services.strings.createBundle(
const WorkerIcon = "chrome://devtools/skin/images/debugging-workers.svg";
const MORE_INFO_URL = "https://developer.mozilla.org/en-US/docs/Tools/about%3Adebugging";
const PROCESS_COUNT_PREF = "dom.ipc.processCount";
const MULTI_OPTOUT_PREF = "dom.ipc.multiOptOut";
module.exports = createClass({
displayName: "WorkersPanel",
@ -58,7 +59,20 @@ module.exports = createClass({
client.addListener("processListChanged", this.updateWorkers);
client.addListener("registration-changed", this.updateWorkers);
// Some notes about these observers:
// - nsIPrefBranch.addObserver observes prefixes. In reality, watching
// PROCESS_COUNT_PREF watches two separate prefs:
// dom.ipc.processCount *and* dom.ipc.processCount.web. Because these
// are the two ways that we control the number of content processes,
// that works perfectly fine.
// - The user might opt in or out of multi by setting the multi opt out
// pref. That affects whether we need to show our warning, so we need to
// update our state when that pref changes.
// - In all cases, we don't have to manually check which pref changed to
// what. The platform code in nsIXULRuntime.maxWebProcessCount does all
// of that for us.
Services.prefs.addObserver(PROCESS_COUNT_PREF, this.updateMultiE10S);
Services.prefs.addObserver(MULTI_OPTOUT_PREF, this.updateMultiE10S);
this.updateMultiE10S();
this.updateWorkers();
@ -72,11 +86,12 @@ module.exports = createClass({
client.removeListener("registration-changed", this.updateWorkers);
Services.prefs.removeObserver(PROCESS_COUNT_PREF, this.updateMultiE10S);
Services.prefs.removeObserver(MULTI_OPTOUT_PREF, this.updateMultiE10S);
},
updateMultiE10S() {
// We watch the pref but set the state based on
// nsIXULRuntime::maxWebProcessCount.
// nsIXULRuntime.maxWebProcessCount.
let processCount = Services.appinfo.maxWebProcessCount;
this.setState({ processCount });
},

View File

@ -79,7 +79,6 @@ function loadTelemetryAndRecordLogs() {
info("Mock the Telemetry log function to record logged information");
let Telemetry = require("devtools/client/shared/telemetry");
Telemetry.prototype.telemetryInfo = {};
Telemetry.prototype._oldlog = Telemetry.prototype.log;
Telemetry.prototype.log = function (histogramId, value) {
@ -94,6 +93,8 @@ function loadTelemetryAndRecordLogs() {
this.telemetryInfo[histogramId].push(value);
}
};
Telemetry.prototype._oldlogScalar = Telemetry.prototype.logScalar;
Telemetry.prototype.logScalar = Telemetry.prototype.log;
Telemetry.prototype._oldlogKeyed = Telemetry.prototype.logKeyed;
Telemetry.prototype.logKeyed = function (histogramId, key, value) {
this.log(`${histogramId}|${key}`, value);
@ -110,8 +111,10 @@ function loadTelemetryAndRecordLogs() {
function stopRecordingTelemetryLogs(Telemetry) {
info("Stopping Telemetry");
Telemetry.prototype.log = Telemetry.prototype._oldlog;
Telemetry.prototype.logScalar = Telemetry.prototype._oldlogScalar;
Telemetry.prototype.logKeyed = Telemetry.prototype._oldlogKeyed;
delete Telemetry.prototype._oldlog;
delete Telemetry.prototype._oldlogScalar;
delete Telemetry.prototype._oldlogKeyed;
delete Telemetry.prototype.telemetryInfo;
}

View File

@ -95,7 +95,7 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, {
this._preferredSourceURL = null;
this._unnamedSourceIndex = 0;
this.emptyText = L10N.getStr("noSourcesText");
this._blackBoxCheckboxTooltip = L10N.getStr("blackBoxCheckboxTooltip");
this._blackBoxCheckboxTooltip = L10N.getStr("blackboxCheckboxTooltip2");
this._commandset = document.getElementById("debuggerCommands");
this._popupset = document.getElementById("debuggerPopupset");

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -7,6 +7,6 @@ DevToolsModules(
'debugger.css',
'debugger.js',
'panel.js',
'parser-worker.js',
'pretty-print-worker.js',
'source-map-worker.js'
)

View File

@ -4,7 +4,7 @@
"use strict";
const { Task } = require("devtools/shared/task");
var {LocalizationHelper} = require("devtools/shared/l10n");
var { LocalizationHelper } = require("devtools/shared/l10n");
const DBG_STRINGS_URI = "devtools/client/locales/debugger.properties";
var L10N = new LocalizationHelper(DBG_STRINGS_URI);
@ -16,38 +16,46 @@ function DebuggerPanel(iframeWindow, toolbox) {
}
DebuggerPanel.prototype = {
open: Task.async(function* () {
open: async function() {
if (!this.toolbox.target.isRemote) {
yield this.toolbox.target.makeRemote();
await this.toolbox.target.makeRemote();
}
yield this.panelWin.Debugger.bootstrap({
const {
actions,
store,
selectors,
client
} = await this.panelWin.Debugger.bootstrap({
threadClient: this.toolbox.threadClient,
tabTarget: this.toolbox.target
tabTarget: this.toolbox.target,
debuggerClient: this.toolbox.target._client,
sourceMaps: this.toolbox.sourceMapService
});
this._actions = actions;
this._store = store;
this._selectors = selectors;
this._client = client;
this.isReady = true;
return this;
}),
_store: function () {
return this.panelWin.Debugger.store;
},
_getState: function () {
return this._store().getState();
getVarsForTests() {
return {
store: this._store,
selectors: this._selectors,
actions: this._actions,
client: this._client
};
},
_actions: function () {
return this.panelWin.Debugger.actions;
_getState: function() {
return this._store.getState();
},
_selectors: function () {
return this.panelWin.Debugger.selectors;
},
getFrames: function () {
let frames = this._selectors().getFrames(this._getState());
getFrames: function() {
let frames = this._selectors.getFrames(this._getState());
// Frames is null when the debugger is not paused.
if (!frames) {
@ -58,7 +66,7 @@ DebuggerPanel.prototype = {
}
frames = frames.toJS();
const selectedFrame = this._selectors().getSelectedFrame(this._getState());
const selectedFrame = this._selectors.getSelectedFrame(this._getState());
const selected = frames.findIndex(frame => frame.id == selectedFrame.id);
frames.forEach(frame => {
@ -68,7 +76,15 @@ DebuggerPanel.prototype = {
return { frames, selected };
},
destroy: function () {
selectSource(sourceURL, sourceLine) {
this._actions.selectSourceURL(sourceURL, { line: sourceLine });
},
getSource(sourceURL) {
return this._selectors.getSourceByURL(this._getState(), sourceURL);
},
destroy: function() {
this.panelWin.Debugger.destroy();
this.emit("destroyed");
}

File diff suppressed because one or more lines are too long

View File

@ -55,7 +55,7 @@ return /******/ (function(modules) { // webpackBootstrap
/***/ 0:
/***/ function(module, exports, __webpack_require__) {
module.exports = __webpack_require__(801);
module.exports = __webpack_require__(964);
/***/ },
@ -75,76 +75,6 @@ return /******/ (function(modules) { // webpackBootstrap
/***/ },
/***/ 801:
/***/ function(module, exports, __webpack_require__) {
"use strict";
var prettyFast = __webpack_require__(802);
var assert = __webpack_require__(223);
function prettyPrint(_ref) {
var url = _ref.url,
indent = _ref.indent,
source = _ref.source;
try {
var prettified = prettyFast(source, {
url: url,
indent: " ".repeat(indent)
});
return {
code: prettified.code,
mappings: prettified.map._mappings
};
} catch (e) {
throw new Error(`${e.message}\n${e.stack}`);
}
}
function invertMappings(mappings) {
return mappings._array.map(m => {
var mapping = {
generated: {
line: m.originalLine,
column: m.originalColumn
}
};
if (m.source) {
mapping.source = m.source;
mapping.original = {
line: m.generatedLine,
column: m.generatedColumn
};
mapping.name = m.name;
}
return mapping;
});
}
self.onmessage = function (msg) {
var _msg$data = msg.data,
id = _msg$data.id,
args = _msg$data.args;
assert(msg.data.method === "prettyPrint", "Method must be `prettyPrint`");
try {
var _prettyPrint = prettyPrint(args[0]),
code = _prettyPrint.code,
mappings = _prettyPrint.mappings;
self.postMessage({ id, response: {
code, mappings: invertMappings(mappings)
} });
} catch (e) {
self.postMessage({ id, error: e });
}
};
/***/ },
/***/ 802:
/***/ function(module, exports, __webpack_require__) {
@ -5918,6 +5848,80 @@ return /******/ (function(modules) { // webpackBootstrap
}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
/***/ },
/***/ 964:
/***/ function(module, exports, __webpack_require__) {
"use strict";
var prettyFast = __webpack_require__(802);
var assert = __webpack_require__(223);
function prettyPrint(_ref) {
var url = _ref.url,
indent = _ref.indent,
source = _ref.source;
try {
var prettified = prettyFast(source, {
url: url,
indent: " ".repeat(indent)
});
return {
code: prettified.code,
mappings: prettified.map._mappings
};
} catch (e) {
throw new Error(`${e.message}\n${e.stack}`);
}
}
function invertMappings(mappings) {
return mappings._array.map(m => {
var mapping = {
generated: {
line: m.originalLine,
column: m.originalColumn
}
};
if (m.source) {
mapping.source = m.source;
mapping.original = {
line: m.generatedLine,
column: m.generatedColumn
};
mapping.name = m.name;
}
return mapping;
});
}
self.onmessage = function (msg) {
var _msg$data = msg.data,
id = _msg$data.id,
args = _msg$data.args;
assert(msg.data.method === "prettyPrint", "Method must be `prettyPrint`");
try {
var _prettyPrint = prettyPrint(args[0]),
code = _prettyPrint.code,
mappings = _prettyPrint.mappings;
self.postMessage({
id,
response: {
code,
mappings: invertMappings(mappings)
}
});
} catch (e) {
self.postMessage({ id, error: e });
}
};
/***/ }
/******/ })

File diff suppressed because it is too large Load Diff

View File

@ -42,6 +42,7 @@ support-files =
[browser_dbg-breakpoints.js]
[browser_dbg-breakpoints-cond.js]
[browser_dbg-call-stack.js]
[browser_dbg-expressions.js]
[browser_dbg-scopes.js]
[browser_dbg-chrome-create.js]
[browser_dbg-chrome-debugging.js]

View File

@ -54,6 +54,6 @@ add_task(function* () {
button = toggleButton(dbg);
frames = findAllElements(dbg, "frames");
is(button.innerText, "Collapse Rows", "toggle button should be collapse");
is(button.innerText, "Collapse Rows", "toggle button should be collapsed");
is(frames.length, 22, "All of the frames should be shown");
});

View File

@ -18,7 +18,9 @@ add_task(function* () {
// Wait for the source text to load and make sure we're in the right
// place.
yield waitForDispatch(dbg, "LOAD_SOURCE_TEXT");
assertHighlightLocation(dbg, "long.js", 66);
// TODO: revisit highlighting lines when the debugger opens
//assertHighlightLocation(dbg, "long.js", 66);
// Jump to line 16 and make sure the editor scrolled.
yield selectSource(dbg, "long.js", 16);

View File

@ -50,5 +50,5 @@ add_task(function* () {
invokeInTab("testModel");
yield waitForPaused(dbg);
assertPausedLocation(dbg, longSrc, 66);
// ok(isElementVisible(dbg, "breakpoint"), "Breakpoint is visible");
ok(isElementVisible(dbg, "breakpoint"), "Breakpoint is visible");
});

View File

@ -1,12 +1,56 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
const {
setupTestRunner,
expressions
} = require("devtools/client/debugger/new/integration-tests");
/**
* tests the watch expressions component
* 1. add watch expressions
* 2. edit watch expressions
* 3. delete watch expressions
*/
const expressionSelectors = {
input: "input.input-expression"
};
function getLabel(dbg, index) {
return findElement(dbg, "expressionNode", index).innerText;
}
function getValue(dbg, index) {
return findElement(dbg, "expressionValue", index).innerText;
}
async function addExpression(dbg, input) {
info("Adding an expression");
findElementWithSelector(dbg, expressionSelectors.input).focus();
type(dbg, input);
pressKey(dbg, "Enter");
await waitForDispatch(dbg, "EVALUATE_EXPRESSION");
}
async function editExpression(dbg, input) {
info("updating the expression");
dblClickElement(dbg, "expressionNode", 1);
type(dbg, input);
pressKey(dbg, "Enter");
await waitForDispatch(dbg, "EVALUATE_EXPRESSION");
}
add_task(function*() {
setupTestRunner(this);
yield expressions(this);
const dbg = yield initDebugger("doc-script-switching.html");
invokeInTab("firstCall");
yield waitForPaused(dbg);
yield addExpression(dbg, "f");
is(getLabel(dbg, 1), "f");
is(getValue(dbg, 1), "ReferenceError");
yield editExpression(dbg, "oo");
is(getLabel(dbg, 1), "foo()");
is(getValue(dbg, 1), "");
yield deleteExpression(dbg, "foo");
is(findAllElements(dbg, "expressionNodes").length, 0);
});

View File

@ -20,7 +20,6 @@ add_task(function* () {
const dbg = yield initDebugger("doc-exceptions.html");
// test skipping an uncaught exception
yield togglePauseOnExceptions(dbg, false, false);
yield uncaughtException();
ok(!isPaused(dbg));

View File

@ -3,7 +3,7 @@
// Tests basic pretty-printing functionality.
add_task(function* () {
add_task(function*() {
const dbg = yield initDebugger("doc-minified.html");
yield selectSource(dbg, "math.min.js");

View File

@ -19,4 +19,13 @@ add_task(function* () {
is(getLabel(dbg, 1), "secondCall");
is(getLabel(dbg, 2), "<this>");
is(getLabel(dbg, 4), "foo()");
toggleNode(dbg, 4);
yield waitForDispatch(dbg, "LOAD_OBJECT_PROPERTIES");
is(getLabel(dbg, 5), "prototype");
yield stepOver(dbg);
is(getLabel(dbg, 4), "foo()");
is(getLabel(dbg, 5), "prototype");
});

View File

@ -4,7 +4,10 @@
// Test that an error while loading a sourcemap does not break
// debugging.
add_task(function* () {
add_task(function*() {
// NOTE: the CORS call makes the test run times inconsistent
requestLongerTimeout(2);
const dbg = yield initDebugger("doc-sourcemap-bogus.html");
const { selectors: { getSources }, getState } = dbg;

View File

@ -4,7 +4,10 @@
// Tests loading sourcemapped sources, setting breakpoints, and
// stepping in them.
add_task(function* () {
add_task(function*() {
// NOTE: the CORS call makes the test run times inconsistent
requestLongerTimeout(2);
const dbg = yield initDebugger("doc-sourcemaps.html");
const { selectors: { getBreakpoint, getBreakpoints }, getState } = dbg;
@ -13,21 +16,27 @@ add_task(function* () {
const entrySrc = findSource(dbg, "entry.js");
yield selectSource(dbg, entrySrc);
ok(dbg.win.cm.getValue().includes("window.keepMeAlive"),
"Original source text loaded correctly");
ok(
dbg.win.cm.getValue().includes("window.keepMeAlive"),
"Original source text loaded correctly"
);
// Test that breakpoint sliding is not attempted. The breakpoint
// should not move anywhere.
yield addBreakpoint(dbg, entrySrc, 13);
is(getBreakpoints(getState()).size, 1, "One breakpoint exists");
ok(getBreakpoint(getState(), { sourceId: entrySrc.id, line: 13 }),
"Breakpoint has correct line");
ok(
getBreakpoint(getState(), { sourceId: entrySrc.id, line: 13 }),
"Breakpoint has correct line"
);
// Test breaking on a breakpoint
yield addBreakpoint(dbg, "entry.js", 15);
is(getBreakpoints(getState()).size, 2, "Two breakpoints exist");
ok(getBreakpoint(getState(), { sourceId: entrySrc.id, line: 15 }),
"Breakpoint has correct line");
ok(
getBreakpoint(getState(), { sourceId: entrySrc.id, line: 15 }),
"Breakpoint has correct line"
);
invokeInTab("keepMeAlive");
yield waitForPaused(dbg);

View File

@ -6,7 +6,10 @@
// This source map does not have source contents, so it's fetched separately
add_task(function* () {
add_task(function*() {
// NOTE: the CORS call makes the test run times inconsistent
requestLongerTimeout(2);
const dbg = yield initDebugger("doc-sourcemaps2.html");
const { selectors: { getBreakpoint, getBreakpoints }, getState } = dbg;
@ -20,8 +23,10 @@ add_task(function* () {
// Test that breakpoint is not off by a line.
yield addBreakpoint(dbg, mainSrc, 4);
is(getBreakpoints(getState()).size, 1, "One breakpoint exists");
ok(getBreakpoint(getState(), { sourceId: mainSrc.id, line: 4 }),
"Breakpoint has correct line");
ok(
getBreakpoint(getState(), { sourceId: mainSrc.id, line: 4 }),
"Breakpoint has correct line"
);
invokeInTab("logMessage");

View File

@ -6,6 +6,7 @@
<body>
<script>
debugger;
// This inline script allows this HTML page to show up as a
// source. It also needs to introduce a new global variable so
// it's not immediately garbage collected.

View File

@ -33,13 +33,14 @@
*/
// shared-head.js handles imports, constants, and utility functions
Services.scriptloader.loadSubScript("chrome://mochitests/content/browser/devtools/client/framework/test/shared-head.js", this);
Services.scriptloader.loadSubScript(
"chrome://mochitests/content/browser/devtools/client/framework/test/shared-head.js",
this
);
var { Toolbox } = require("devtools/client/framework/toolbox");
const EXAMPLE_URL = "http://example.com/browser/devtools/client/debugger/new/test/mochitest/examples/";
Services.prefs.setBoolPref("devtools.debugger.new-debugger-frontend", true);
Services.prefs.clearUserPref("devtools.debugger.tabs")
Services.prefs.clearUserPref("devtools.debugger.pending-selected-location")
registerCleanupFunction(() => {
Services.prefs.clearUserPref("devtools.debugger.new-debugger-frontend");
@ -76,9 +77,9 @@ function _afterDispatchDone(store, type) {
type: "@@service/waitUntil",
predicate: action => {
if (action.type === type) {
return action.status ?
(action.status === "done" || action.status === "error") :
true;
return action.status
? action.status === "done" || action.status === "error"
: true;
}
},
run: (dispatch, getState, action) => {
@ -102,7 +103,7 @@ function _afterDispatchDone(store, type) {
function waitForDispatch(dbg, type, eventRepeat = 1) {
let count = 0;
return Task.spawn(function* () {
return Task.spawn(function*() {
info("Waiting for " + type + " to dispatch " + eventRepeat + " time(s)");
while (count < eventRepeat) {
yield _afterDispatchDone(dbg.store, type);
@ -170,21 +171,23 @@ function waitForSources(dbg, ...sources) {
info("Waiting on sources: " + sources.join(", "));
const { selectors: { getSources }, store } = dbg;
return Promise.all(sources.map(url => {
function sourceExists(state) {
return getSources(state).some(s => {
return s.get("url").includes(url);
});
}
return Promise.all(
sources.map(url => {
function sourceExists(state) {
return getSources(state).some(s => {
return s.get("url").includes(url);
});
}
if (!sourceExists(store.getState())) {
return waitForState(dbg, sourceExists);
}
}));
if (!sourceExists(store.getState())) {
return waitForState(dbg, sourceExists);
}
})
);
}
function waitForElement(dbg, selector) {
return waitUntil(() => findElementWithSelector(dbg, selector))
return waitUntil(() => findElementWithSelector(dbg, selector));
}
/**
@ -209,8 +212,10 @@ function assertPausedLocation(dbg, source, line) {
is(location.get("line"), line);
// Check the debug line
ok(dbg.win.cm.lineInfo(line - 1).wrapClass.includes("debug-line"),
"Line is highlighted as paused");
ok(
dbg.win.cm.lineInfo(line - 1).wrapClass.includes("debug-line"),
"Line is highlighted as paused"
);
}
/**
@ -232,10 +237,14 @@ function assertHighlightLocation(dbg, source, line) {
// Check the highlight line
const lineEl = findElement(dbg, "highlightLine");
ok(lineEl, "Line is highlighted");
// ok(isVisibleWithin(findElement(dbg, "codeMirror"), lineEl),
// "Highlighted line is visible");
ok(dbg.win.cm.lineInfo(line - 1).wrapClass.includes("highlight-line"),
"Line is highlighted");
ok(
isVisibleWithin(findElement(dbg, "codeMirror"), lineEl),
"Highlighted line is visible"
);
ok(
dbg.win.cm.lineInfo(line - 1).wrapClass.includes("highlight-line"),
"Line is highlighted"
);
}
/**
@ -258,12 +267,11 @@ function isPaused(dbg) {
* @static
*/
function waitForPaused(dbg) {
return Task.spawn(function* () {
return Task.spawn(function*() {
// We want to make sure that we get both a real paused event and
// that the state is fully populated. The client may do some more
// work (call other client methods) before populating the state.
yield waitForThreadEvents(dbg, "paused"),
yield waitForState(dbg, state => {
yield waitForThreadEvents(dbg, "paused"), yield waitForState(dbg, state => {
const pause = dbg.selectors.getPause(state);
// Make sure we have the paused state.
if (!pause) {
@ -279,15 +287,16 @@ function waitForPaused(dbg) {
}
function createDebuggerContext(toolbox) {
const win = toolbox.getPanel("jsdebugger").panelWin;
const store = win.Debugger.store;
const panel = toolbox.getPanel("jsdebugger");
const win = panel.panelWin;
const { store, client, selectors, actions } = panel.getVarsForTests();
return {
actions: win.Debugger.actions,
selectors: win.Debugger.selectors,
actions: actions,
selectors: selectors,
getState: store.getState,
store: store,
client: win.Debugger.client,
client: client,
toolbox: toolbox,
win: win
};
@ -303,9 +312,13 @@ function createDebuggerContext(toolbox) {
* @static
*/
function initDebugger(url, ...sources) {
return Task.spawn(function* () {
Services.prefs.clearUserPref("devtools.debugger.tabs")
Services.prefs.clearUserPref("devtools.debugger.pending-selected-location")
return Task.spawn(function*() {
Services.prefs.clearUserPref("devtools.debugger.pause-on-exceptions");
Services.prefs.clearUserPref("devtools.debugger.ignore-caught-exceptions");
Services.prefs.clearUserPref("devtools.debugger.tabs");
Services.prefs.clearUserPref("devtools.debugger.pending-selected-location");
Services.prefs.clearUserPref("devtools.debugger.pending-breakpoints");
Services.prefs.clearUserPref("devtools.debugger.expressions");
const toolbox = yield openNewTabAndToolbox(EXAMPLE_URL + url, "jsdebugger");
return createDebuggerContext(toolbox);
});
@ -429,6 +442,11 @@ function resume(dbg) {
return waitForThreadEvents(dbg, "resumed");
}
function deleteExpression(dbg, input) {
info("Resuming");
return dbg.actions.deleteExpression({ input });
}
/**
* Reloads the debuggee.
*
@ -500,8 +518,11 @@ function removeBreakpoint(dbg, sourceId, line, col) {
* @return {Promise}
* @static
*/
function togglePauseOnExceptions(dbg,
pauseOnExceptions, ignoreCaughtExceptions) {
function togglePauseOnExceptions(
dbg,
pauseOnExceptions,
ignoreCaughtExceptions
) {
const command = dbg.actions.pauseOnExceptions(
pauseOnExceptions,
ignoreCaughtExceptions
@ -526,7 +547,7 @@ function togglePauseOnExceptions(dbg,
*/
function invokeInTab(fnc) {
info(`Invoking function ${fnc} in tab`);
return ContentTask.spawn(gBrowser.selectedBrowser, fnc, function* (fnc) {
return ContentTask.spawn(gBrowser.selectedBrowser, fnc, function*(fnc) {
content.wrappedJSObject[fnc](); // eslint-disable-line mozilla/no-cpows-in-tests, max-len
});
}
@ -534,18 +555,21 @@ function invokeInTab(fnc) {
const isLinux = Services.appinfo.OS === "Linux";
const cmdOrCtrl = isLinux ? { ctrlKey: true } : { metaKey: true };
const keyMappings = {
sourceSearch: { code: "p", modifiers: cmdOrCtrl},
fileSearch: { code: "f", modifiers: cmdOrCtrl},
"Enter": { code: "VK_RETURN" },
"Up": { code: "VK_UP" },
"Down": { code: "VK_DOWN" },
"Tab": { code: "VK_TAB" },
"Escape": { code: "VK_ESCAPE" },
sourceSearch: { code: "p", modifiers: cmdOrCtrl },
fileSearch: { code: "f", modifiers: cmdOrCtrl },
Enter: { code: "VK_RETURN" },
Up: { code: "VK_UP" },
Down: { code: "VK_DOWN" },
Tab: { code: "VK_TAB" },
Escape: { code: "VK_ESCAPE" },
pauseKey: { code: "VK_F8" },
resumeKey: { code: "VK_F8" },
stepOverKey: { code: "VK_F10" },
stepInKey: { code: "VK_F11", modifiers: { ctrlKey: isLinux }},
stepOutKey: { code: "VK_F11", modifiers: { ctrlKey: isLinux, shiftKey: true }}
stepInKey: { code: "VK_F11", modifiers: { ctrlKey: isLinux } },
stepOutKey: {
code: "VK_F11",
modifiers: { ctrlKey: isLinux, shiftKey: true }
}
};
/**
@ -561,11 +585,7 @@ function pressKey(dbg, keyName) {
let keyEvent = keyMappings[keyName];
const { code, modifiers } = keyEvent;
return EventUtils.synthesizeKey(
code,
modifiers || {},
dbg.win
);
return EventUtils.synthesizeKey(code, modifiers || {}, dbg.win);
}
function type(dbg, string) {
@ -577,14 +597,19 @@ function type(dbg, string) {
function isVisibleWithin(outerEl, innerEl) {
const innerRect = innerEl.getBoundingClientRect();
const outerRect = outerEl.getBoundingClientRect();
return innerRect.top > outerRect.top &&
innerRect.bottom < outerRect.bottom;
return innerRect.top > outerRect.top && innerRect.bottom < outerRect.bottom;
}
const selectors = {
callStackHeader: ".call-stack-pane ._header",
callStackBody: ".call-stack-pane .pane",
expressionNode: i =>
`.expressions-list .tree-node:nth-child(${i}) .object-label`,
expressionValue: i =>
`.expressions-list .tree-node:nth-child(${i}) .object-value`,
expressionClose: i =>
`.expressions-list .expression-container:nth-child(${i}) .close`,
expressionNodes: ".expressions-list .tree-node",
scopesHeader: ".scopes-pane ._header",
breakpointItem: i => `.breakpoints-list .breakpoint:nth-child(${i})`,
scopeNode: i => `.scopes-list .tree-node:nth-child(${i}) .object-label`,
@ -605,7 +630,7 @@ const selectors = {
sourceFooter: ".source-footer",
sourceNode: i => `.sources-list .tree-node:nth-child(${i})`,
sourceNodes: ".sources-list .tree-node",
sourceArrow: i => `.sources-list .tree-node:nth-child(${i}) .arrow`,
sourceArrow: i => `.sources-list .tree-node:nth-child(${i}) .arrow`
};
function getSelector(elementName, ...args) {
@ -647,6 +672,9 @@ function findAllElements(dbg, elementName, ...args) {
*/
function clickElement(dbg, elementName, ...args) {
const selector = getSelector(elementName, ...args);
const el = findElement(dbg, elementName, ...args);
el.scrollIntoView();
return EventUtils.synthesizeMouseAtCenter(
findElementWithSelector(dbg, selector),
{},
@ -654,12 +682,22 @@ function clickElement(dbg, elementName, ...args) {
);
}
function dblClickElement(dbg, elementName, ...args) {
const selector = getSelector(elementName, ...args);
return EventUtils.synthesizeMouseAtCenter(
findElementWithSelector(dbg, selector),
{ clickCount: 2 },
dbg.win
);
}
function rightClickElement(dbg, elementName, ...args) {
const selector = getSelector(elementName, ...args);
const doc = dbg.win.document;
return EventUtils.synthesizeMouseAtCenter(
doc.querySelector(selector),
{type: "contextmenu"},
{ type: "contextmenu" },
dbg.win
);
}
@ -669,10 +707,10 @@ function selectMenuItem(dbg, index) {
const doc = dbg.toolbox.win.document;
// there are several context menus, we want the one with the menu-api
const popup = doc.querySelector("menupopup[menu-api=\"true\"]");
const popup = doc.querySelector('menupopup[menu-api="true"]');
const item = popup.querySelector(`menuitem:nth-child(${index})`);
return EventUtils.synthesizeMouseAtCenter(item, {}, dbg.toolbox.win );
return EventUtils.synthesizeMouseAtCenter(item, {}, dbg.toolbox.win);
}
/**

View File

@ -584,6 +584,8 @@ function loadTelemetryAndRecordLogs() {
this.telemetryInfo[histogramId].push(value);
}
};
Telemetry.prototype._oldlogScalar = Telemetry.prototype.logScalar;
Telemetry.prototype.logScalar = Telemetry.prototype.log;
Telemetry.prototype._oldlogKeyed = Telemetry.prototype.logKeyed;
Telemetry.prototype.logKeyed = function (histogramId, key, value) {
this.log(`${histogramId}|${key}`, value);
@ -600,8 +602,10 @@ function loadTelemetryAndRecordLogs() {
function stopRecordingTelemetryLogs(Telemetry) {
info("Stopping Telemetry");
Telemetry.prototype.log = Telemetry.prototype._oldlog;
Telemetry.prototype.logScalar = Telemetry.prototype._oldlogScalar;
Telemetry.prototype.logKeyed = Telemetry.prototype._oldlogKeyed;
delete Telemetry.prototype._oldlog;
delete Telemetry.prototype._oldlogScalar;
delete Telemetry.prototype._oldlogKeyed;
delete Telemetry.prototype.telemetryInfo;
}

View File

@ -6,6 +6,8 @@ http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that the various copy items in the context menu works correctly.
const TEST_URL = URL_ROOT + "doc_inspector_menu.html";
const SELECTOR_UNIQUE = "devtools.copy.unique.css.selector.opened";
const SELECTOR_FULL = "devtools.copy.full.css.selector.opened";
const COPY_ITEMS_TEST_DATA = [
{
desc: "copy inner html",
@ -26,7 +28,7 @@ const COPY_ITEMS_TEST_DATA = [
text: "body > div:nth-child(1) > p:nth-child(2)",
},
{
desc: "copy css path",
desc: "copy CSS path",
id: "node-menu-copycsspath",
selector: "[data-id=\"copy\"]",
text: "html body div p",
@ -41,7 +43,9 @@ const COPY_ITEMS_TEST_DATA = [
];
add_task(function* () {
let Telemetry = loadTelemetryAndRecordLogs();
let { inspector } = yield openInspectorForURL(TEST_URL);
for (let {desc, id, selector, text} of COPY_ITEMS_TEST_DATA) {
info("Testing " + desc);
yield selectNode(selector, inspector);
@ -52,4 +56,32 @@ add_task(function* () {
yield waitForClipboardPromise(() => item.click(), text);
}
checkTelemetryResults(Telemetry);
stopRecordingTelemetryLogs(Telemetry);
});
function checkTelemetryResults(Telemetry) {
let data = Telemetry.prototype.telemetryInfo;
let results = new Map();
for (let key in data) {
if (key.toLowerCase() === key) {
let pings = data[key].length;
results.set(key, pings);
}
}
is(results.size, 2, "The correct number of scalars were logged");
let pings = checkPings(SELECTOR_UNIQUE, results);
is(pings, 1, `${SELECTOR_UNIQUE} has just 1 ping`);
pings = checkPings(SELECTOR_FULL, results);
is(pings, 1, `${SELECTOR_FULL} has just 1 ping`);
}
function checkPings(scalarId, results) {
return results.get(scalarId);
}

View File

@ -128,14 +128,14 @@ multiProcessWarningTitle = Service Worker debugging is not compatible with multi
# LOCALIZATION NOTE (multiProcessWarningMessage):
# This string is displayed in the warning section for multi-e10s in
# about:debugging#workers
multiProcessWarningMessage = The preference “dom.ipc.processCount” can be set to 1 to force a single content process.
multiProcessWarningMessage2 = The preference “dom.ipc.multiOptOut” can be modified to force a single content process for the current version.
# LOCALIZATION NOTE (multiProcessWarningLink):
# This string is the text content of a link in the warning section for multi-e10s in
# about:debugging#workers. The link updates the pref and restarts the browser.
multiProcessWarningUpdateLink = Set dom.ipc.processCount to 1
multiProcessWarningUpdateLink2 = Opt out of multiple content processes
# LOCALIZATION NOTE (multiProcessWarningConfirmUpdate):
# This string is displayed as a confirmation message when the user clicks on
# the multiProcessWarningUpdateLink in about:debugging#workers
multiProcessWarningConfirmUpdate = Set “dom.ipc.processCount” to 1 and restart the browser?
multiProcessWarningConfirmUpdate2 = Opt out of multiple processes?

View File

@ -115,15 +115,19 @@ timeEvents=Time
touchEvents=Touch
otherEvents=Other
# LOCALIZATION NOTE (blackBoxCheckboxTooltip): The tooltip text to display when
# the user hovers over the checkbox used to toggle black boxing its associated
# LOCALIZATION NOTE (blackboxCheckboxTooltip2): The tooltip text to display when
# the user hovers over the checkbox used to toggle blackboxing its associated
# source.
blackBoxCheckboxTooltip=Toggle black boxing
blackboxCheckboxTooltip2=Toggle blackboxing
# LOCALIZATION NOTE (sources.search.key): Key shortcut to open the search for
# searching all the source files the debugger has seen.
sources.search.key=P
# LOCALIZATION NOTE (sources.noSourcesAvailable): Text shown when the debugger
# does not have any sources.
sources.noSourcesAvailable=This page has no sources
# LOCALIZATION NOTE (sources.searchAlt.key): Alternate key shortcut to open
# the search for searching all the source files the debugger has seen.
sources.searchAlt.key=O
@ -235,10 +239,17 @@ callStack.expand=Expand Rows
# for the summarizing the selected search result. e.g. 5 of 10 results.
editor.searchResults=%d of %d results
# LOCALIZATION NOTE (sourceSearch.singleResult): Copy shown when there is one result.
editor.singleResult=1 result
# LOCALIZATION NOTE (editor.noResults): Editor Search bar message
# for when no results found.
editor.noResults=no results
# LOCALIZATION NOTE (editor.searchTypeToggleTitle): Search bar title for
# toggling search type buttons(function search, variable search)
editor.searchTypeToggleTitle=Search for:
# LOCALIZATION NOTE (editor.addBreakpoint): Editor gutter context menu item
# for adding a breakpoint on a line.
editor.addBreakpoint=Add Breakpoint
@ -341,6 +352,22 @@ sourceTabs.prettyPrint=Pretty Print Source
# the editor context menu.
sourceTabs.prettyPrint.accesskey=p
# LOCALIZATION NOTE (sourceFooter.blackbox): Tooltip text associated
# with the blackbox button
sourceFooter.blackbox=Blackbox Source
# LOCALIZATION NOTE (sourceFooter.unblackbox): Tooltip text associated
# with the blackbox button
sourceFooter.unblackbox=Unblackbox Source
# LOCALIZATION NOTE (sourceFooter.blackbox.accesskey): Access key to blackbox
# an associated source
sourceFooter.blackbox.accesskey=b
# LOCALIZATION NOTE (sourceFooter.blackboxed): Text associated
# with a blackboxed source
sourceFooter.blackboxed=Blackboxed Source
# LOCALIZATION NOTE (sourceTabs.closeTabButtonTooltip): The tooltip that is displayed
# for close tab button in source tabs.
sourceTabs.closeTabButtonTooltip=Close tab
@ -393,10 +420,6 @@ sourceSearch.search=Search Sources…
# message when the query did not match any of the sources.
sourceSearch.noResults=No files matching %S found
# LOCALIZATION NOTE (sourceFooter.debugBtnTooltip): Tooltip text associated
# with the pretty-print button
sourceFooter.debugBtnTooltip=Prettify Source
# LOCALIZATION NOTE (ignoreExceptions): The pause on exceptions button tooltip
# when the debugger will not pause on exceptions.
ignoreExceptions=Ignore exceptions. Click to pause on uncaught exceptions
@ -508,8 +531,30 @@ watchExpressionsSeparatorLabel2=\u0020→
# in the functions search panel as a separator between function's inferred name
# and its real name (if available).
functionSearchSeparatorLabel=
functionSearch.search.placeholder=Search Functions…
functionSearch.search.key=O
# LOCALIZATION NOTE(symbolSearch.search.functionsPlaceholder): The placeholder
# text displayed when the user searches for functions in a file
symbolSearch.search.functionsPlaceholder=Search functions…
# LOCALIZATION NOTE(symbolSearch.search.variablesPlaceholder): The placeholder
# text displayed when the user searches for variables in a file
symbolSearch.search.variablesPlaceholder=Search variables…
# LOCALIZATION NOTE(symbolSearch.search.key): The shortcut (cmd+shift+o) for
# searching for a function or variable
symbolSearch.search.key=O
# LOCALIZATION NOTE(symbolSearch.searchModifier.regex): A search option
# when searching text in a file
symbolSearch.searchModifier.regex=Regex
# LOCALIZATION NOTE(symbolSearch.searchModifier.caseSensitive): A search option
# when searching text in a file
symbolSearch.searchModifier.caseSensitive=Case sensitive
# LOCALIZATION NOTE(symbolSearch.searchModifier.wholeWord): A search option
# when searching text in a file
symbolSearch.searchModifier.wholeWord=Whole word
# LOCALIZATION NOTE (resumptionOrderPanelTitle): This is the text that appears
# as a description in the notification panel popup, when multiple debuggers are
@ -577,3 +622,7 @@ whyPaused.debugCommand=Paused on debugged function
# in a info block explaining how the debugger is currently paused on an event
# listener breakpoint set
whyPaused.other=Debugger paused
# LOCALIZATION NOTE (ctrl): The text that is used for documenting
# keyboard shortcuts that use the control key
ctrl=Ctrl

View File

@ -11,7 +11,6 @@
# A good criteria is the language in which you'd find the best
# documentation on web development on the web.
# LOCALIZATION NOTE (responsiveUI.rotate2): tooltip of the rotate button.
responsiveUI.rotate2=Rotate
@ -67,3 +66,13 @@ responsiveUI.notificationReload=Reload
responsiveUI.notificationReload_accesskey=R
responsiveUI.dontShowReloadNotification=Never show again
responsiveUI.dontShowReloadNotification_accesskey=N
# LOCALIZATION NOTE (responsiveUI.newVersionUserDisabled): notification that appears
# when old RDM is displayed because the user has disabled new RDM.
responsiveUI.newVersionUserDisabled=A new version of Responsive Design Mode is available, but it appears to be disabled. Please enable it and provide feedback, as this version will be removed.
# LOCALIZATION NOTE (responsiveUI.newVersionE10sDisabled): notification that appears
# when old RDM is displayed because e10s is disabled.
responsiveUI.newVersionE10sDisabled=A new version of Responsive Design Mode is available, but it requires multi-process mode, which is currently disabled. Please enable it and provide feedback, as this version will be removed.
# LOCALIZATION NOTE (responsiveUI.newVersionEnableAndRestart): button text in notification
# to enable new RDM itself or e10s as a prerequisite for new RDM.
responsiveUI.newVersionEnableAndRestart=Enable and Restart

View File

@ -1,7 +1,5 @@
# -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
# This Source Code Form is subject to the terms of the Mozilla Public
# 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/.
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
#ifdef RELEASE_OR_BETA
pref("devtools.debugger.new-debugger-frontend", false);
@ -17,7 +15,7 @@ pref("devtools.debugger.chrome-debugging-websocket", false);
pref("devtools.debugger.remote-host", "localhost");
pref("devtools.debugger.remote-timeout", 20000);
pref("devtools.debugger.pause-on-exceptions", false);
pref("devtools.debugger.ignore-caught-exceptions", true);
pref("devtools.debugger.ignore-caught-exceptions", false);
pref("devtools.debugger.source-maps-enabled", true);
pref("devtools.debugger.client-source-maps-enabled", true);
pref("devtools.debugger.pretty-print-enabled", true);
@ -38,4 +36,5 @@ pref("devtools.debugger.start-panel-collapsed", false);
pref("devtools.debugger.end-panel-collapsed", false);
pref("devtools.debugger.tabs", "[]");
pref("devtools.debugger.pending-selected-location", "{}");
pref("devtools.debugger.pending-breakpoints", "[]");
pref("devtools.debugger.expressions", "[]");

View File

@ -14,6 +14,8 @@ const EventEmitter = require("devtools/shared/event-emitter");
loader.lazyImporter(this, "SystemAppProxy",
"resource://gre/modules/SystemAppProxy.jsm");
loader.lazyImporter(this, "BrowserUtils",
"resource://gre/modules/BrowserUtils.jsm");
loader.lazyRequireGetter(this, "Telemetry", "devtools/client/shared/telemetry");
loader.lazyRequireGetter(this, "showDoorhanger",
"devtools/client/shared/doorhanger", true);
@ -27,9 +29,12 @@ loader.lazyRequireGetter(this, "DebuggerClient",
"devtools/shared/client/main", true);
loader.lazyRequireGetter(this, "DebuggerServer",
"devtools/server/main", true);
loader.lazyRequireGetter(this, "system", "devtools/shared/system");
this.EXPORTED_SYMBOLS = ["ResponsiveUIManager"];
const NEW_RDM_ENABLED = "devtools.responsive.html.enabled";
const MIN_WIDTH = 50;
const MIN_HEIGHT = 50;
@ -136,7 +141,7 @@ EventEmitter.decorate(Manager);
// the new HTML RDM UI to function), delegate the ResponsiveUIManager API over to that
// tool instead. Performing this delegation here allows us to contain the pref check to a
// single place.
if (Services.prefs.getBoolPref("devtools.responsive.html.enabled") &&
if (Services.prefs.getBoolPref(NEW_RDM_ENABLED) &&
Services.appinfo.browserTabsRemoteAutostart) {
let { ResponsiveUIManager } =
require("devtools/client/responsive.html/manager");
@ -266,6 +271,8 @@ ResponsiveUI.prototype = {
anchor: this.chromeDoc.querySelector("#content")
});
this.showNewUINotification();
// Notify that responsive mode is on.
this._telemetry.toolOpened("responsive");
ResponsiveUIManager.emit("on", { tab: this.tab });
@ -399,12 +406,14 @@ ResponsiveUI.prototype = {
this._telemetry.toolClosed("responsive");
if (this.tab.linkedBrowser.messageManager) {
if (this.tab.linkedBrowser && this.tab.linkedBrowser.messageManager) {
let stopped = this.waitForMessage("ResponsiveMode:Stop:Done");
this.tab.linkedBrowser.messageManager.sendAsyncMessage("ResponsiveMode:Stop");
yield stopped;
}
this.hideNewUINotification();
this.inited = null;
ResponsiveUIManager.emit("off", { tab: this.tab });
}),
@ -683,6 +692,69 @@ ResponsiveUI.prototype = {
this.container.appendChild(bottomToolbar);
},
showNewUINotification() {
let nbox = this.mainWindow.gBrowser.getNotificationBox(this.browser);
// One reason we might be using old RDM is that the user explcitly disabled new RDM.
// We should encourage them to use the new one, since the old one will be removed.
if (Services.prefs.prefHasUserValue(NEW_RDM_ENABLED) &&
!Services.prefs.getBoolPref(NEW_RDM_ENABLED)) {
let buttons = [{
label: this.strings.GetStringFromName("responsiveUI.newVersionEnableAndRestart"),
callback: () => {
Services.prefs.setBoolPref(NEW_RDM_ENABLED, true);
BrowserUtils.restartApplication();
},
}];
nbox.appendNotification(
this.strings.GetStringFromName("responsiveUI.newVersionUserDisabled"),
"responsive-ui-new-version-user-disabled",
null,
nbox.PRIORITY_INFO_LOW,
buttons
);
return;
}
// Only show a notification about the new RDM UI on channels where there is an e10s
// switch in the preferences UI (Dev. Ed, Nightly). On other channels, it is less
// clear how a user would proceed here, so don't show a message.
if (!system.constants.E10S_TESTING_ONLY) {
return;
}
let buttons = [{
label: this.strings.GetStringFromName("responsiveUI.newVersionEnableAndRestart"),
callback: () => {
Services.prefs.setBoolPref("browser.tabs.remote.autostart", true);
Services.prefs.setBoolPref("browser.tabs.remote.autostart.2", true);
BrowserUtils.restartApplication();
},
}];
nbox.appendNotification(
this.strings.GetStringFromName("responsiveUI.newVersionE10sDisabled"),
"responsive-ui-new-version-e10s-disabled",
null,
nbox.PRIORITY_INFO_LOW,
buttons
);
},
hideNewUINotification() {
if (!this.mainWindow.gBrowser || !this.mainWindow.gBrowser.getNotificationBox) {
return;
}
let nbox = this.mainWindow.gBrowser.getNotificationBox(this.browser);
let n = nbox.getNotificationWithValue("responsive-ui-new-version-user-disabled");
if (n) {
n.close();
}
n = nbox.getNotificationWithValue("responsive-ui-new-version-e10s-disabled");
if (n) {
n.close();
}
},
/**
* Validate and apply any user input on the editable menulist
*/

File diff suppressed because it is too large Load Diff

View File

@ -69,7 +69,3 @@ function testRepRenderModes(modeTests, testName, componentUnderTest, gripStub,
is(rendered.textContent, expectedOutput, message);
});
}
function getStubAttachedActorIds(gripStubs) {
return gripStubs.map(gripStub => gripStub.actor);
}

View File

@ -20,8 +20,12 @@ Test ArrayRep rep
/* import-globals-from head.js */
window.onload = Task.async(function* () {
const { REPS, MODE } = browserRequire("devtools/client/shared/components/reps/reps");
let { Rep, ArrayRep } = REPS;
const {
REPS,
MODE,
getRep,
} = browserRequire("devtools/client/shared/components/reps/reps");
let { ArrayRep } = REPS;
let componentUnderTest = ArrayRep;
const maxLength = {
@ -52,9 +56,7 @@ window.onload = Task.async(function* () {
function testBasic() {
// Test that correct rep is chosen
const stub = [];
const renderedRep = shallowRenderComponent(Rep, { object: stub });
is(renderedRep.type, ArrayRep.rep,
`Rep correctly selects ${ArrayRep.rep.displayName}`);
is(getRep(stub), ArrayRep.rep, "Rep correctly selects Array Rep");
// Test rendering

View File

@ -17,8 +17,11 @@ Test Attribute rep
<script src="head.js" type="application/javascript"></script>
<script type="application/javascript">
window.onload = Task.async(function* () {
const { REPS } = browserRequire("devtools/client/shared/components/reps/reps");
let { Rep, Attribute } = REPS;
const {
REPS,
getRep,
} = browserRequire("devtools/client/shared/components/reps/reps");
let { Attribute } = REPS;
try {
testBasic();
@ -31,8 +34,7 @@ window.onload = Task.async(function* () {
function testBasic() {
// Test that correct rep is chosen
const renderedRep = shallowRenderComponent(Rep, { object: getStub() });
is(renderedRep.type, Attribute.rep, `Rep correctly selects ${Attribute.rep.displayName}`);
is(getRep(getStub()), Attribute.rep, "Rep correctly selects Attribute Rep");
// Test rendering
const renderedComponent = renderComponent(Attribute.rep, { object: getStub() });

View File

@ -20,8 +20,12 @@ Test comment-node rep
window.onload = Task.async(function* () {
try {
const { REPS, MODE } = browserRequire("devtools/client/shared/components/reps/reps");
let { Rep, CommentNode } = REPS;
const {
REPS,
MODE,
getRep,
} = browserRequire("devtools/client/shared/components/reps/reps");
let { CommentNode } = REPS;
let gripStub = {
"type": "object",
@ -40,9 +44,7 @@ window.onload = Task.async(function* () {
};
// Test that correct rep is chosen.
const renderedRep = shallowRenderComponent(Rep, { object: gripStub });
is(renderedRep.type, CommentNode.rep,
`Rep correctly selects ${CommentNode.rep.displayName}`);
is(getRep(gripStub), CommentNode.rep, "Rep correctly selects CommentNode Rep");
// Test rendering.
const renderedComponent = renderComponent(CommentNode.rep, { object: gripStub });

View File

@ -17,8 +17,11 @@ Test DateTime rep
<script src="head.js" type="application/javascript"></script>
<script type="application/javascript">
window.onload = Task.async(function* () {
const { REPS } = browserRequire("devtools/client/shared/components/reps/reps");
let { Rep, DateTime } = REPS;
const {
REPS,
getRep,
} = browserRequire("devtools/client/shared/components/reps/reps");
let { DateTime } = REPS;
try {
testValid();
@ -45,12 +48,11 @@ window.onload = Task.async(function* () {
};
// Test that correct rep is chosen
const renderedRep = shallowRenderComponent(Rep, { object: gripStub });
is(renderedRep.type, DateTime.rep, `Rep correctly selects ${DateTime.rep.displayName}`);
is(getRep(gripStub), DateTime.rep, "Rep correctly selects DateTime Rep");
// Test rendering
const renderedComponent = renderComponent(DateTime.rep, { object: gripStub });
is(renderedComponent.textContent, "2016-03-30T21:17:24.859Z", "DateTime rep has expected text content for valid date");
is(renderedComponent.textContent, "Date 2016-03-30T21:17:24.859Z", "DateTime rep has expected text content for valid date");
}
function testInvalid() {

View File

@ -17,8 +17,11 @@ Test Document rep
<script src="head.js" type="application/javascript"></script>
<script type="application/javascript">
window.onload = Task.async(function* () {
const { REPS } = browserRequire("devtools/client/shared/components/reps/reps");
let { Rep, Document } = REPS;
const {
REPS,
getRep,
} = browserRequire("devtools/client/shared/components/reps/reps");
let { Document } = REPS;
try {
testBasic();
@ -31,12 +34,11 @@ window.onload = Task.async(function* () {
function testBasic() {
// Test that correct rep is chosen
const renderedRep = shallowRenderComponent(Rep, { object: getStub() });
is(renderedRep.type, Document.rep, `Rep correctly selects ${Document.rep.displayName}`);
is(getRep(getStub()), Document.rep, "Rep correctly selects Document Rep");
// Test rendering
const renderedComponent = renderComponent(Document.rep, { object: getStub() });
is(renderedComponent.textContent, "https://www.mozilla.org/en-US/firefox/new/",
is(renderedComponent.textContent, "HTMLDocument https://www.mozilla.org/en-US/firefox/new/",
"Document rep has expected text content");
}

View File

@ -22,9 +22,10 @@ window.onload = Task.async(function* () {
const {
REPS,
MODE,
getRep,
getSelectableInInspectorGrips,
} = browserRequire("devtools/client/shared/components/reps/reps");
let { Rep, ElementNode } = REPS;
let { ElementNode } = REPS;
try {
yield testBodyNode();
@ -48,9 +49,8 @@ window.onload = Task.async(function* () {
function testBodyNode() {
const stub = getGripStub("testBodyNode");
const renderedRep = shallowRenderComponent(Rep, { object: stub });
is(renderedRep.type, ElementNode.rep,
`Rep correctly selects ${ElementNode.rep.displayName} for body node`);
is(getRep(stub), ElementNode.rep,
"Rep correctly selects ElementNode Rep for body node");
const renderedComponent = renderComponent(ElementNode.rep, { object: stub });
is(renderedComponent.textContent, `<body id="body-id" class="body-class">`,
@ -64,9 +64,8 @@ window.onload = Task.async(function* () {
function testDocumentElement() {
const stub = getGripStub("testDocumentElement");
const renderedRep = shallowRenderComponent(Rep, { object: stub });
is(renderedRep.type, ElementNode.rep,
`Rep correctly selects ${ElementNode.rep.displayName} for document element node`);
is(getRep(stub), ElementNode.rep,
"Rep correctly selects ElementNode Rep for document element node");
const renderedComponent = renderComponent(ElementNode.rep, { object: stub });
is(renderedComponent.textContent, `<html dir="ltr" lang="en-US">`,
@ -80,9 +79,8 @@ window.onload = Task.async(function* () {
function testNode() {
const stub = getGripStub("testNode");
const renderedRep = shallowRenderComponent(Rep, { object: stub });
is(renderedRep.type, ElementNode.rep,
`Rep correctly selects ${ElementNode.rep.displayName} for element node`);
is(getRep(stub), ElementNode.rep,
"Rep correctly selects ElementNode Rep for element node");
const renderedComponent = renderComponent(ElementNode.rep, { object: stub });
is(renderedComponent.textContent,
@ -99,9 +97,8 @@ window.onload = Task.async(function* () {
function testNodeWithLeadingAndTrailingSpacesClassName() {
const stub = getGripStub("testNodeWithLeadingAndTrailingSpacesClassName");
const renderedRep = shallowRenderComponent(Rep, { object: stub });
is(renderedRep.type, ElementNode.rep,
`Rep correctly selects ${ElementNode.rep.displayName} for element node`);
is(getRep(stub), ElementNode.rep,
"Rep correctly selects ElementNode Rep for element node");
const renderedComponent = renderComponent(ElementNode.rep, { object: stub });
is(renderedComponent.textContent,
@ -119,8 +116,7 @@ window.onload = Task.async(function* () {
function testNodeWithoutAttributes() {
const stub = getGripStub("testNodeWithoutAttributes");
const renderedComponent = renderComponent(ElementNode.rep, { object: stub });
is(renderedComponent.textContent, "<p>",
is(getRep(stub), ElementNode.rep,
"Element node rep has expected text content for element node without attributes");
const tinyRenderedComponent = renderComponent(
@ -147,8 +143,7 @@ window.onload = Task.async(function* () {
function testSvgNode() {
const stub = getGripStub("testSvgNode");
const renderedRep = shallowRenderComponent(Rep, { object: stub });
is(renderedRep.type, ElementNode.rep,
is(getRep(stub), ElementNode.rep,
`Rep correctly selects ${ElementNode.rep.displayName} for SVG element node`);
const renderedComponent = renderComponent(ElementNode.rep, { object: stub });
@ -165,8 +160,7 @@ window.onload = Task.async(function* () {
function testSvgNodeInXHTML() {
const stub = getGripStub("testSvgNodeInXHTML");
const renderedRep = shallowRenderComponent(Rep, { object: stub });
is(renderedRep.type, ElementNode.rep,
is(getRep(stub), ElementNode.rep,
`Rep correctly selects ${ElementNode.rep.displayName} for XHTML SVG element node`);
const renderedComponent = renderComponent(ElementNode.rep, { object: stub });
@ -182,12 +176,9 @@ window.onload = Task.async(function* () {
function testOnMouseOver() {
const stub = getGripStub("testNode");
debugger;
const grips = getSelectableInInspectorGrips(stub);
is(grips.length, 1, "the stub has one node grip");
const attachedActorIds = getStubAttachedActorIds(grips);
let mouseOverValue;
let onDOMNodeMouseOver = (object) => {
mouseOverValue = object;
@ -195,7 +186,6 @@ window.onload = Task.async(function* () {
const renderedComponent = renderComponent(ElementNode.rep, {
object: stub,
onDOMNodeMouseOver,
attachedActorIds,
});
TestUtils.Simulate.mouseOver(renderedComponent);
@ -209,8 +199,6 @@ window.onload = Task.async(function* () {
const grips = getSelectableInInspectorGrips(stub);
is(grips.length, 1, "the stub has one node grip");
const attachedActorIds = getStubAttachedActorIds(grips);
let called = false;
let onDOMNodeMouseOut = (object) => {
called = true;
@ -218,7 +206,6 @@ window.onload = Task.async(function* () {
const renderedComponent = renderComponent(ElementNode.rep, {
object: stub,
onDOMNodeMouseOut,
attachedActorIds,
});
TestUtils.Simulate.mouseOut(renderedComponent);
@ -231,8 +218,6 @@ window.onload = Task.async(function* () {
const grips = getSelectableInInspectorGrips(stub);
is(grips.length, 1, "the stub has one node grip");
const attachedActorIds = getStubAttachedActorIds(grips);
let inspectIconClickedValue = null;
let inspectIconClickedEvent = null;
@ -242,28 +227,18 @@ window.onload = Task.async(function* () {
};
const renderedComponentWithoutInspectIcon = renderComponent(ElementNode.rep, {
object: stub,
object: getGripStub("testDisconnectedNode"),
onInspectIconClick,
attachedActorIds: ["someOtherId"]
});
is(renderedComponentWithoutInspectIcon.querySelector(".open-inspector"), null,
"There isn't an inspect icon when actor is not in attachedActorIds");
"There isn't an inspect icon when the node is not in the DOM tree");
let renderedComponent = renderComponent(ElementNode.rep, {
const renderedComponent = renderComponent(ElementNode.rep, {
object: stub,
onInspectIconClick,
});
let inspectIconNode = renderedComponent.querySelector(".open-inspector");
ok(inspectIconNode !== null,
"There is an inspect icon when attachedActorIds is not specified");
renderedComponent = renderComponent(ElementNode.rep, {
object: stub,
onInspectIconClick,
attachedActorIds,
});
inspectIconNode = renderedComponent.querySelector(".open-inspector");
const inspectIconNode = renderedComponent.querySelector(".open-inspector");
ok(inspectIconNode !== null, "There is an inspect icon as expected");
TestUtils.Simulate.click(inspectIconNode);
@ -345,6 +320,32 @@ window.onload = Task.async(function* () {
"kind": "DOMNode",
"nodeType": 1,
"nodeName": "input",
"isConnected": true,
"attributes": {
"id": "newtab-customize-button",
"dir": "ltr",
"title": "Customize your New Tab page",
"class": "bar baz",
"value": "foo",
"type": "button"
},
"attributesLength": 6
}
};
case "testDisconnectedNode":
return {
"type": "object",
"actor": "server1.conn2.child1/obj116",
"class": "HTMLInputElement",
"extensible": true,
"frozen": false,
"sealed": false,
"ownPropertyLength": 0,
"preview": {
"kind": "DOMNode",
"nodeType": 1,
"nodeName": "input",
"isConnected": false,
"attributes": {
"id": "newtab-customize-button",
"dir": "ltr",

View File

@ -19,8 +19,12 @@ Test Error rep
"use strict";
window.onload = Task.async(function* () {
const { REPS, MODE } = browserRequire("devtools/client/shared/components/reps/reps");
let { Rep, ErrorRep } = REPS;
const {
REPS,
MODE,
getRep,
} = browserRequire("devtools/client/shared/components/reps/reps");
let { ErrorRep } = REPS;
try {
// Test errors with different properties
@ -47,9 +51,7 @@ window.onload = Task.async(function* () {
function testSimpleError() {
// Test object = `new Error("Error message")`
const stub = getGripStub("testSimpleError");
const renderedRep = shallowRenderComponent(Rep, {object: stub});
is(renderedRep.type, ErrorRep.rep,
`Rep correctly selects ${ErrorRep.rep.displayName} for Error object`);
is(getRep(stub), ErrorRep.rep, "Rep correctly selects Error Rep for Error object");
const renderedComponent = renderComponent(ErrorRep.rep, {object: stub});
is(renderedComponent.textContent,
@ -77,9 +79,8 @@ window.onload = Task.async(function* () {
* errorFoo();`
*/
const stub = getGripStub("testMultilineStackError");
const renderedRep = shallowRenderComponent(Rep, {object: stub});
is(renderedRep.type, ErrorRep.rep,
`Rep correctly selects ${ErrorRep.rep.displayName} for Error object`);
is(getRep(stub), ErrorRep.rep,
`Rep correctly selects Error Rep for Error object`);
const renderedComponent = renderComponent(ErrorRep.rep, {object: stub});
is(renderedComponent.textContent,
@ -99,9 +100,8 @@ window.onload = Task.async(function* () {
function testErrorWithoutStacktrace() {
const stub = getGripStub("testErrorWithoutStacktrace");
const renderedRep = shallowRenderComponent(Rep, {object: stub});
is(renderedRep.type, ErrorRep.rep,
`Rep correctly selects ${ErrorRep.rep.displayName} for Error object`);
is(getRep(stub), ErrorRep.rep,
`Rep correctly selects Error Rep for Error object`);
const renderedComponent = renderComponent(ErrorRep.rep, {object: stub});
is(renderedComponent.textContent,
@ -118,9 +118,8 @@ window.onload = Task.async(function* () {
function testEvalError() {
// Test object = `new EvalError("EvalError message")`
const stub = getGripStub("testEvalError");
const renderedRep = shallowRenderComponent(Rep, {object: stub});
is(renderedRep.type, ErrorRep.rep,
`Rep correctly selects ${ErrorRep.rep.displayName} for EvalError object`);
is(getRep(stub), ErrorRep.rep,
`Rep correctly selects Error Rep for EvalError object`);
const renderedComponent = renderComponent(ErrorRep.rep, {object: stub});
is(renderedComponent.textContent,
@ -139,9 +138,8 @@ window.onload = Task.async(function* () {
function testInternalError() {
// Test object = `new InternalError("InternalError message")`
const stub = getGripStub("testInternalError");
const renderedRep = shallowRenderComponent(Rep, {object: stub});
is(renderedRep.type, ErrorRep.rep,
`Rep correctly selects ${ErrorRep.rep.displayName} for InternalError object`);
is(getRep(stub), ErrorRep.rep,
`Rep correctly selects Error Rep for InternalError object`);
const renderedComponent = renderComponent(ErrorRep.rep, {object: stub});
is(renderedComponent.textContent,
@ -160,9 +158,8 @@ window.onload = Task.async(function* () {
function testRangeError() {
// Test object = `new RangeError("RangeError message")`
const stub = getGripStub("testRangeError");
const renderedRep = shallowRenderComponent(Rep, {object: stub});
is(renderedRep.type, ErrorRep.rep,
`Rep correctly selects ${ErrorRep.rep.displayName} for RangeError object`);
is(getRep(stub), ErrorRep.rep,
`Rep correctly selects Error Rep for RangeError object`);
const renderedComponent = renderComponent(ErrorRep.rep, {object: stub});
is(renderedComponent.textContent,
@ -181,9 +178,8 @@ window.onload = Task.async(function* () {
function testReferenceError() {
// Test object = `new ReferenceError("ReferenceError message"`
const stub = getGripStub("testReferenceError");
const renderedRep = shallowRenderComponent(Rep, {object: stub});
is(renderedRep.type, ErrorRep.rep,
`Rep correctly selects ${ErrorRep.rep.displayName} for ReferenceError object`);
is(getRep(stub), ErrorRep.rep,
`Rep correctly selects Error Rep for ReferenceError object`);
const renderedComponent = renderComponent(ErrorRep.rep, {object: stub});
is(renderedComponent.textContent,
@ -202,9 +198,8 @@ window.onload = Task.async(function* () {
function testSyntaxError() {
// Test object = `new SyntaxError("SyntaxError message"`
const stub = getGripStub("testSyntaxError");
const renderedRep = shallowRenderComponent(Rep, {object: stub});
is(renderedRep.type, ErrorRep.rep,
`Rep correctly selects ${ErrorRep.rep.displayName} for SyntaxError object`);
is(getRep(stub), ErrorRep.rep,
`Rep correctly selects Error Rep for SyntaxError object`);
const renderedComponent = renderComponent(ErrorRep.rep, {object: stub});
is(renderedComponent.textContent,
@ -223,9 +218,8 @@ window.onload = Task.async(function* () {
function testTypeError() {
// Test object = `new TypeError("TypeError message"`
const stub = getGripStub("testTypeError");
const renderedRep = shallowRenderComponent(Rep, {object: stub});
is(renderedRep.type, ErrorRep.rep,
`Rep correctly selects ${ErrorRep.rep.displayName} for TypeError`);
is(getRep(stub), ErrorRep.rep,
`Rep correctly selects Error Rep for TypeError`);
const renderedComponent = renderComponent(ErrorRep.rep, {object: stub});
is(renderedComponent.textContent,
@ -244,9 +238,8 @@ window.onload = Task.async(function* () {
function testURIError() {
// Test object = `new URIError("URIError message")`
const stub = getGripStub("testURIError");
const renderedRep = shallowRenderComponent(Rep, {object: stub});
is(renderedRep.type, ErrorRep.rep,
`Rep correctly selects ${ErrorRep.rep.displayName} for URIError object`);
is(getRep(stub), ErrorRep.rep,
`Rep correctly selects Error Rep for URIError object`);
const renderedComponent = renderComponent(ErrorRep.rep, {object: stub});
is(renderedComponent.textContent,

View File

@ -20,14 +20,14 @@ window.onload = Task.async(function* () {
const {
REPS,
MODE,
getRep,
getSelectableInInspectorGrips,
} = browserRequire("devtools/client/shared/components/reps/reps");
let { Rep, Event } = REPS;
let { Event } = REPS;
try {
// Test that correct rep is chosen
const renderedRep = shallowRenderComponent(Rep, { object: getGripStub("testEvent") });
is(renderedRep.type, Event.rep, `Rep correctly selects ${Event.rep.displayName}`);
is(getRep(getGripStub("testEvent")), Event.rep, "Rep correctly selects Event Rep");
yield testEvent();
yield testMouseEvent();
@ -129,8 +129,6 @@ window.onload = Task.async(function* () {
is(grips.length, 1, "the stub has one node grip");
const attachedActorIds = getStubAttachedActorIds(grips);
let mouseOverValue;
let onDOMNodeMouseOver = (object) => {
mouseOverValue = object;
@ -138,7 +136,6 @@ window.onload = Task.async(function* () {
const renderedComponent = renderComponent(Event.rep, {
object: stub,
onDOMNodeMouseOver,
attachedActorIds,
});
const node = renderedComponent.querySelector(".objectBox-node");
@ -153,8 +150,6 @@ window.onload = Task.async(function* () {
const grips = getSelectableInInspectorGrips(stub);
is(grips.length, 1, "the stub has one node grip");
const attachedActorIds = getStubAttachedActorIds(grips);
let called = false;
let onDOMNodeMouseOut = (object) => {
called = true;
@ -162,7 +157,6 @@ window.onload = Task.async(function* () {
const renderedComponent = renderComponent(Event.rep, {
object: stub,
onDOMNodeMouseOut,
attachedActorIds
});
const node = renderedComponent.querySelector(".objectBox-node");
@ -176,34 +170,19 @@ window.onload = Task.async(function* () {
const grips = getSelectableInInspectorGrips(stub);
is(grips.length, 1, "the stub has one node grip");
const attachedActorIds = getStubAttachedActorIds(grips);
let inspectIconClickedValue = null;
let onInspectIconClick = (object) => {
inspectIconClickedValue = object;
};
let renderedComponentWithoutInspectIcon = renderComponent(Event.rep, {
object: stub,
onInspectIconClick,
attachedActorIds: ["someOtherId"]
});
is(renderedComponentWithoutInspectIcon.querySelector(".open-inspector"), null,
"There isn't an inspect icon when the actor is not in attachedActorIds");
is(renderedComponentWithoutInspectIcon.querySelector(".open-inspector"), null,
"There isn't an inspect icon when attachedActorIds does not have keys " +
"matching grip event's target item");
const renderedComponent = renderComponent(Event.rep, {
object: stub,
onInspectIconClick,
attachedActorIds
});
const icon = renderedComponent.querySelector(".open-inspector");
ok(icon !== null, "There is an icon as expected when passing a matching " +
"attachedActorIds item");
ok(icon !== null,
"There is an inspect icon when the node is connected to the DOM tree");
TestUtils.Simulate.click(icon);
@ -344,6 +323,7 @@ window.onload = Task.async(function* () {
"kind": "DOMNode",
"nodeType": 1,
"nodeName": "div",
"isConnected": true,
"attributes": {
"id": "test"
},

View File

@ -18,8 +18,11 @@ Test fallback for rep rendering when a rep fails to render.
<script type="application/javascript">
window.onload = Task.async(function* () {
try {
const { REPS } = browserRequire("devtools/client/shared/components/reps/reps");
let { Rep, ArrayRep, RegExp } = REPS;
const {
REPS,
getRep,
} = browserRequire("devtools/client/shared/components/reps/reps");
let { ArrayRep, RegExp } = REPS;
// Force the RegExp rep to crash by creating RegExp grip that throws when accessing
// the displayString property
@ -37,8 +40,7 @@ window.onload = Task.async(function* () {
};
// Test that correct rep is chosen.
const renderedRep = shallowRenderComponent(Rep, { object: gripStub });
is(renderedRep.type, RegExp.rep, `Rep correctly selects ${RegExp.rep.displayName}`);
is(getRep(gripStub), RegExp.rep, "Rep correctly selects RegExp Rep");
// Test fallback message is displayed when rendering bad rep directly.
let renderedComponent = renderComponent(RegExp.rep, { object: gripStub });

View File

@ -17,16 +17,19 @@ Test Func rep
<script src="head.js" type="application/javascript"></script>
<script type="application/javascript">
window.onload = Task.async(function* () {
const { REPS, MODE } = browserRequire("devtools/client/shared/components/reps/reps");
let { Rep, Func } = REPS;
const {
REPS,
MODE,
getRep,
} = browserRequire("devtools/client/shared/components/reps/reps");
let { Func } = REPS;
const componentUnderTest = Func;
try {
// Test that correct rep is chosen
const gripStub = getGripStub("testNamed");
const renderedRep = shallowRenderComponent(Rep, { object: gripStub });
is(renderedRep.type, Func.rep, `Rep correctly selects ${Func.rep.displayName}`);
is(getRep(gripStub), Func.rep, "Rep correctly selects Func Rep");
yield testNamed();
yield testVarNamed();

View File

@ -20,9 +20,10 @@ window.onload = Task.async(function* () {
const {
REPS,
MODE,
getRep,
getSelectableInInspectorGrips,
} = browserRequire("devtools/client/shared/components/reps/reps");
let { Rep, GripArray } = REPS;
let { GripArray } = REPS;
let componentUnderTest = GripArray;
const maxLength = {
@ -60,8 +61,7 @@ window.onload = Task.async(function* () {
// Test that correct rep is chosen
const gripStub = getGripStub("testBasic");
const renderedRep = shallowRenderComponent(Rep, { object: gripStub });
is(renderedRep.type, GripArray.rep, `Rep correctly selects ${GripArray.rep.displayName}`);
is(getRep(gripStub), GripArray.rep, "Rep correctly selects GripArray Rep");
// Test rendering
const defaultOutput = `Array []`;
@ -328,8 +328,6 @@ window.onload = Task.async(function* () {
is(grips.length, 3, "the stub has three node grips");
const attachedActorIds = getStubAttachedActorIds(grips);
let mouseOverValue;
let onDOMNodeMouseOver = (object) => {
mouseOverValue = object;
@ -337,7 +335,6 @@ window.onload = Task.async(function* () {
const renderedComponent = renderComponent(GripArray.rep, {
object: stub,
onDOMNodeMouseOver,
attachedActorIds,
});
const nodes = renderedComponent.querySelectorAll(".objectBox-node");
@ -357,8 +354,6 @@ window.onload = Task.async(function* () {
is(grips.length, 3, "the stub has three node grips");
const attachedActorIds = getStubAttachedActorIds(grips);
let called = 0;
let onDOMNodeMouseOut = (object) => {
called++;
@ -366,7 +361,6 @@ window.onload = Task.async(function* () {
const renderedComponent = renderComponent(GripArray.rep, {
object: stub,
onDOMNodeMouseOut,
attachedActorIds,
});
const nodes = renderedComponent.querySelectorAll(".objectBox-node");
@ -377,35 +371,30 @@ window.onload = Task.async(function* () {
}
function testOnDomNodeInspectIconClick() {
const stub = getGripStub("testNodeList");
const grips = getSelectableInInspectorGrips(stub);
is(grips.length, 3, "the stub has three node grips");
const attachedActorIds = getStubAttachedActorIds(grips);
let inspectIconClickedValue = null;
let onInspectIconClick = (object) => {
inspectIconClickedValue = object;
};
let renderedComponentWithoutInspectIcon = renderComponent(GripArray.rep, {
object: stub,
object: getGripStub("testDisconnectedNodeList"),
onInspectIconClick,
attachedActorIds: ["someOtherId"],
});
is(renderedComponentWithoutInspectIcon.querySelector(".open-inspector"), null,
"There isn't an inspect icon when the actor is not in attachedActorIds");
"There isn't an inspect icon when the nodes are not connected to the DOM tree");
const stub = getGripStub("testNodeList");
const grips = getSelectableInInspectorGrips(stub);
is(grips.length, 3, "the stub has three node grips");
const renderedComponent = renderComponent(GripArray.rep, {
object: stub,
onInspectIconClick,
attachedActorIds,
});
const icons = renderedComponent.querySelectorAll(".open-inspector");
is(icons.length, grips.length,
"There is an icon for each grip array item with a matching attachedNodeFront");
"There is an icon for each node connected to the DOM tree");
icons.forEach((icon, index) => {
TestUtils.Simulate.click(icon);
@ -678,6 +667,7 @@ window.onload = Task.async(function* () {
"kind": "DOMNode",
"nodeType": 1,
"nodeName": "button",
"isConnected": true,
"attributes": {
"id": "btn-1",
"class": "btn btn-log",
@ -698,6 +688,7 @@ window.onload = Task.async(function* () {
"kind": "DOMNode",
"nodeType": 1,
"nodeName": "button",
"isConnected": true,
"attributes": {
"id": "btn-2",
"class": "btn btn-err",
@ -718,6 +709,87 @@ window.onload = Task.async(function* () {
"kind": "DOMNode",
"nodeType": 1,
"nodeName": "button",
"isConnected": true,
"attributes": {
"id": "btn-3",
"class": "btn btn-count",
"type": "button"
},
"attributesLength": 3
}
}
]
}
};
case "testDisconnectedNodeList":
return {
"type": "object",
"actor": "server1.conn1.child1/obj51",
"class": "NodeList",
"extensible": true,
"frozen": false,
"sealed": false,
"ownPropertyLength": 3,
"preview": {
"kind": "ArrayLike",
"length": 3,
"items": [
{
"type": "object",
"actor": "server1.conn1.child1/obj52",
"class": "HTMLButtonElement",
"extensible": true,
"frozen": false,
"sealed": false,
"ownPropertyLength": 0,
"preview": {
"kind": "DOMNode",
"nodeType": 1,
"nodeName": "button",
"isConnected": false,
"attributes": {
"id": "btn-1",
"class": "btn btn-log",
"type": "button"
},
"attributesLength": 3
}
},
{
"type": "object",
"actor": "server1.conn1.child1/obj53",
"class": "HTMLButtonElement",
"extensible": true,
"frozen": false,
"sealed": false,
"ownPropertyLength": 0,
"preview": {
"kind": "DOMNode",
"nodeType": 1,
"nodeName": "button",
"isConnected": false,
"attributes": {
"id": "btn-2",
"class": "btn btn-err",
"type": "button"
},
"attributesLength": 3
}
},
{
"type": "object",
"actor": "server1.conn1.child1/obj54",
"class": "HTMLButtonElement",
"extensible": true,
"frozen": false,
"sealed": false,
"ownPropertyLength": 0,
"preview": {
"kind": "DOMNode",
"nodeType": 1,
"nodeName": "button",
"isConnected": false,
"attributes": {
"id": "btn-3",
"class": "btn btn-count",

View File

@ -22,9 +22,10 @@ window.onload = Task.async(function* () {
const {
REPS,
MODE,
getRep,
getSelectableInInspectorGrips,
} = browserRequire("devtools/client/shared/components/reps/reps");
let { Rep, GripMap } = REPS;
let { GripMap } = REPS;
const componentUnderTest = GripMap;
@ -55,8 +56,7 @@ window.onload = Task.async(function* () {
// Test that correct rep is chosen
const gripStub = getGripStub("testEmptyMap");
const renderedRep = shallowRenderComponent(Rep, { object: gripStub });
is(renderedRep.type, GripMap.rep, `Rep correctly selects ${GripMap.rep.displayName}`);
is(getRep(gripStub), GripMap.rep, "Rep correctly selects GripMap Rep");
// Test rendering
const defaultOutput = `Map { }`;
@ -118,8 +118,7 @@ window.onload = Task.async(function* () {
// Test that correct rep is chosen
const gripStub = getGripStub("testWeakMap");
const renderedRep = shallowRenderComponent(Rep, { object: gripStub });
is(renderedRep.type, GripMap.rep, `Rep correctly selects ${GripMap.rep.displayName}`);
is(getRep(gripStub), GripMap.rep, "Rep correctly selects GripMap Rep");
// Test rendering
const defaultOutput = `WeakMap { Object: "value-a" }`;
@ -254,11 +253,9 @@ window.onload = Task.async(function* () {
const valuesGrips = getSelectableInInspectorGrips(nodeValuedStub);
is(valuesGrips.length, 3, "the stub has three node grips");
const valuesattachedActorIds = getStubAttachedActorIds(valuesGrips);
const keysGrips = getSelectableInInspectorGrips(nodeKeyedStub);
is(keysGrips.length, 3, "the stub has three node grips");
const keysAttachedActorIds = getStubAttachedActorIds(keysGrips);
let mouseOverValue;
let onDOMNodeMouseOver = (object) => {
@ -269,7 +266,6 @@ window.onload = Task.async(function* () {
const nodeValuedRenderedComponent = renderComponent(GripMap.rep, {
object: nodeValuedStub,
onDOMNodeMouseOver,
attachedActorIds: valuesattachedActorIds,
});
let nodes = nodeValuedRenderedComponent.querySelectorAll(".objectBox-node");
@ -284,7 +280,6 @@ window.onload = Task.async(function* () {
const nodeKeyedRenderedComponent = renderComponent(GripMap.rep, {
object: nodeKeyedStub,
onDOMNodeMouseOver,
attachedActorIds: keysAttachedActorIds,
});
nodes = nodeKeyedRenderedComponent.querySelectorAll(".objectBox-node");
@ -302,11 +297,9 @@ window.onload = Task.async(function* () {
const valuesGrips = getSelectableInInspectorGrips(nodeValuedStub);
is(valuesGrips.length, 3, "the stub has three node grips");
const valuesattachedActorIds = getStubAttachedActorIds(valuesGrips);
const keysGrips = getSelectableInInspectorGrips(nodeKeyedStub);
is(keysGrips.length, 3, "the stub has three node grips");
const keysAttachedActorIds = getStubAttachedActorIds(keysGrips);
let called = 0;
let onDOMNodeMouseOut = (object) => {
@ -317,7 +310,6 @@ window.onload = Task.async(function* () {
const nodeValuedRenderedComponent = renderComponent(GripMap.rep, {
object: nodeValuedStub,
onDOMNodeMouseOut,
attachedActorIds: valuesattachedActorIds,
});
let nodes = nodeValuedRenderedComponent.querySelectorAll(".objectBox-node");
@ -330,7 +322,6 @@ window.onload = Task.async(function* () {
const nodeKeyedRenderedComponent = renderComponent(GripMap.rep, {
object: nodeKeyedStub,
onDOMNodeMouseOut,
attachedActorIds: keysAttachedActorIds,
});
nodes = nodeKeyedRenderedComponent.querySelectorAll(".objectBox-node");
@ -348,11 +339,9 @@ window.onload = Task.async(function* () {
const valuesGrips = getSelectableInInspectorGrips(nodeValuedStub);
is(valuesGrips.length, 3, "the stub has three node grips");
const valuesattachedActorIds = getStubAttachedActorIds(valuesGrips);
const keysGrips = getSelectableInInspectorGrips(nodeKeyedStub);
is(keysGrips.length, 3, "the stub has three node grips");
const keysAttachedActorIds = getStubAttachedActorIds(keysGrips);
let inspectIconClickedValue = null;
let onInspectIconClick = (object) => {
@ -360,23 +349,21 @@ window.onload = Task.async(function* () {
};
const renderedComponentWithoutInspectIcon = renderComponent(GripMap.rep, {
object: nodeValuedStub,
object: getGripStub("testDisconnectedNodeValuedMap"),
onInspectIconClick,
attachedActorIds: [],
});
is(renderedComponentWithoutInspectIcon.querySelector(".open-inspector"), null,
"There isn't an inspect icon when the actor is not in attachedActorIds");
"There isn't an inspect icon when nodes are not connected to the DOM tree");
info("Testing onInspectIconClick on node valued Map");
const nodeValuedRenderedComponent = renderComponent(GripMap.rep, {
object: nodeValuedStub,
onInspectIconClick,
attachedActorIds: valuesattachedActorIds,
});
let icons = nodeValuedRenderedComponent.querySelectorAll(".open-inspector");
is(icons.length, valuesGrips.length,
"There is an icon for each map value with a matching attachedNodeFront");
"There is an icon for each node connected to the DOM tree");
icons.forEach((icon, index) => {
TestUtils.Simulate.click(icon);
@ -388,12 +375,11 @@ window.onload = Task.async(function* () {
const nodeKeyedRenderedComponent = renderComponent(GripMap.rep, {
object: nodeKeyedStub,
onInspectIconClick,
attachedActorIds: keysAttachedActorIds,
});
icons = nodeKeyedRenderedComponent.querySelectorAll(".open-inspector");
is(icons.length, keysGrips.length,
"There is an icon for each map key with a matching attachedNodeFront");
"There is an icon for each node connected to the DOM tree");
icons.forEach((icon, index) => {
TestUtils.Simulate.click(icon);
@ -607,6 +593,92 @@ window.onload = Task.async(function* () {
}
};
case "testDisconnectedNodeValuedMap":
return {
"type": "object",
"actor": "server1.conn1.child1/obj213",
"class": "Map",
"ownPropertyLength": 0,
"preview": {
"kind": "MapLike",
"size": 3,
"entries": [
[
"item-0",
{
"type": "object",
"actor": "server1.conn1.child1/obj214",
"class": "HTMLButtonElement",
"extensible": true,
"frozen": false,
"sealed": false,
"ownPropertyLength": 0,
"preview": {
"kind": "DOMNode",
"nodeType": 1,
"nodeName": "button",
"isConnected": false,
"attributes": {
"id": "btn-1",
"class": "btn btn-log",
"type": "button"
},
"attributesLength": 3
}
}
],
[
"item-1",
{
"type": "object",
"actor": "server1.conn1.child1/obj215",
"class": "HTMLButtonElement",
"extensible": true,
"frozen": false,
"sealed": false,
"ownPropertyLength": 0,
"preview": {
"kind": "DOMNode",
"nodeType": 1,
"nodeName": "button",
"isConnected": false,
"attributes": {
"id": "btn-2",
"class": "btn btn-err",
"type": "button"
},
"attributesLength": 3
}
}
],
[
"item-2",
{
"type": "object",
"actor": "server1.conn1.child1/obj216",
"class": "HTMLButtonElement",
"extensible": true,
"frozen": false,
"sealed": false,
"ownPropertyLength": 0,
"preview": {
"kind": "DOMNode",
"nodeType": 1,
"nodeName": "button",
"isConnected": false,
"attributes": {
"id": "btn-3",
"class": "btn btn-count",
"type": "button"
},
"attributesLength": 3
}
}
]
]
}
};
case "testNodeValuedMap":
return {
"type": "object",
@ -631,6 +703,7 @@ window.onload = Task.async(function* () {
"kind": "DOMNode",
"nodeType": 1,
"nodeName": "button",
"isConnected": true,
"attributes": {
"id": "btn-1",
"class": "btn btn-log",
@ -654,6 +727,7 @@ window.onload = Task.async(function* () {
"kind": "DOMNode",
"nodeType": 1,
"nodeName": "button",
"isConnected": true,
"attributes": {
"id": "btn-2",
"class": "btn btn-err",
@ -677,6 +751,7 @@ window.onload = Task.async(function* () {
"kind": "DOMNode",
"nodeType": 1,
"nodeName": "button",
"isConnected": true,
"attributes": {
"id": "btn-3",
"class": "btn btn-count",
@ -713,6 +788,7 @@ window.onload = Task.async(function* () {
"kind": "DOMNode",
"nodeType": 1,
"nodeName": "button",
"isConnected": true,
"attributes": {
"id": "btn-1",
"class": "btn btn-log",
@ -736,6 +812,7 @@ window.onload = Task.async(function* () {
"kind": "DOMNode",
"nodeType": 1,
"nodeName": "button",
"isConnected": true,
"attributes": {
"id": "btn-3",
"class": "btn btn-count",
@ -759,6 +836,7 @@ window.onload = Task.async(function* () {
"kind": "DOMNode",
"nodeType": 1,
"nodeName": "button",
"isConnected": true,
"attributes": {
"id": "btn-2",
"class": "btn btn-err",

View File

@ -20,9 +20,10 @@ window.onload = Task.async(function* () {
const {
REPS,
MODE,
getRep,
getSelectableInInspectorGrips,
} = browserRequire("devtools/client/shared/components/reps/reps");
let { Rep, Grip } = REPS;
let { Grip } = REPS;
const componentUnderTest = Grip;
@ -66,8 +67,7 @@ window.onload = Task.async(function* () {
// Test that correct rep is chosen
const gripStub = getGripStub("testBasic");
const renderedRep = shallowRenderComponent(Rep, { object: gripStub });
is(renderedRep.type, Grip.rep, `Rep correctly selects ${Grip.rep.displayName}`);
is(getRep(gripStub), Grip.rep, "Rep correctly selects Grip Rep");
// Test rendering
const defaultOutput = `Object { }`;
@ -100,8 +100,7 @@ window.onload = Task.async(function* () {
// Test that correct rep is chosen
const gripStub = getGripStub(testName);
const renderedRep = shallowRenderComponent(Rep, { object: gripStub });
is(renderedRep.type, Grip.rep, `Rep correctly selects ${Grip.rep.displayName}`);
is(getRep(gripStub), Grip.rep, "Rep correctly selects Grip Rep");
// Test rendering
const defaultOutput = `Boolean { true }`;
@ -134,8 +133,7 @@ window.onload = Task.async(function* () {
// Test that correct rep is chosen
const gripStub = getGripStub(testName);
const renderedRep = shallowRenderComponent(Rep, { object: gripStub });
is(renderedRep.type, Grip.rep, `Rep correctly selects ${Grip.rep.displayName}`);
is(getRep(gripStub), Grip.rep, "Rep correctly selects Grip Rep");
// Test rendering
const defaultOutput = `Number { 42 }`;
@ -168,8 +166,7 @@ window.onload = Task.async(function* () {
// Test that correct rep is chosen
const gripStub = getGripStub(testName);
const renderedRep = shallowRenderComponent(Rep, { object: gripStub });
is(renderedRep.type, Grip.rep, `Rep correctly selects ${Grip.rep.displayName}`);
is(getRep(gripStub), Grip.rep, "Rep correctly selects Grip Rep");
// Test rendering
const defaultOutput = `String { "foo" }`;
@ -202,8 +199,7 @@ window.onload = Task.async(function* () {
// Test that correct rep is chosen
const gripStub = getGripStub(testName);
const renderedRep = shallowRenderComponent(Rep, { object: gripStub });
is(renderedRep.type, Grip.rep, `Rep correctly selects ${Grip.rep.displayName}`);
is(getRep(gripStub), Grip.rep, "Rep correctly selects Grip Rep");
// Test rendering
const defaultOutput = `Proxy { <target>: Object, <handler>: [3] }`;
@ -236,8 +232,7 @@ window.onload = Task.async(function* () {
// Test that correct rep is chosen
const gripStub = getGripStub(testName);
const renderedRep = shallowRenderComponent(Rep, { object: gripStub });
is(renderedRep.type, Grip.rep, `Rep correctly selects ${Grip.rep.displayName}`);
is(getRep(gripStub), Grip.rep, "Rep correctly selects Grip Rep");
// Test rendering
const defaultOutput = `ArrayBuffer { byteLength: 10 }`;
@ -270,8 +265,7 @@ window.onload = Task.async(function* () {
// Test that correct rep is chosen
const gripStub = getGripStub(testName);
const renderedRep = shallowRenderComponent(Rep, { object: gripStub });
is(renderedRep.type, Grip.rep, `Rep correctly selects ${Grip.rep.displayName}`);
is(getRep(gripStub), Grip.rep, "Rep correctly selects Grip Rep");
// Test rendering
const defaultOutput = `SharedArrayBuffer { byteLength: 5 }`;
@ -304,8 +298,7 @@ window.onload = Task.async(function* () {
// Test that correct rep is chosen
const gripStub = getGripStub(testName);
const renderedRep = shallowRenderComponent(Rep, { object: gripStub });
is(renderedRep.type, Grip.rep, `Rep correctly selects ${Grip.rep.displayName}`);
is(getRep(gripStub), Grip.rep, "Rep correctly selects Grip Rep");
// Test rendering
const defaultOutput =
@ -412,8 +405,7 @@ window.onload = Task.async(function* () {
// Test that correct rep is chosen
const gripStub = getGripStub("testNonEnumerableProps");
const renderedRep = shallowRenderComponent(Rep, { object: gripStub });
is(renderedRep.type, Grip.rep, `Rep correctly selects ${Grip.rep.displayName}`);
is(getRep(gripStub), Grip.rep, "Rep correctly selects Grip Rep");
// Test rendering
const defaultOutput = `Object { }`;
@ -537,7 +529,6 @@ window.onload = Task.async(function* () {
const grips = getSelectableInInspectorGrips(stub);
is(grips.length, 2, "the stub has two node grips");
const attachedActorIds = getStubAttachedActorIds(grips);
let mouseOverValue;
let called = 0;
@ -549,7 +540,6 @@ window.onload = Task.async(function* () {
const renderedComponent = renderComponent(Grip.rep, {
object: stub,
onDOMNodeMouseOver,
attachedActorIds,
});
const nodes = renderedComponent.querySelectorAll(".objectBox-node");
@ -568,7 +558,6 @@ window.onload = Task.async(function* () {
const grips = getSelectableInInspectorGrips(stub);
is(grips.length, 2, "the stub has two node grips");
const attachedActorIds = getStubAttachedActorIds(grips);
let called = 0;
let onDOMNodeMouseOut = (object) => {
@ -578,7 +567,6 @@ window.onload = Task.async(function* () {
const renderedComponent = renderComponent(Grip.rep, {
object: stub,
onDOMNodeMouseOut,
attachedActorIds,
});
const nodes = renderedComponent.querySelectorAll(".objectBox-node");
@ -593,7 +581,6 @@ window.onload = Task.async(function* () {
const grips = getSelectableInInspectorGrips(stub);
is(grips.length, 2, "the stub has two node grips");
const attachedActorIds = getStubAttachedActorIds(grips);
let inspectIconClickedValue = null;
let onInspectIconClick = (object) => {
@ -601,26 +588,20 @@ window.onload = Task.async(function* () {
};
let renderedComponentWithoutInspectIcon = renderComponent(Grip.rep, {
object: stub,
object: getGripStub("testObjectWithDisconnectedNodes"),
onInspectIconClick,
attachedActorIds: ["someOtherId"],
});
is(renderedComponentWithoutInspectIcon.querySelector(".open-inspector"), null,
"There isn't an inspect icon when the actor is not in attachedActorIds");
is(renderedComponentWithoutInspectIcon.querySelector(".open-inspector"), null,
"There isn't an inspect icon when attachedActorIds does not have keys " +
"matching grip properties");
"There isn't an inspect icon when the node is not connected to the DOM tree");
const renderedComponent = renderComponent(Grip.rep, {
object: stub,
onInspectIconClick,
attachedActorIds,
});
const icons = renderedComponent.querySelectorAll(".open-inspector");
is(icons.length, 2,
"There is an icon for each grip property matching an attachedNodeFront");
"There is an icon for each node connected to the DOM tree");
icons.forEach((icon, index) => {
TestUtils.Simulate.click(icon);
@ -1169,6 +1150,72 @@ window.onload = Task.async(function* () {
}
};
case "testObjectWithNodes":
return {
"type": "object",
"actor": "server1.conn1.child1/obj214",
"class": "Object",
"ownPropertyLength": 2,
"preview": {
"kind": "Object",
"ownProperties": {
"foo": {
"configurable": true,
"enumerable": true,
"writable": true,
"value": {
"type": "object",
"actor": "server1.conn1.child1/obj215",
"class": "HTMLButtonElement",
"extensible": true,
"frozen": false,
"sealed": false,
"ownPropertyLength": 0,
"preview": {
"kind": "DOMNode",
"nodeType": 1,
"nodeName": "button",
"isConnected": true,
"attributes": {
"id": "btn-1",
"class": "btn btn-log",
"type": "button"
},
"attributesLength": 3
}
}
},
"bar": {
"configurable": true,
"enumerable": true,
"writable": true,
"value": {
"type": "object",
"actor": "server1.conn1.child1/obj216",
"class": "HTMLButtonElement",
"extensible": true,
"frozen": false,
"sealed": false,
"ownPropertyLength": 0,
"preview": {
"kind": "DOMNode",
"nodeType": 1,
"nodeName": "button",
"isConnected": true,
"attributes": {
"id": "btn-2",
"class": "btn btn-err",
"type": "button"
},
"attributesLength": 3
}
}
}
},
"ownPropertiesLength": 2,
"safeGetterValues": {}
}
};
case "testObjectWithDisconnectedNodes":
return {
"type": "object",
"actor": "server1.conn1.child1/obj214",

View File

@ -19,8 +19,11 @@ Test Infinity rep
"use strict";
window.onload = Task.async(function* () {
const { REPS } = browserRequire("devtools/client/shared/components/reps/reps");
let { Rep, InfinityRep } = REPS;
const {
REPS,
getRep,
} = browserRequire("devtools/client/shared/components/reps/reps");
let { InfinityRep } = REPS;
try {
yield testInfinity();
@ -33,9 +36,7 @@ window.onload = Task.async(function* () {
function testInfinity() {
const stub = getGripStub("testInfinity");
const renderedRep = shallowRenderComponent(Rep, { object: stub });
is(renderedRep.type, InfinityRep.rep,
`Rep correctly selects ${InfinityRep.rep.displayName} for Infinity value`);
is(getRep(stub), InfinityRep.rep, "Rep correctly selects Infinity Rep");
const renderedComponent = renderComponent(InfinityRep.rep, { object: stub });
is(renderedComponent.textContent, "Infinity",
@ -44,9 +45,7 @@ window.onload = Task.async(function* () {
function testNegativeInfinity() {
const stub = getGripStub("testNegativeInfinity");
const renderedRep = shallowRenderComponent(Rep, { object: stub });
is(renderedRep.type, InfinityRep.rep,
`Rep correctly selects ${InfinityRep.rep.displayName} for negative Infinity value`);
is(getRep(stub), InfinityRep.rep, "Rep correctly selects Infinity Rep");
const renderedComponent = renderComponent(InfinityRep.rep, { object: stub });
is(renderedComponent.textContent, "-Infinity",

View File

@ -17,14 +17,16 @@ Test LongString rep
<script src="head.js" type="application/javascript"></script>
<script type="application/javascript">
window.onload = Task.async(function* () {
const { REPS } = browserRequire("devtools/client/shared/components/reps/reps");
let { Rep, LongStringRep } = REPS;
const {
REPS,
getRep,
} = browserRequire("devtools/client/shared/components/reps/reps");
let { LongStringRep } = REPS;
try {
// Test that correct rep is chosen
const renderedRep = shallowRenderComponent(Rep, { object: getGripStub("testMultiline") });
is(renderedRep.type, LongStringRep.rep,
`Rep correctly selects ${LongStringRep.rep.displayName}`);
is(getRep(getGripStub("testMultiline")), LongStringRep.rep,
"Rep correctly selects LongString Rep");
// Test rendering
yield testMultiline();

Some files were not shown because too many files have changed in this diff Show More