mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-20 16:55:40 +00:00
Merge mozilla-central to mozilla-inbound. a=merge
This commit is contained in:
commit
a9686f654d
@ -55,9 +55,6 @@ module.exports = {
|
|||||||
}, {
|
}, {
|
||||||
// TODO: Bug 1246594. Empty this list once the rule has landed for all dirs
|
// TODO: Bug 1246594. Empty this list once the rule has landed for all dirs
|
||||||
"files": [
|
"files": [
|
||||||
"gfx/layers/apz/test/mochitest/**",
|
|
||||||
"mobile/android/components/**",
|
|
||||||
"mobile/android/modules/**",
|
|
||||||
"modules/libmar/tests/unit/head_libmar.js",
|
"modules/libmar/tests/unit/head_libmar.js",
|
||||||
"netwerk/protocol/http/WellKnownOpportunisticUtils.jsm",
|
"netwerk/protocol/http/WellKnownOpportunisticUtils.jsm",
|
||||||
"netwerk/test/httpserver/httpd.js",
|
"netwerk/test/httpserver/httpd.js",
|
||||||
|
@ -65,6 +65,12 @@ var SidebarUI = {
|
|||||||
_switcherArrow: null,
|
_switcherArrow: null,
|
||||||
_inited: false,
|
_inited: false,
|
||||||
|
|
||||||
|
_initDeferred: PromiseUtils.defer(),
|
||||||
|
|
||||||
|
get promiseInitialized() {
|
||||||
|
return this._initDeferred.promise;
|
||||||
|
},
|
||||||
|
|
||||||
get initialized() {
|
get initialized() {
|
||||||
return this._inited;
|
return this._inited;
|
||||||
},
|
},
|
||||||
@ -83,6 +89,8 @@ var SidebarUI = {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this._inited = true;
|
this._inited = true;
|
||||||
|
|
||||||
|
this._initDeferred.resolve();
|
||||||
},
|
},
|
||||||
|
|
||||||
uninit() {
|
uninit() {
|
||||||
|
@ -983,7 +983,7 @@ const menuTracker = {
|
|||||||
gMenuBuilder.build(subject);
|
gMenuBuilder.build(subject);
|
||||||
},
|
},
|
||||||
|
|
||||||
onWindowOpen(window) {
|
async onWindowOpen(window) {
|
||||||
for (const id of menuTracker.menuIds) {
|
for (const id of menuTracker.menuIds) {
|
||||||
const menu = window.document.getElementById(id);
|
const menu = window.document.getElementById(id);
|
||||||
menu.addEventListener("popupshowing", menuTracker);
|
menu.addEventListener("popupshowing", menuTracker);
|
||||||
@ -991,7 +991,10 @@ const menuTracker = {
|
|||||||
|
|
||||||
const sidebarHeader = window.document.getElementById("sidebar-switcher-target");
|
const sidebarHeader = window.document.getElementById("sidebar-switcher-target");
|
||||||
sidebarHeader.addEventListener("SidebarShown", menuTracker.onSidebarShown);
|
sidebarHeader.addEventListener("SidebarShown", menuTracker.onSidebarShown);
|
||||||
if (window.SidebarUI.currentID === "viewBookmarksSidebar") {
|
|
||||||
|
await window.SidebarUI.promiseInitialized;
|
||||||
|
|
||||||
|
if (!window.closed && window.SidebarUI.currentID === "viewBookmarksSidebar") {
|
||||||
menuTracker.onSidebarShown({currentTarget: sidebarHeader});
|
menuTracker.onSidebarShown({currentTarget: sidebarHeader});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1185,7 +1185,6 @@ function getTransactionsForCopy(items, insertionIndex,
|
|||||||
!PlacesUtils.bookmarks.isVirtualRootItem(guid) &&
|
!PlacesUtils.bookmarks.isVirtualRootItem(guid) &&
|
||||||
!PlacesUtils.isVirtualLeftPaneItem(guid)) {
|
!PlacesUtils.isVirtualLeftPaneItem(guid)) {
|
||||||
transaction = PlacesTransactions.Copy({
|
transaction = PlacesTransactions.Copy({
|
||||||
excludingAnnotation: "Places/SmartBookmark",
|
|
||||||
guid,
|
guid,
|
||||||
newIndex: index,
|
newIndex: index,
|
||||||
newParentGuid: insertionParentGuid,
|
newParentGuid: insertionParentGuid,
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
const TP_PB_ENABLED_PREF = "privacy.trackingprotection.pbmode.enabled";
|
const TP_PB_ENABLED_PREF = "privacy.trackingprotection.pbmode.enabled";
|
||||||
|
|
||||||
|
const {UrlbarTestUtils} = ChromeUtils.import("resource://testing-common/UrlbarTestUtils.jsm");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens a new private window and loads "about:privatebrowsing" there.
|
* Opens a new private window and loads "about:privatebrowsing" there.
|
||||||
*/
|
*/
|
||||||
@ -133,12 +135,15 @@ add_task(async function test_search_handoff_on_keydown() {
|
|||||||
});
|
});
|
||||||
ok(urlBarHasNormalFocus(win), "url bar has normal focused");
|
ok(urlBarHasNormalFocus(win), "url bar has normal focused");
|
||||||
is(win.gURLBar.value, "@google f", "url bar has search text");
|
is(win.gURLBar.value, "@google f", "url bar has search text");
|
||||||
|
await UrlbarTestUtils.promiseSearchComplete(win);
|
||||||
|
// Close the popup.
|
||||||
|
await UrlbarTestUtils.promisePopupClose(win);
|
||||||
|
|
||||||
// Hitting ESC should reshow the in-content search
|
// Hitting ESC should reshow the in-content search
|
||||||
await new Promise(r => EventUtils.synthesizeKey("KEY_Escape", {}, win, r));
|
await new Promise(r => EventUtils.synthesizeKey("KEY_Escape", {}, win, r));
|
||||||
await ContentTask.spawn(tab, null, async function() {
|
await ContentTask.spawn(tab, null, async function() {
|
||||||
ok(!content.document.getElementById("search-handoff-button").classList.contains("hidden"),
|
ok(!content.document.getElementById("search-handoff-button").classList.contains("hidden"),
|
||||||
"in-content search is not");
|
"in-content search is not hidden");
|
||||||
});
|
});
|
||||||
|
|
||||||
await BrowserTestUtils.closeWindow(win);
|
await BrowserTestUtils.closeWindow(win);
|
||||||
@ -176,6 +181,11 @@ add_task(async function test_search_handoff_on_paste() {
|
|||||||
.getService(SpecialPowers.Ci.nsIClipboardHelper);
|
.getService(SpecialPowers.Ci.nsIClipboardHelper);
|
||||||
helper.copyString("words");
|
helper.copyString("words");
|
||||||
await new Promise(r => EventUtils.synthesizeKey("v", {accelKey: true}, win, r));
|
await new Promise(r => EventUtils.synthesizeKey("v", {accelKey: true}, win, r));
|
||||||
|
// TODO: Bug 1539199 We should be able to wait for search complete for AwesomeBar
|
||||||
|
// as well.
|
||||||
|
if (UrlbarPrefs.get("quantumbar")) {
|
||||||
|
await UrlbarTestUtils.promiseSearchComplete(win);
|
||||||
|
}
|
||||||
ok(urlBarHasNormalFocus(win), "url bar has normal focused");
|
ok(urlBarHasNormalFocus(win), "url bar has normal focused");
|
||||||
is(win.gURLBar.value, "@google words", "url bar has search text");
|
is(win.gURLBar.value, "@google words", "url bar has search text");
|
||||||
|
|
||||||
|
@ -554,6 +554,7 @@ class UrlbarInput {
|
|||||||
muxer: "UnifiedComplete",
|
muxer: "UnifiedComplete",
|
||||||
providers: ["UnifiedComplete"],
|
providers: ["UnifiedComplete"],
|
||||||
searchString,
|
searchString,
|
||||||
|
userContextId: this.window.gBrowser.selectedBrowser.getAttribute("usercontextid"),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -989,12 +990,18 @@ class UrlbarInput {
|
|||||||
*/
|
*/
|
||||||
_loadURL(url, openUILinkWhere, params, result = {},
|
_loadURL(url, openUILinkWhere, params, result = {},
|
||||||
browser = this.window.gBrowser.selectedBrowser) {
|
browser = this.window.gBrowser.selectedBrowser) {
|
||||||
this.value = url;
|
// No point in setting these because we'll handleRevert() a few rows below.
|
||||||
browser.userTypedValue = url;
|
if (openUILinkWhere == "current") {
|
||||||
|
this.value = url;
|
||||||
|
browser.userTypedValue = url;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.window.gInitialPages.includes(url)) {
|
// No point in setting this if we are loading in a new window.
|
||||||
|
if (openUILinkWhere != "window" &&
|
||||||
|
this.window.gInitialPages.includes(url)) {
|
||||||
browser.initialPageLoadedFromUserAction = url;
|
browser.initialPageLoadedFromUserAction = url;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
UrlbarUtils.addToUrlbarHistory(url, this.window);
|
UrlbarUtils.addToUrlbarHistory(url, this.window);
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
|
@ -395,6 +395,8 @@ class UrlbarQueryContext {
|
|||||||
* The maximum number of results that will be displayed for this query.
|
* The maximum number of results that will be displayed for this query.
|
||||||
* @param {boolean} options.allowAutofill
|
* @param {boolean} options.allowAutofill
|
||||||
* Whether or not to allow providers to include autofill results.
|
* Whether or not to allow providers to include autofill results.
|
||||||
|
* @param {number} options.userContextId
|
||||||
|
* The container id where this context was generated, if any.
|
||||||
*/
|
*/
|
||||||
constructor(options = {}) {
|
constructor(options = {}) {
|
||||||
this._checkRequiredOptions(options, [
|
this._checkRequiredOptions(options, [
|
||||||
@ -418,6 +420,8 @@ class UrlbarQueryContext {
|
|||||||
(!Array.isArray(options.sources) || !options.sources.length)) {
|
(!Array.isArray(options.sources) || !options.sources.length)) {
|
||||||
throw new Error(`Invalid sources list`);
|
throw new Error(`Invalid sources list`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.userContextId = options.userContextId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -226,6 +226,17 @@ var UrlbarTestUtils = {
|
|||||||
let urlbar = getUrlbarAbstraction(win);
|
let urlbar = getUrlbarAbstraction(win);
|
||||||
return urlbar.isPopupOpen();
|
return urlbar.isPopupOpen();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the userContextId (container id) for the last search.
|
||||||
|
* @param {object} win The browser window
|
||||||
|
* @returns {Promise} resolved when fetching is complete
|
||||||
|
* @resolves {number} a userContextId
|
||||||
|
*/
|
||||||
|
promiseUserContextId(win) {
|
||||||
|
let urlbar = getUrlbarAbstraction(win);
|
||||||
|
return urlbar.promiseUserContextId();
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -340,6 +351,15 @@ class UrlbarAbstraction {
|
|||||||
"waiting urlbar search to complete", 100, 50);
|
"waiting urlbar search to complete", 100, 50);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async promiseUserContextId() {
|
||||||
|
const defaultId = Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID;
|
||||||
|
if (this.quantumbar) {
|
||||||
|
let context = await this.urlbar.lastQueryContextPromise;
|
||||||
|
return context.userContextId || defaultId;
|
||||||
|
}
|
||||||
|
return this.urlbar.userContextId || defaultId;
|
||||||
|
}
|
||||||
|
|
||||||
async promiseResultAt(index) {
|
async promiseResultAt(index) {
|
||||||
if (!this.quantumbar) {
|
if (!this.quantumbar) {
|
||||||
// In the legacy address bar, old results are replaced when new results
|
// In the legacy address bar, old results are replaced when new results
|
||||||
|
@ -70,7 +70,13 @@ async function withNewWindow(callback) {
|
|||||||
"", "chrome");
|
"", "chrome");
|
||||||
await BrowserTestUtils.waitForEvent(win, "load");
|
await BrowserTestUtils.waitForEvent(win, "load");
|
||||||
|
|
||||||
win.gBrowser = {};
|
win.gBrowser = {
|
||||||
|
selectedBrowser: {
|
||||||
|
getAttribute() {
|
||||||
|
return undefined;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
// Clone the elements into the new window, so we get exact copies without having
|
// Clone the elements into the new window, so we get exact copies without having
|
||||||
// to replicate the xul.
|
// to replicate the xul.
|
||||||
|
@ -11,8 +11,10 @@ const START_VALUE = "example.org";
|
|||||||
|
|
||||||
add_task(async function setup() {
|
add_task(async function setup() {
|
||||||
await SpecialPowers.pushPrefEnv({
|
await SpecialPowers.pushPrefEnv({
|
||||||
set: [["browser.altClickSave", true],
|
set: [
|
||||||
["browser.urlbar.autoFill", false]],
|
["browser.altClickSave", true],
|
||||||
|
["browser.urlbar.autoFill", false],
|
||||||
|
],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -29,7 +31,7 @@ add_task(async function alt_left_click_test() {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
triggerCommand("click", {altKey: true});
|
await triggerCommand("click", {altKey: true});
|
||||||
|
|
||||||
await saveURLPromise;
|
await saveURLPromise;
|
||||||
ok(true, "SaveURL was called");
|
ok(true, "SaveURL was called");
|
||||||
@ -41,7 +43,7 @@ add_task(async function shift_left_click_test() {
|
|||||||
|
|
||||||
let destinationURL = "http://" + TEST_VALUE + "/";
|
let destinationURL = "http://" + TEST_VALUE + "/";
|
||||||
let newWindowPromise = BrowserTestUtils.waitForNewWindow({url: destinationURL});
|
let newWindowPromise = BrowserTestUtils.waitForNewWindow({url: destinationURL});
|
||||||
triggerCommand("click", {shiftKey: true});
|
await triggerCommand("click", {shiftKey: true});
|
||||||
let win = await newWindowPromise;
|
let win = await newWindowPromise;
|
||||||
|
|
||||||
info("URL should be loaded in a new window");
|
info("URL should be loaded in a new window");
|
||||||
@ -65,7 +67,7 @@ add_task(async function right_click_test() {
|
|||||||
// Add a new tab.
|
// Add a new tab.
|
||||||
await promiseOpenNewTab();
|
await promiseOpenNewTab();
|
||||||
|
|
||||||
triggerCommand("click", {button: 2});
|
await triggerCommand("click", {button: 2});
|
||||||
|
|
||||||
// Right click should do nothing (context menu will be shown).
|
// Right click should do nothing (context menu will be shown).
|
||||||
is(gURLBar.value, TEST_VALUE, "Urlbar still has the value we entered");
|
is(gURLBar.value, TEST_VALUE, "Urlbar still has the value we entered");
|
||||||
@ -81,7 +83,7 @@ add_task(async function shift_accel_left_click_test() {
|
|||||||
let tab = await promiseOpenNewTab();
|
let tab = await promiseOpenNewTab();
|
||||||
|
|
||||||
let loadStartedPromise = promiseLoadStarted();
|
let loadStartedPromise = promiseLoadStarted();
|
||||||
triggerCommand("click", {accelKey: true, shiftKey: true});
|
await triggerCommand("click", {accelKey: true, shiftKey: true});
|
||||||
await loadStartedPromise;
|
await loadStartedPromise;
|
||||||
|
|
||||||
// Check the load occurred in a new background tab.
|
// Check the load occurred in a new background tab.
|
||||||
@ -92,7 +94,7 @@ add_task(async function shift_accel_left_click_test() {
|
|||||||
|
|
||||||
// Select the new background tab
|
// Select the new background tab
|
||||||
gBrowser.selectedTab = gBrowser.selectedTab.nextElementSibling;
|
gBrowser.selectedTab = gBrowser.selectedTab.nextElementSibling;
|
||||||
is(gURLBar.value, TEST_VALUE, "New URL is loaded in new tab");
|
is(gURLBar.textValue, TEST_VALUE, "New URL is loaded in new tab");
|
||||||
|
|
||||||
// Cleanup.
|
// Cleanup.
|
||||||
gBrowser.removeCurrentTab();
|
gBrowser.removeCurrentTab();
|
||||||
@ -129,7 +131,7 @@ add_task(async function load_in_current_tab_test() {
|
|||||||
|
|
||||||
// Trigger a load and check it occurs in the current tab.
|
// Trigger a load and check it occurs in the current tab.
|
||||||
let loadStartedPromise = promiseLoadStarted();
|
let loadStartedPromise = promiseLoadStarted();
|
||||||
triggerCommand(type, details);
|
await triggerCommand(type, details);
|
||||||
await loadStartedPromise;
|
await loadStartedPromise;
|
||||||
|
|
||||||
info("URL should be loaded in the current tab");
|
info("URL should be loaded in the current tab");
|
||||||
@ -149,7 +151,7 @@ add_task(async function load_in_new_tab_test() {
|
|||||||
desc: "Ctrl/Cmd left click on go button",
|
desc: "Ctrl/Cmd left click on go button",
|
||||||
type: "click",
|
type: "click",
|
||||||
details: {accelKey: true},
|
details: {accelKey: true},
|
||||||
url: null,
|
url: "about:blank",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "Alt+Return keypress in a dirty tab",
|
desc: "Alt+Return keypress in a dirty tab",
|
||||||
@ -163,16 +165,16 @@ add_task(async function load_in_new_tab_test() {
|
|||||||
info(`Running test: ${desc}`);
|
info(`Running test: ${desc}`);
|
||||||
|
|
||||||
// Add a new tab.
|
// Add a new tab.
|
||||||
let tab = await promiseOpenNewTab(url || "about:blank");
|
let tab = await promiseOpenNewTab(url);
|
||||||
|
|
||||||
// Trigger a load and check it occurs in the current tab.
|
// Trigger a load and check it occurs in the current tab.
|
||||||
let tabSwitchedPromise = promiseNewTabSwitched();
|
let tabSwitchedPromise = promiseNewTabSwitched();
|
||||||
triggerCommand(type, details);
|
await triggerCommand(type, details);
|
||||||
await tabSwitchedPromise;
|
await tabSwitchedPromise;
|
||||||
|
|
||||||
// Check the load occurred in a new tab.
|
// Check the load occurred in a new tab.
|
||||||
info("URL should be loaded in a new focused tab");
|
info("URL should be loaded in a new focused tab");
|
||||||
is(gURLBar.inputField.value, TEST_VALUE, "Urlbar still has the value we entered");
|
is(gURLBar.textValue, TEST_VALUE, "Urlbar still has the value we entered");
|
||||||
await promiseCheckChildNoFocusedElement(gBrowser.selectedBrowser);
|
await promiseCheckChildNoFocusedElement(gBrowser.selectedBrowser);
|
||||||
is(document.activeElement, gBrowser.selectedBrowser, "Content window should be focused");
|
is(document.activeElement, gBrowser.selectedBrowser, "Content window should be focused");
|
||||||
isnot(gBrowser.selectedTab, tab, "New URL was loaded in a new tab");
|
isnot(gBrowser.selectedTab, tab, "New URL was loaded in a new tab");
|
||||||
@ -183,11 +185,15 @@ add_task(async function load_in_new_tab_test() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function triggerCommand(type, details = {}) {
|
async function triggerCommand(type, details = {}) {
|
||||||
gURLBar.focus();
|
gURLBar.focus();
|
||||||
gURLBar.value = "";
|
gURLBar.value = "";
|
||||||
EventUtils.sendString(TEST_VALUE);
|
EventUtils.sendString(TEST_VALUE);
|
||||||
|
|
||||||
|
Assert.equal(await UrlbarTestUtils.promiseUserContextId(window),
|
||||||
|
gBrowser.selectedTab.getAttribute("usercontextid"),
|
||||||
|
"userContextId must be the same as the originating tab");
|
||||||
|
|
||||||
if (type == "click") {
|
if (type == "click") {
|
||||||
ok(gURLBar.hasAttribute("usertyping"),
|
ok(gURLBar.hasAttribute("usertyping"),
|
||||||
"usertyping attribute must be set for the go button to be visible");
|
"usertyping attribute must be set for the go button to be visible");
|
||||||
@ -212,8 +218,9 @@ function promiseLoadStarted() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let gUserContextIdSerial = 1;
|
||||||
async function promiseOpenNewTab(url = "about:blank") {
|
async function promiseOpenNewTab(url = "about:blank") {
|
||||||
let tab = BrowserTestUtils.addTab(gBrowser, url);
|
let tab = BrowserTestUtils.addTab(gBrowser, url, {userContextId: gUserContextIdSerial++});
|
||||||
let tabSwitchPromise = promiseNewTabSwitched(tab);
|
let tabSwitchPromise = promiseNewTabSwitched(tab);
|
||||||
gBrowser.selectedTab = tab;
|
gBrowser.selectedTab = tab;
|
||||||
await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
|
await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
|
||||||
|
@ -45,10 +45,14 @@
|
|||||||
--white-100: #fff; /* for ui, no special semantic */
|
--white-100: #fff; /* for ui, no special semantic */
|
||||||
|
|
||||||
/* Typography from Photon */
|
/* Typography from Photon */
|
||||||
|
/* See https://firefox-dev.tools/photon/visuals/typography.html */
|
||||||
--body-10-font-size: 13px;
|
--body-10-font-size: 13px;
|
||||||
--body-10-font-weight: 400;
|
--body-10-font-weight: 400;
|
||||||
--body-20-font-size: 15px;
|
--body-20-font-size: 15px;
|
||||||
--body-20-font-weight: 700;
|
--body-20-font-weight: 400;
|
||||||
|
--body-20-font-weight-bold: 700;
|
||||||
|
--caption-10-font-size: 11px;
|
||||||
|
--caption-10-font-weight: 400;
|
||||||
--caption-20-font-size: 13px;
|
--caption-20-font-size: 13px;
|
||||||
--caption-20-font-weight: 400;
|
--caption-20-font-weight: 400;
|
||||||
--caption-20-color: var(--grey-50);
|
--caption-20-color: var(--grey-50);
|
||||||
@ -245,7 +249,7 @@ p, h1 {
|
|||||||
|
|
||||||
/* adds breathing space to the separator */
|
/* adds breathing space to the separator */
|
||||||
.separator--breathe {
|
.separator--breathe {
|
||||||
margin: calc(var(--base-unit) * 4) 0;
|
margin: calc(var(--base-unit) * 5) 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* a series of button-like elements, layed out horizontally */
|
/* a series of button-like elements, layed out horizontally */
|
||||||
|
@ -43,7 +43,7 @@
|
|||||||
align-self: center;
|
align-self: center;
|
||||||
grid-area: name;
|
grid-area: name;
|
||||||
font-size: var(--body-20-font-size);
|
font-size: var(--body-20-font-size);
|
||||||
font-weight: var(--body-20-font-weight);
|
font-weight: var(--body-20-font-weight-bold);
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
margin-inline-start: calc(var(--base-unit) * 3);
|
margin-inline-start: calc(var(--base-unit) * 3);
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,11 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
.sidebar {
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: auto auto;
|
||||||
|
}
|
||||||
|
|
||||||
.sidebar__label {
|
.sidebar__label {
|
||||||
color: var(--grey-40);
|
color: var(--grey-40);
|
||||||
display: block;
|
display: block;
|
||||||
@ -13,3 +18,20 @@
|
|||||||
.sidebar__refresh-usb {
|
.sidebar__refresh-usb {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sidebar__footer {
|
||||||
|
align-self: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar__footer__support-help {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
|
column-gap: calc(var(--base-unit) * 4);
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar__footer__icon {
|
||||||
|
width: calc(var(--base-unit) * 4);
|
||||||
|
height: calc(var(--base-unit) * 4);
|
||||||
|
}
|
||||||
|
@ -63,9 +63,7 @@ class Sidebar extends PureComponent {
|
|||||||
|
|
||||||
renderDevicesEmpty() {
|
renderDevicesEmpty() {
|
||||||
return SidebarItem(
|
return SidebarItem(
|
||||||
{
|
{},
|
||||||
isSelected: false,
|
|
||||||
},
|
|
||||||
Localized(
|
Localized(
|
||||||
{
|
{
|
||||||
id: "about-debugging-sidebar-no-devices",
|
id: "about-debugging-sidebar-no-devices",
|
||||||
@ -89,12 +87,12 @@ class Sidebar extends PureComponent {
|
|||||||
}
|
}
|
||||||
// render all devices otherwise
|
// render all devices otherwise
|
||||||
return [
|
return [
|
||||||
...this.renderSidebarItems(GLOBE_ICON, networkRuntimes),
|
...this.renderRuntimeItems(GLOBE_ICON, networkRuntimes),
|
||||||
...this.renderSidebarItems(USB_ICON, usbRuntimes),
|
...this.renderRuntimeItems(USB_ICON, usbRuntimes),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
renderSidebarItems(icon, runtimes) {
|
renderRuntimeItems(icon, runtimes) {
|
||||||
const { dispatch, selectedPage, selectedRuntimeId } = this.props;
|
const { dispatch, selectedPage, selectedRuntimeId } = this.props;
|
||||||
|
|
||||||
return runtimes.map(runtime => {
|
return runtimes.map(runtime => {
|
||||||
@ -123,6 +121,51 @@ class Sidebar extends PureComponent {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderFooter() {
|
||||||
|
const HELP_ICON_SRC = "chrome://global/skin/icons/help.svg";
|
||||||
|
const SUPPORT_URL = "https://developer.mozilla.org/docs/Tools/about:debugging";
|
||||||
|
|
||||||
|
return dom.footer(
|
||||||
|
{
|
||||||
|
className: "sidebar__footer",
|
||||||
|
},
|
||||||
|
dom.ul(
|
||||||
|
{},
|
||||||
|
SidebarItem(
|
||||||
|
{
|
||||||
|
className: "sidebar-item--condensed",
|
||||||
|
to: SUPPORT_URL,
|
||||||
|
},
|
||||||
|
dom.span(
|
||||||
|
{
|
||||||
|
className: "sidebar__footer__support-help",
|
||||||
|
},
|
||||||
|
Localized(
|
||||||
|
{
|
||||||
|
id: "about-debugging-sidebar-support-icon",
|
||||||
|
attrs: {
|
||||||
|
alt: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
dom.img(
|
||||||
|
{
|
||||||
|
className: "sidebar__footer__icon",
|
||||||
|
src: HELP_ICON_SRC,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Localized(
|
||||||
|
{
|
||||||
|
id: "about-debugging-sidebar-support",
|
||||||
|
},
|
||||||
|
dom.span({}, "about-debugging-sidebar-support"),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { dispatch, selectedPage, selectedRuntimeId, isScanningUsb } = this.props;
|
const { dispatch, selectedPage, selectedRuntimeId, isScanningUsb } = this.props;
|
||||||
|
|
||||||
@ -156,17 +199,15 @@ class Sidebar extends PureComponent {
|
|||||||
),
|
),
|
||||||
SidebarItem(
|
SidebarItem(
|
||||||
{
|
{
|
||||||
className: "sidebar-item--overflow",
|
className: "sidebar-item--overflow sidebar-item--full-width",
|
||||||
isSelected: false,
|
|
||||||
},
|
},
|
||||||
dom.hr({ className: "separator" }),
|
dom.hr({ className: "separator separator--breathe" }),
|
||||||
this.renderAdbAddonStatus(),
|
this.renderAdbAddonStatus(),
|
||||||
),
|
),
|
||||||
this.renderDevices(),
|
this.renderDevices(),
|
||||||
SidebarItem(
|
SidebarItem(
|
||||||
{
|
{
|
||||||
className: "sidebar-item--breathe sidebar__refresh-usb",
|
className: "sidebar-item--breathe sidebar__refresh-usb",
|
||||||
isSelected: false,
|
|
||||||
key: "refresh-devices",
|
key: "refresh-devices",
|
||||||
},
|
},
|
||||||
RefreshDevicesButton({
|
RefreshDevicesButton({
|
||||||
@ -174,7 +215,8 @@ class Sidebar extends PureComponent {
|
|||||||
isScanning: isScanningUsb,
|
isScanning: isScanningUsb,
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
|
this.renderFooter(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,8 +15,9 @@
|
|||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 34px 1fr;
|
grid-template-columns: 34px 1fr;
|
||||||
font-size: 16px;
|
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
font-size: var(--body-20-font-size);
|
||||||
|
font-weight: var(--body-20-font-weight);
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-fixed-item__icon {
|
.sidebar-fixed-item__icon {
|
||||||
|
@ -33,6 +33,7 @@ class SidebarFixedItem extends PureComponent {
|
|||||||
|
|
||||||
return SidebarItem(
|
return SidebarItem(
|
||||||
{
|
{
|
||||||
|
className: "sidebar-item--tall",
|
||||||
isSelected,
|
isSelected,
|
||||||
to,
|
to,
|
||||||
},
|
},
|
||||||
|
@ -11,17 +11,29 @@
|
|||||||
.sidebar-item {
|
.sidebar-item {
|
||||||
color: var(--sidebar-text-color);
|
color: var(--sidebar-text-color);
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
height: var(--category-height);
|
|
||||||
padding-inline-end: var(--category-padding);
|
padding-inline-end: var(--category-padding);
|
||||||
padding-inline-start: var(--category-padding);
|
padding-inline-start: var(--category-padding);
|
||||||
transition: background-color var(--category-transition-duration);
|
transition: background-color var(--category-transition-duration);
|
||||||
-moz-user-select: none;
|
-moz-user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-item--overflow {
|
.sidebar-item--tall {
|
||||||
|
height: var(--category-height);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-item--condensed {
|
||||||
|
height: calc(var(--base-unit) * 9);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-item--full-width {
|
||||||
|
padding-inline-start: 0;
|
||||||
|
padding-inline-end: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* .sidebar-item--overflow {
|
||||||
min-height: var(--category-height);
|
min-height: var(--category-height);
|
||||||
height: auto;
|
height: auto;
|
||||||
}
|
} */
|
||||||
|
|
||||||
.sidebar-item__link {
|
.sidebar-item__link {
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -22,24 +22,41 @@ class SidebarItem extends PureComponent {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static get defaultProps() {
|
||||||
|
return {
|
||||||
|
isSelected: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
renderContent() {
|
renderContent() {
|
||||||
const { children, to } = this.props;
|
const { children, to } = this.props;
|
||||||
|
|
||||||
if (to) {
|
if (to) {
|
||||||
return Link(
|
const isExternalUrl = /^http/.test(to);
|
||||||
{
|
|
||||||
className: "sidebar-item__link js-sidebar-link",
|
return isExternalUrl
|
||||||
to,
|
? dom.a(
|
||||||
},
|
{
|
||||||
children
|
className: "sidebar-item__link",
|
||||||
);
|
href: to,
|
||||||
|
target: "_blank",
|
||||||
|
},
|
||||||
|
children,
|
||||||
|
)
|
||||||
|
: Link(
|
||||||
|
{
|
||||||
|
className: "sidebar-item__link js-sidebar-link",
|
||||||
|
to,
|
||||||
|
},
|
||||||
|
children,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return children;
|
return children;
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {className, isSelected, to } = this.props;
|
const { className, isSelected, to } = this.props;
|
||||||
|
|
||||||
return dom.li(
|
return dom.li(
|
||||||
{
|
{
|
||||||
|
@ -11,15 +11,25 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
.sidebar-runtime-item__container {
|
.sidebar-runtime-item__container {
|
||||||
font-size: 0.8em;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-column-gap: var(--base-unit);
|
grid-column-gap: var(--base-unit);
|
||||||
grid-template-columns: calc(var(--base-unit) * 6) 1fr auto;
|
grid-template-columns: calc(var(--base-unit) * 6) 1fr auto;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
font-size: var(--body-20-font-size);
|
||||||
|
font-weight: var(--body-20-font-weight);
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-runtime-item__icon {
|
.sidebar-runtime-item__icon {
|
||||||
fill: currentColor;
|
fill: currentColor;
|
||||||
-moz-context-properties: fill;
|
-moz-context-properties: fill;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sidebar-runtime-item__runtime {
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-runtime-item__runtime__details {
|
||||||
|
font-size: var(--caption-10-font-size);
|
||||||
|
font-weight: var(--caption-10-font-weight);
|
||||||
|
}
|
||||||
|
@ -57,29 +57,47 @@ class SidebarRuntimeItem extends PureComponent {
|
|||||||
const displayName = isUnknown ?
|
const displayName = isUnknown ?
|
||||||
getString("about-debugging-sidebar-runtime-item-waiting-for-runtime") : name;
|
getString("about-debugging-sidebar-runtime-item-waiting-for-runtime") : name;
|
||||||
|
|
||||||
const titleLocalizationId = deviceName ?
|
const localizationId = deviceName
|
||||||
"about-debugging-sidebar-runtime-item-name" :
|
? "about-debugging-sidebar-runtime-item-name"
|
||||||
"about-debugging-sidebar-runtime-item-name-no-device";
|
: "about-debugging-sidebar-runtime-item-name-no-device";
|
||||||
|
|
||||||
|
const className = "ellipsis-text sidebar-runtime-item__runtime";
|
||||||
|
|
||||||
|
function renderWithDevice() {
|
||||||
|
return dom.span(
|
||||||
|
{
|
||||||
|
className,
|
||||||
|
title: localizationId,
|
||||||
|
},
|
||||||
|
deviceName,
|
||||||
|
dom.br({}),
|
||||||
|
dom.span(
|
||||||
|
{
|
||||||
|
className: "sidebar-runtime-item__runtime__details",
|
||||||
|
},
|
||||||
|
displayName,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderNoDevice() {
|
||||||
|
return dom.span(
|
||||||
|
{
|
||||||
|
className,
|
||||||
|
title: localizationId,
|
||||||
|
},
|
||||||
|
displayName,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return Localized(
|
return Localized(
|
||||||
{
|
{
|
||||||
id: titleLocalizationId,
|
id: localizationId,
|
||||||
attrs: { title: true },
|
attrs: { title: true },
|
||||||
$deviceName: deviceName,
|
$deviceName: deviceName,
|
||||||
$displayName: displayName,
|
$displayName: displayName,
|
||||||
},
|
},
|
||||||
dom.span(
|
deviceName ? renderWithDevice() : renderNoDevice(),
|
||||||
{
|
|
||||||
className: "ellipsis-text",
|
|
||||||
title: titleLocalizationId,
|
|
||||||
},
|
|
||||||
displayName,
|
|
||||||
// If a deviceName is available, display it on a separate line.
|
|
||||||
...(deviceName ? [
|
|
||||||
dom.br({}),
|
|
||||||
deviceName,
|
|
||||||
] : []),
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,10 +117,11 @@ class SidebarRuntimeItem extends PureComponent {
|
|||||||
|
|
||||||
return SidebarItem(
|
return SidebarItem(
|
||||||
{
|
{
|
||||||
|
className: "sidebar-item--tall",
|
||||||
isSelected,
|
isSelected,
|
||||||
to: isConnected ? `/runtime/${encodeURIComponent(runtimeId)}` : null,
|
to: isConnected ? `/runtime/${encodeURIComponent(runtimeId)}` : null,
|
||||||
},
|
},
|
||||||
dom.div(
|
dom.section(
|
||||||
{
|
{
|
||||||
className: "sidebar-runtime-item__container",
|
className: "sidebar-runtime-item__container",
|
||||||
},
|
},
|
||||||
|
@ -34,7 +34,7 @@ add_task(async function() {
|
|||||||
await waitUntil(() => !usbRuntimeSidebarItem.querySelector(".js-connect-button"));
|
await waitUntil(() => !usbRuntimeSidebarItem.querySelector(".js-connect-button"));
|
||||||
|
|
||||||
info("Check whether the label of item is updated after connecting");
|
info("Check whether the label of item is updated after connecting");
|
||||||
ok(usbRuntimeSidebarItem.textContent.startsWith(RUNTIME_NAME), "Label of item updated");
|
ok(usbRuntimeSidebarItem.textContent.includes(RUNTIME_NAME), "Label of item updated");
|
||||||
|
|
||||||
info("Remove all USB runtimes");
|
info("Remove all USB runtimes");
|
||||||
mocks.removeUSBRuntime(RUNTIME_ID);
|
mocks.removeUSBRuntime(RUNTIME_ID);
|
||||||
|
10
devtools/client/aboutdebugging-new/test/jest/.eslintrc.js
Normal file
10
devtools/client/aboutdebugging-new/test/jest/.eslintrc.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
"env": {
|
||||||
|
"jest": true,
|
||||||
|
},
|
||||||
|
};
|
22
devtools/client/aboutdebugging-new/test/jest/README.md
Normal file
22
devtools/client/aboutdebugging-new/test/jest/README.md
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# Jest Tests for devtools/client/aboutdebugging-new
|
||||||
|
|
||||||
|
## About
|
||||||
|
|
||||||
|
DevTools React components can be tested using [jest](https://jestjs.io/). Jest allows to test our UI components in isolation and complement our end to end mochitests.
|
||||||
|
|
||||||
|
## Run locally
|
||||||
|
|
||||||
|
We use yarn for dependency management. To run the tests locally:
|
||||||
|
```
|
||||||
|
cd devtools/client/shared/aboutdebugging-new/test/jest
|
||||||
|
yarn && yarn test
|
||||||
|
```
|
||||||
|
|
||||||
|
## Run on try
|
||||||
|
|
||||||
|
The tests run on try on linux64 platforms. The complete name of try job is `devtools-tests`. In treeherder, they will show up as `node(devtools)`.
|
||||||
|
|
||||||
|
Adding the tests to a try push depends on the try selector you are using.
|
||||||
|
- try fuzzy: look for the job named `source-test-node-devtools-tests`
|
||||||
|
|
||||||
|
The configuration file for try can be found at `taskcluster/ci/source-test/node.yml`
|
@ -0,0 +1,19 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`Message component renders the expected snapshot for INFO level 1`] = `
|
||||||
|
<aside
|
||||||
|
className="message message--level-info js-message some-classname"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
className="message__icon"
|
||||||
|
src="chrome://devtools/skin/images/aboutdebugging-information.svg"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
className="message__body"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
Message content
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
`;
|
@ -0,0 +1,27 @@
|
|||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for the shared/Message component.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const renderer = require("react-test-renderer");
|
||||||
|
const React = require("devtools/client/shared/vendor/react");
|
||||||
|
const dom = require("devtools/client/shared/vendor/react-dom-factories");
|
||||||
|
|
||||||
|
const { MESSAGE_LEVEL } = require("devtools/client/aboutdebugging-new/src/constants");
|
||||||
|
|
||||||
|
const Message = React.createFactory(require("devtools/client/aboutdebugging-new/src/components/shared/Message"));
|
||||||
|
|
||||||
|
describe("Message component", () => {
|
||||||
|
it("renders the expected snapshot for INFO level", () => {
|
||||||
|
const message = renderer.create(Message({
|
||||||
|
children: dom.div({}, "Message content"),
|
||||||
|
className: "some-classname",
|
||||||
|
level: MESSAGE_LEVEL.INFO,
|
||||||
|
}));
|
||||||
|
expect(message.toJSON()).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
14
devtools/client/aboutdebugging-new/test/jest/jest.config.js
Normal file
14
devtools/client/aboutdebugging-new/test/jest/jest.config.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/* global __dirname */
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
verbose: true,
|
||||||
|
moduleNameMapper: {
|
||||||
|
// Map all require("devtools/...") to the real devtools root.
|
||||||
|
"^devtools\\/(.*)": `${__dirname}/../../../../$1`,
|
||||||
|
},
|
||||||
|
};
|
17
devtools/client/aboutdebugging-new/test/jest/package.json
Normal file
17
devtools/client/aboutdebugging-new/test/jest/package.json
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "devtools-client-framework-tests",
|
||||||
|
"license": "MPL-2.0",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.9.4"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "jest"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"jest": "^23.0.0",
|
||||||
|
"react-test-renderer": "16.4.1",
|
||||||
|
"react": "16.4.1",
|
||||||
|
"react-dom": "16.4.1"
|
||||||
|
}
|
||||||
|
}
|
3738
devtools/client/aboutdebugging-new/test/jest/yarn.lock
Normal file
3738
devtools/client/aboutdebugging-new/test/jest/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
@ -34,6 +34,14 @@ async function mapLocations(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Filter out positions, that are not in the original source Id
|
||||||
|
function filterBySource(positions, sourceId) {
|
||||||
|
if (!isOriginalId(sourceId)) {
|
||||||
|
return positions;
|
||||||
|
}
|
||||||
|
return positions.filter(position => position.location.sourceId == sourceId);
|
||||||
|
}
|
||||||
|
|
||||||
function filterByUniqLocation(positions: MappedLocation[]) {
|
function filterByUniqLocation(positions: MappedLocation[]) {
|
||||||
return uniqBy(positions, ({ location }) => makeBreakpointId(location));
|
return uniqBy(positions, ({ location }) => makeBreakpointId(location));
|
||||||
}
|
}
|
||||||
@ -96,6 +104,8 @@ async function _setBreakpointPositions(sourceId, thunkArgs) {
|
|||||||
|
|
||||||
let positions = convertToList(results, generatedSource);
|
let positions = convertToList(results, generatedSource);
|
||||||
positions = await mapLocations(positions, thunkArgs);
|
positions = await mapLocations(positions, thunkArgs);
|
||||||
|
|
||||||
|
positions = filterBySource(positions, sourceId);
|
||||||
positions = filterByUniqLocation(positions);
|
positions = filterByUniqLocation(positions);
|
||||||
|
|
||||||
const source = getSource(getState(), sourceId);
|
const source = getSource(getState(), sourceId);
|
||||||
|
@ -44,7 +44,7 @@ export function generateBreakpoint(
|
|||||||
text: "",
|
text: "",
|
||||||
location: {
|
location: {
|
||||||
sourceUrl: `http://localhost:8000/examples/${filename}`,
|
sourceUrl: `http://localhost:8000/examples/${filename}`,
|
||||||
sourceId: `${filename}/originalSource`,
|
sourceId: `${filename}`,
|
||||||
line,
|
line,
|
||||||
column
|
column
|
||||||
},
|
},
|
||||||
|
@ -30,19 +30,13 @@ jest.mock("../../utils/prefs", () => ({
|
|||||||
asyncStore: {
|
asyncStore: {
|
||||||
pendingBreakpoints: {}
|
pendingBreakpoints: {}
|
||||||
},
|
},
|
||||||
features: {
|
|
||||||
replay: false
|
|
||||||
},
|
|
||||||
clear: jest.fn()
|
clear: jest.fn()
|
||||||
}));
|
}));
|
||||||
|
|
||||||
import "../sources/loadSourceText";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
createStore,
|
createStore,
|
||||||
selectors,
|
selectors,
|
||||||
actions,
|
actions,
|
||||||
makeOriginalSource,
|
|
||||||
makeSource,
|
makeSource,
|
||||||
waitForState
|
waitForState
|
||||||
} from "../../utils/test-head";
|
} from "../../utils/test-head";
|
||||||
@ -81,7 +75,7 @@ describe("when adding breakpoints", () => {
|
|||||||
mockSourceMaps()
|
mockSourceMaps()
|
||||||
);
|
);
|
||||||
|
|
||||||
const source = makeOriginalSource("foo.js");
|
const source = makeSource("foo.js");
|
||||||
await dispatch(actions.newSource(source));
|
await dispatch(actions.newSource(source));
|
||||||
await dispatch(actions.newSource(makeSource("foo.js")));
|
await dispatch(actions.newSource(makeSource("foo.js")));
|
||||||
await dispatch(actions.loadSourceText(source));
|
await dispatch(actions.loadSourceText(source));
|
||||||
@ -116,8 +110,8 @@ describe("when adding breakpoints", () => {
|
|||||||
mockSourceMaps()
|
mockSourceMaps()
|
||||||
);
|
);
|
||||||
|
|
||||||
const source1 = makeOriginalSource("foo");
|
const source1 = makeSource("foo");
|
||||||
const source2 = makeOriginalSource("foo2");
|
const source2 = makeSource("foo2");
|
||||||
|
|
||||||
await dispatch(actions.newSource(makeSource("foo")));
|
await dispatch(actions.newSource(makeSource("foo")));
|
||||||
await dispatch(actions.newSource(makeSource("foo2")));
|
await dispatch(actions.newSource(makeSource("foo2")));
|
||||||
@ -147,7 +141,7 @@ describe("when adding breakpoints", () => {
|
|||||||
mockSourceMaps()
|
mockSourceMaps()
|
||||||
);
|
);
|
||||||
|
|
||||||
const source = makeOriginalSource("foo");
|
const source = makeSource("foo");
|
||||||
await dispatch(actions.newSource(makeSource("foo")));
|
await dispatch(actions.newSource(makeSource("foo")));
|
||||||
await dispatch(actions.newSource(source));
|
await dispatch(actions.newSource(source));
|
||||||
await dispatch(actions.loadSourceText(source));
|
await dispatch(actions.loadSourceText(source));
|
||||||
@ -170,8 +164,8 @@ describe("when adding breakpoints", () => {
|
|||||||
await dispatch(actions.newSource(makeSource("foo")));
|
await dispatch(actions.newSource(makeSource("foo")));
|
||||||
await dispatch(actions.newSource(makeSource("foo2")));
|
await dispatch(actions.newSource(makeSource("foo2")));
|
||||||
|
|
||||||
const source1 = makeOriginalSource("foo");
|
const source1 = makeSource("foo");
|
||||||
const source2 = makeOriginalSource("foo2");
|
const source2 = makeSource("foo2");
|
||||||
|
|
||||||
await dispatch(actions.newSource(source1));
|
await dispatch(actions.newSource(source1));
|
||||||
await dispatch(actions.newSource(source2));
|
await dispatch(actions.newSource(source2));
|
||||||
@ -200,7 +194,7 @@ describe("when changing an existing breakpoint", () => {
|
|||||||
const bp = generateBreakpoint("foo");
|
const bp = generateBreakpoint("foo");
|
||||||
const id = makePendingLocationId(bp.location);
|
const id = makePendingLocationId(bp.location);
|
||||||
|
|
||||||
const source = makeOriginalSource("foo");
|
const source = makeSource("foo");
|
||||||
await dispatch(actions.newSource(source));
|
await dispatch(actions.newSource(source));
|
||||||
await dispatch(actions.newSource(makeSource("foo")));
|
await dispatch(actions.newSource(makeSource("foo")));
|
||||||
await dispatch(actions.loadSourceText(source));
|
await dispatch(actions.loadSourceText(source));
|
||||||
@ -225,7 +219,7 @@ describe("when changing an existing breakpoint", () => {
|
|||||||
|
|
||||||
await dispatch(actions.newSource(makeSource("foo")));
|
await dispatch(actions.newSource(makeSource("foo")));
|
||||||
|
|
||||||
const source = makeOriginalSource("foo");
|
const source = makeSource("foo");
|
||||||
await dispatch(actions.newSource(source));
|
await dispatch(actions.newSource(source));
|
||||||
await dispatch(actions.loadSourceText(source));
|
await dispatch(actions.loadSourceText(source));
|
||||||
|
|
||||||
@ -244,7 +238,7 @@ describe("when changing an existing breakpoint", () => {
|
|||||||
);
|
);
|
||||||
const bp = generateBreakpoint("foo.js");
|
const bp = generateBreakpoint("foo.js");
|
||||||
|
|
||||||
const source = makeOriginalSource("foo.js");
|
const source = makeSource("foo.js");
|
||||||
await dispatch(actions.newSource(source));
|
await dispatch(actions.newSource(source));
|
||||||
await dispatch(actions.newSource(makeSource("foo.js")));
|
await dispatch(actions.newSource(makeSource("foo.js")));
|
||||||
await dispatch(actions.loadSourceText(source));
|
await dispatch(actions.loadSourceText(source));
|
||||||
@ -282,7 +276,7 @@ describe("initializing when pending breakpoints exist in prefs", () => {
|
|||||||
|
|
||||||
await dispatch(actions.newSource(makeSource("bar.js")));
|
await dispatch(actions.newSource(makeSource("bar.js")));
|
||||||
|
|
||||||
const source = makeOriginalSource("bar.js");
|
const source = makeSource("bar.js");
|
||||||
await dispatch(actions.newSource(source));
|
await dispatch(actions.newSource(source));
|
||||||
await dispatch(actions.loadSourceText(source));
|
await dispatch(actions.loadSourceText(source));
|
||||||
await dispatch(actions.addBreakpoint(bar.location));
|
await dispatch(actions.addBreakpoint(bar.location));
|
||||||
@ -299,7 +293,7 @@ describe("initializing when pending breakpoints exist in prefs", () => {
|
|||||||
);
|
);
|
||||||
const bp = generateBreakpoint("foo.js");
|
const bp = generateBreakpoint("foo.js");
|
||||||
|
|
||||||
const source = makeOriginalSource("foo.js");
|
const source = makeSource("foo.js");
|
||||||
await dispatch(actions.newSource(source));
|
await dispatch(actions.newSource(source));
|
||||||
await dispatch(actions.newSource(makeSource("foo.js")));
|
await dispatch(actions.newSource(makeSource("foo.js")));
|
||||||
await dispatch(actions.loadSourceText(source));
|
await dispatch(actions.loadSourceText(source));
|
||||||
@ -320,7 +314,7 @@ describe("initializing with disabled pending breakpoints in prefs", () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const { getState, dispatch } = store;
|
const { getState, dispatch } = store;
|
||||||
const source = makeOriginalSource("bar.js");
|
const source = makeSource("bar.js");
|
||||||
|
|
||||||
await dispatch(actions.newSource(makeSource("bar.js")));
|
await dispatch(actions.newSource(makeSource("bar.js")));
|
||||||
await dispatch(actions.newSource(source));
|
await dispatch(actions.newSource(source));
|
||||||
@ -356,7 +350,7 @@ describe("adding sources", () => {
|
|||||||
|
|
||||||
expect(selectors.getBreakpointCount(getState())).toEqual(0);
|
expect(selectors.getBreakpointCount(getState())).toEqual(0);
|
||||||
|
|
||||||
const source = makeOriginalSource("bar.js");
|
const source = makeSource("bar.js");
|
||||||
|
|
||||||
await dispatch(actions.newSource(makeSource("bar.js")));
|
await dispatch(actions.newSource(makeSource("bar.js")));
|
||||||
await dispatch(actions.newSource(source));
|
await dispatch(actions.newSource(source));
|
||||||
@ -368,7 +362,7 @@ describe("adding sources", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("corresponding breakpoints are added to the original source", async () => {
|
it("corresponding breakpoints are added to the original source", async () => {
|
||||||
const source = makeOriginalSource("bar.js", { sourceMapURL: "foo" });
|
const source = makeSource("bar.js", { sourceMapURL: "foo" });
|
||||||
const store = createStore(mockClient({ "5": [2] }), loadInitialState(), {
|
const store = createStore(mockClient({ "5": [2] }), loadInitialState(), {
|
||||||
getOriginalURLs: async () => [source.url],
|
getOriginalURLs: async () => [source.url],
|
||||||
getOriginalSourceText: async () => ({ source: "" }),
|
getOriginalSourceText: async () => ({ source: "" }),
|
||||||
@ -406,8 +400,8 @@ describe("adding sources", () => {
|
|||||||
|
|
||||||
expect(selectors.getBreakpointCount(getState())).toEqual(0);
|
expect(selectors.getBreakpointCount(getState())).toEqual(0);
|
||||||
|
|
||||||
const source1 = makeOriginalSource("bar.js");
|
const source1 = makeSource("bar.js");
|
||||||
const source2 = makeOriginalSource("foo.js");
|
const source2 = makeSource("foo.js");
|
||||||
await dispatch(actions.newSource(makeSource("bar.js")));
|
await dispatch(actions.newSource(makeSource("bar.js")));
|
||||||
await dispatch(actions.newSource(makeSource("foo.js")));
|
await dispatch(actions.newSource(makeSource("foo.js")));
|
||||||
await dispatch(actions.newSources([source1, source2]));
|
await dispatch(actions.newSources([source1, source2]));
|
||||||
|
@ -70,7 +70,7 @@ class DebugTargetInfo extends PureComponent {
|
|||||||
|
|
||||||
return dom.span(
|
return dom.span(
|
||||||
{
|
{
|
||||||
className: "iconized-label",
|
className: "iconized-label js-connection-info",
|
||||||
},
|
},
|
||||||
dom.img({ src: image, alt: `${connectionType} icon`}),
|
dom.img({ src: image, alt: `${connectionType} icon`}),
|
||||||
this.props.L10N.getStr(l10nId),
|
this.props.L10N.getStr(l10nId),
|
||||||
@ -108,7 +108,7 @@ class DebugTargetInfo extends PureComponent {
|
|||||||
className: "iconized-label",
|
className: "iconized-label",
|
||||||
},
|
},
|
||||||
dom.img({ src: favicon, alt: "favicon"}),
|
dom.img({ src: favicon, alt: "favicon"}),
|
||||||
title ? dom.b({ className: "devtools-ellipsis-text"}, title) : null,
|
title ? dom.b({ className: "devtools-ellipsis-text js-target-title"}, title) : null,
|
||||||
dom.span({ className: "devtools-ellipsis-text" }, url),
|
dom.span({ className: "devtools-ellipsis-text" }, url),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
10
devtools/client/framework/test/jest/.eslintrc.js
Normal file
10
devtools/client/framework/test/jest/.eslintrc.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
"env": {
|
||||||
|
"jest": true,
|
||||||
|
},
|
||||||
|
};
|
22
devtools/client/framework/test/jest/README.md
Normal file
22
devtools/client/framework/test/jest/README.md
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# Jest Tests for devtools/client/framework
|
||||||
|
|
||||||
|
## About
|
||||||
|
|
||||||
|
DevTools React components can be tested using [jest](https://jestjs.io/). Jest allows to test our UI components in isolation and complement our end to end mochitests.
|
||||||
|
|
||||||
|
## Run locally
|
||||||
|
|
||||||
|
We use yarn for dependency management. To run the tests locally:
|
||||||
|
```
|
||||||
|
cd devtools/client/shared/framework/test/jest
|
||||||
|
yarn && yarn test
|
||||||
|
```
|
||||||
|
|
||||||
|
## Run on try
|
||||||
|
|
||||||
|
The tests run on try on linux64 platforms. The complete name of the try job is `devtools-tests`. In treeherder, they will show up as `node(devtools)`.
|
||||||
|
|
||||||
|
Adding the tests to a try push depends on the try selector you are using.
|
||||||
|
- try fuzzy: look for the job named `source-test-node-devtools-tests`
|
||||||
|
|
||||||
|
The configuration file for try can be found at `taskcluster/ci/source-test/node.yml`
|
@ -0,0 +1,130 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`DebugTargetInfo component renders the expected snapshot for This Firefox target 1`] = `
|
||||||
|
<header
|
||||||
|
className="debug-target-info"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className="iconized-label"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
className="channel-icon"
|
||||||
|
src="chrome://devtools/skin/images/aboutdebugging-firefox-release.svg"
|
||||||
|
/>
|
||||||
|
<b
|
||||||
|
className="devtools-ellipsis-text"
|
||||||
|
>
|
||||||
|
toolbox.debugTargetInfo.runtimeLabel.thisFirefox-1.0.0
|
||||||
|
</b>
|
||||||
|
<span
|
||||||
|
className="devtools-ellipsis-text"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
className="iconized-label"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
alt="favicon"
|
||||||
|
src="chrome://devtools/skin/images/aboutdebugging-globe-icon.svg"
|
||||||
|
/>
|
||||||
|
<b
|
||||||
|
className="devtools-ellipsis-text js-target-title"
|
||||||
|
>
|
||||||
|
Test Tab Name
|
||||||
|
</b>
|
||||||
|
<span
|
||||||
|
className="devtools-ellipsis-text"
|
||||||
|
>
|
||||||
|
http://some.target/url
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</header>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`DebugTargetInfo component renders the expected snapshot for USB Release target 1`] = `
|
||||||
|
<header
|
||||||
|
className="debug-target-info"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className="iconized-label js-connection-info"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
alt="usb icon"
|
||||||
|
src="chrome://devtools/skin/images/aboutdebugging-usb-icon.svg"
|
||||||
|
/>
|
||||||
|
toolbox.debugTargetInfo.connection.usb
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
className="iconized-label"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
className="channel-icon"
|
||||||
|
src="chrome://devtools/skin/images/aboutdebugging-firefox-release.svg"
|
||||||
|
/>
|
||||||
|
<b
|
||||||
|
className="devtools-ellipsis-text"
|
||||||
|
>
|
||||||
|
toolbox.debugTargetInfo.runtimeLabel-usbRuntimeBrandName-1.0.0
|
||||||
|
</b>
|
||||||
|
<span
|
||||||
|
className="devtools-ellipsis-text"
|
||||||
|
>
|
||||||
|
usbDeviceName
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
className="iconized-label"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
alt="favicon"
|
||||||
|
src="chrome://devtools/skin/images/aboutdebugging-globe-icon.svg"
|
||||||
|
/>
|
||||||
|
<b
|
||||||
|
className="devtools-ellipsis-text js-target-title"
|
||||||
|
>
|
||||||
|
Test Tab Name
|
||||||
|
</b>
|
||||||
|
<span
|
||||||
|
className="devtools-ellipsis-text"
|
||||||
|
>
|
||||||
|
http://some.target/url
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</header>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`DebugTargetInfo component renders the expected snapshot for a Toolbox with an unnamed target 1`] = `
|
||||||
|
<header
|
||||||
|
className="debug-target-info"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className="iconized-label"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
className="channel-icon"
|
||||||
|
src="chrome://devtools/skin/images/aboutdebugging-firefox-release.svg"
|
||||||
|
/>
|
||||||
|
<b
|
||||||
|
className="devtools-ellipsis-text"
|
||||||
|
>
|
||||||
|
toolbox.debugTargetInfo.runtimeLabel.thisFirefox-1.0.0
|
||||||
|
</b>
|
||||||
|
<span
|
||||||
|
className="devtools-ellipsis-text"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
className="iconized-label"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
alt="favicon"
|
||||||
|
src="chrome://devtools/skin/images/aboutdebugging-globe-icon.svg"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
className="devtools-ellipsis-text"
|
||||||
|
>
|
||||||
|
http://some.target/without/a/name
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</header>
|
||||||
|
`;
|
@ -0,0 +1,110 @@
|
|||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for the DebugTargetInfo component.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const renderer = require("react-test-renderer");
|
||||||
|
const React = require("devtools/client/shared/vendor/react");
|
||||||
|
const DebugTargetInfo = React.createFactory(require("devtools/client/framework/components/DebugTargetInfo"));
|
||||||
|
const { CONNECTION_TYPES } = require("devtools/client/shared/remote-debugging/remote-client-manager");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stub for the L10N property expected by the DebugTargetInfo component.
|
||||||
|
*/
|
||||||
|
const stubL10N = {
|
||||||
|
getStr: id => id,
|
||||||
|
getFormatStr: (id, ...args) => [id, ...args].join("-"),
|
||||||
|
};
|
||||||
|
|
||||||
|
const findByClassName = (testInstance, className) => {
|
||||||
|
return testInstance.findAll(node => {
|
||||||
|
return node.props.className && node.props.className.includes(className);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const TEST_TOOLBOX = {
|
||||||
|
target: {
|
||||||
|
name: "Test Tab Name",
|
||||||
|
url: "http://some.target/url",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const TEST_TOOLBOX_NO_NAME = {
|
||||||
|
target: {
|
||||||
|
url: "http://some.target/without/a/name",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const USB_DEVICE_DESCRIPTION = {
|
||||||
|
brandName: "usbRuntimeBrandName",
|
||||||
|
connectionType: CONNECTION_TYPES.USB,
|
||||||
|
channel: "release",
|
||||||
|
deviceName: "usbDeviceName",
|
||||||
|
version: "1.0.0",
|
||||||
|
};
|
||||||
|
|
||||||
|
const THIS_FIREFOX_DEVICE_DESCRIPTION = {
|
||||||
|
brandName: "thisFirefoxRuntimeBrandName",
|
||||||
|
connectionType: CONNECTION_TYPES.THIS_FIREFOX,
|
||||||
|
channel: "release",
|
||||||
|
version: "1.0.0",
|
||||||
|
};
|
||||||
|
|
||||||
|
const USB_TARGET_INFO = DebugTargetInfo({
|
||||||
|
deviceDescription: USB_DEVICE_DESCRIPTION,
|
||||||
|
toolbox: TEST_TOOLBOX,
|
||||||
|
L10N: stubL10N,
|
||||||
|
});
|
||||||
|
|
||||||
|
const THIS_FIREFOX_TARGET_INFO = DebugTargetInfo({
|
||||||
|
deviceDescription: THIS_FIREFOX_DEVICE_DESCRIPTION,
|
||||||
|
toolbox: TEST_TOOLBOX,
|
||||||
|
L10N: stubL10N,
|
||||||
|
});
|
||||||
|
|
||||||
|
const THIS_FIREFOX_NO_NAME_TARGET_INFO = DebugTargetInfo({
|
||||||
|
deviceDescription: THIS_FIREFOX_DEVICE_DESCRIPTION,
|
||||||
|
toolbox: TEST_TOOLBOX_NO_NAME,
|
||||||
|
L10N: stubL10N,
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("DebugTargetInfo component", () => {
|
||||||
|
it("displays connection info for USB Release target", () => {
|
||||||
|
const targetInfo = renderer.create(USB_TARGET_INFO);
|
||||||
|
expect(findByClassName(targetInfo.root, "js-connection-info").length).toEqual(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders the expected snapshot for USB Release target", () => {
|
||||||
|
const targetInfo = renderer.create(USB_TARGET_INFO);
|
||||||
|
expect(targetInfo.toJSON()).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("hides the connection info for This Firefox target", () => {
|
||||||
|
const targetInfo = renderer.create(THIS_FIREFOX_TARGET_INFO);
|
||||||
|
expect(findByClassName(targetInfo.root, "js-connection-info").length).toEqual(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("displays the target title if the target of the Toolbox has a name", () => {
|
||||||
|
const targetInfo = renderer.create(THIS_FIREFOX_TARGET_INFO);
|
||||||
|
expect(findByClassName(targetInfo.root, "js-target-title").length).toEqual(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders the expected snapshot for This Firefox target", () => {
|
||||||
|
const targetInfo = renderer.create(THIS_FIREFOX_TARGET_INFO);
|
||||||
|
expect(targetInfo.toJSON()).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("doesn't display the target title if the target of the Toolbox has no name", () => {
|
||||||
|
const targetInfo = renderer.create(THIS_FIREFOX_NO_NAME_TARGET_INFO);
|
||||||
|
expect(findByClassName(targetInfo.root, "js-target-title").length).toEqual(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders the expected snapshot for a Toolbox with an unnamed target", () => {
|
||||||
|
const targetInfo = renderer.create(THIS_FIREFOX_NO_NAME_TARGET_INFO);
|
||||||
|
expect(targetInfo.toJSON()).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
14
devtools/client/framework/test/jest/jest.config.js
Normal file
14
devtools/client/framework/test/jest/jest.config.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/* global __dirname */
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
verbose: true,
|
||||||
|
moduleNameMapper: {
|
||||||
|
// Map all require("devtools/...") to the real devtools root.
|
||||||
|
"^devtools\\/(.*)": `${__dirname}/../../../../$1`,
|
||||||
|
},
|
||||||
|
};
|
17
devtools/client/framework/test/jest/package.json
Normal file
17
devtools/client/framework/test/jest/package.json
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "devtools-client-framework-tests",
|
||||||
|
"license": "MPL-2.0",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.9.4"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "jest"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"jest": "^23.0.0",
|
||||||
|
"react-test-renderer": "16.4.1",
|
||||||
|
"react": "16.4.1",
|
||||||
|
"react-dom": "16.4.1"
|
||||||
|
}
|
||||||
|
}
|
3224
devtools/client/framework/test/jest/yarn.lock
Normal file
3224
devtools/client/framework/test/jest/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
@ -19,7 +19,6 @@
|
|||||||
<link rel="stylesheet" href="chrome://devtools/skin/layout.css"/>
|
<link rel="stylesheet" href="chrome://devtools/skin/layout.css"/>
|
||||||
<link rel="stylesheet" href="chrome://devtools/skin/animation.css"/>
|
<link rel="stylesheet" href="chrome://devtools/skin/animation.css"/>
|
||||||
<link rel="stylesheet" href="resource://devtools/client/shared/components/tabs/Tabs.css"/>
|
<link rel="stylesheet" href="resource://devtools/client/shared/components/tabs/Tabs.css"/>
|
||||||
<link rel="stylesheet" href="resource://devtools/client/shared/components/tabs/TabBar.css"/>
|
|
||||||
<link rel="stylesheet" href="resource://devtools/client/shared/components/SidebarToggle.css"/>
|
<link rel="stylesheet" href="resource://devtools/client/shared/components/SidebarToggle.css"/>
|
||||||
<link rel="stylesheet" href="resource://devtools/client/inspector/components/InspectorTabPanel.css"/>
|
<link rel="stylesheet" href="resource://devtools/client/inspector/components/InspectorTabPanel.css"/>
|
||||||
<link rel="stylesheet" href="resource://devtools/client/shared/components/splitter/SplitBox.css"/>
|
<link rel="stylesheet" href="resource://devtools/client/shared/components/splitter/SplitBox.css"/>
|
||||||
|
@ -63,6 +63,15 @@ about-debugging-sidebar-runtime-item-name =
|
|||||||
about-debugging-sidebar-runtime-item-name-no-device =
|
about-debugging-sidebar-runtime-item-name-no-device =
|
||||||
.title = { $displayName }
|
.title = { $displayName }
|
||||||
|
|
||||||
|
# Text to show in the footer of the sidebar that links to a help page
|
||||||
|
# (currently: https://developer.mozilla.org/docs/Tools/about:debugging)
|
||||||
|
about-debugging-sidebar-support = Debugging Support
|
||||||
|
|
||||||
|
# Text to show as the ALT attribute of a help icon that accompanies the help about
|
||||||
|
# debugging link in the footer of the sidebar
|
||||||
|
about-debugging-sidebar-support-icon =
|
||||||
|
.alt = Help icon
|
||||||
|
|
||||||
# Text displayed in a sidebar button to refresh the list of USB devices. Clicking on it
|
# Text displayed in a sidebar button to refresh the list of USB devices. Clicking on it
|
||||||
# will attempt to update the list of devices displayed in the sidebar.
|
# will attempt to update the list of devices displayed in the sidebar.
|
||||||
about-debugging-refresh-usb-devices-button = Refresh devices
|
about-debugging-refresh-usb-devices-button = Refresh devices
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
@import "resource://devtools/client/shared/components/splitter/SplitBox.css";
|
@import "resource://devtools/client/shared/components/splitter/SplitBox.css";
|
||||||
@import "resource://devtools/client/shared/components/tree/TreeView.css";
|
@import "resource://devtools/client/shared/components/tree/TreeView.css";
|
||||||
@import "resource://devtools/client/shared/components/tabs/Tabs.css";
|
@import "resource://devtools/client/shared/components/tabs/Tabs.css";
|
||||||
@import "resource://devtools/client/shared/components/tabs/TabBar.css";
|
|
||||||
@import "chrome://devtools/skin/components-frame.css";
|
@import "chrome://devtools/skin/components-frame.css";
|
||||||
@import "chrome://devtools/content/shared/sourceeditor/codemirror/lib/codemirror.css";
|
@import "chrome://devtools/content/shared/sourceeditor/codemirror/lib/codemirror.css";
|
||||||
@import "chrome://devtools/content/shared/sourceeditor/codemirror/addon/dialog/dialog.css";
|
@import "chrome://devtools/content/shared/sourceeditor/codemirror/addon/dialog/dialog.css";
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
@import "resource://devtools/client/shared/components/splitter/SplitBox.css";
|
@import "resource://devtools/client/shared/components/splitter/SplitBox.css";
|
||||||
@import "resource://devtools/client/shared/components/tree/TreeView.css";
|
@import "resource://devtools/client/shared/components/tree/TreeView.css";
|
||||||
@import "resource://devtools/client/shared/components/tabs/Tabs.css";
|
@import "resource://devtools/client/shared/components/tabs/Tabs.css";
|
||||||
@import "resource://devtools/client/shared/components/tabs/TabBar.css";
|
|
||||||
@import "chrome://devtools/skin/components-frame.css";
|
@import "chrome://devtools/skin/components-frame.css";
|
||||||
@import "chrome://devtools/content/shared/sourceeditor/codemirror/lib/codemirror.css";
|
@import "chrome://devtools/content/shared/sourceeditor/codemirror/lib/codemirror.css";
|
||||||
@import "chrome://devtools/content/shared/sourceeditor/codemirror/addon/dialog/dialog.css";
|
@import "chrome://devtools/content/shared/sourceeditor/codemirror/addon/dialog/dialog.css";
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
|
||||||
/* 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/. */
|
|
||||||
|
|
||||||
/* Hides the tab strip in the TabBar */
|
|
||||||
div[hidetabs=true] .tabs .tabs-navigation {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tabs .tabs-navigation {
|
|
||||||
display: flex;
|
|
||||||
line-height: 15px;
|
|
||||||
height: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tabs .tabs-menu-item:first-child {
|
|
||||||
border-inline-start-width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove the outline focusring from tabs-menu-item. */
|
|
||||||
.tabs .tabs-navigation .tabs-menu-item > a:-moz-focusring {
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tabs .tabs-menu-item.is-active {
|
|
||||||
height: 23px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The tab takes entire horizontal space and individual tabs
|
|
||||||
should stretch accordingly. Use flexbox for the behavior.
|
|
||||||
Use also `overflow: hidden` so, 'overflow' and 'underflow'
|
|
||||||
events are fired (it's utilized by the all-tabs-menu). */
|
|
||||||
.tabs .tabs-navigation .tabs-menu {
|
|
||||||
overflow: hidden;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tabs .tabs-navigation .tabs-menu-item {
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tabs .tabs-navigation .tabs-menu-item a {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
@ -12,25 +12,72 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Hides the tab strip in the TabBar */
|
||||||
|
div[hidetabs=true] .tabs .tabs-navigation {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs .tabs-navigation {
|
||||||
|
display: flex;
|
||||||
|
line-height: 15px;
|
||||||
|
height: 24px;
|
||||||
|
position: relative;
|
||||||
|
border-bottom: 1px solid var(--theme-splitter-color);
|
||||||
|
background: var(--theme-tab-toolbar-background);
|
||||||
|
}
|
||||||
|
|
||||||
.tabs .tabs-menu {
|
.tabs .tabs-menu {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The tab takes entire horizontal space and individual tabs
|
||||||
|
should stretch accordingly. Use flexbox for the behavior.
|
||||||
|
Use also `overflow: hidden` so, 'overflow' and 'underflow'
|
||||||
|
events are fired (it's utilized by the all-tabs-menu). */
|
||||||
|
.tabs .tabs-navigation .tabs-menu {
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabs .tabs-menu-item {
|
.tabs .tabs-menu-item {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
color: var(--theme-toolbar-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs .tabs-menu-item.is-active {
|
||||||
|
color: var(--theme-toolbar-selected-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs .tabs-menu-item:hover {
|
||||||
|
background-color: var(--theme-toolbar-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs .tabs-menu-item:hover:active:not(.is-active) {
|
||||||
|
background-color: var(--theme-toolbar-hover-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabs .tabs-menu-item a {
|
.tabs .tabs-menu-item a {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: 4px 8px;
|
padding: 3px 10px;
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
cursor: default;
|
||||||
|
-moz-user-select: none;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove the outline focusring from tabs-menu-item. */
|
||||||
|
.tabs .tabs-navigation .tabs-menu-item > a:-moz-focusring {
|
||||||
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabs .tabs-menu-item .tab-badge {
|
.tabs .tabs-menu-item .tab-badge {
|
||||||
@ -54,11 +101,6 @@
|
|||||||
-moz-user-select: none !important;
|
-moz-user-select: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabs .tabs-menu-item a {
|
|
||||||
cursor: default;
|
|
||||||
-moz-user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make sure panel content takes entire vertical space. */
|
/* Make sure panel content takes entire vertical space. */
|
||||||
.tabs .panels {
|
.tabs .panels {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
@ -69,43 +111,4 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabs .tabs-navigation,
|
|
||||||
.tabs .tabs-navigation {
|
|
||||||
position: relative;
|
|
||||||
border-bottom: 1px solid var(--theme-splitter-color);
|
|
||||||
background: var(--theme-tab-toolbar-background);
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-dark .tabs .tabs-menu-item,
|
|
||||||
.theme-light .tabs .tabs-menu-item {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
color: var(--theme-toolbar-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-dark .tabs .tabs-menu-item.is-active,
|
|
||||||
.theme-light .tabs .tabs-menu-item.is-active {
|
|
||||||
color: var(--theme-toolbar-selected-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-dark .tabs .tabs-menu-item:last-child,
|
|
||||||
.theme-light .tabs .tabs-menu-item:last-child {
|
|
||||||
border-inline-end-width: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-dark .tabs .tabs-menu-item a,
|
|
||||||
.theme-light .tabs .tabs-menu-item a {
|
|
||||||
padding: 3px 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-dark .tabs .tabs-menu-item:hover,
|
|
||||||
.theme-light .tabs .tabs-menu-item:hover {
|
|
||||||
background-color: var(--theme-toolbar-hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-dark .tabs .tabs-menu-item:hover:active:not(.is-active),
|
|
||||||
.theme-light .tabs .tabs-menu-item:hover:active:not(.is-active) {
|
|
||||||
background-color: var(--theme-toolbar-hover-active);
|
|
||||||
}
|
|
@ -5,7 +5,6 @@
|
|||||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
DevToolsModules(
|
DevToolsModules(
|
||||||
'TabBar.css',
|
|
||||||
'TabBar.js',
|
'TabBar.js',
|
||||||
'Tabs.css',
|
'Tabs.css',
|
||||||
'Tabs.js',
|
'Tabs.js',
|
||||||
|
@ -14,7 +14,6 @@ Test all-tabs menu.
|
|||||||
<link rel="stylesheet" type="text/css" href="resource://devtools/client/themes/variables.css">
|
<link rel="stylesheet" type="text/css" href="resource://devtools/client/themes/variables.css">
|
||||||
<link rel="stylesheet" type="text/css" href="resource://devtools/client/themes/common.css">
|
<link rel="stylesheet" type="text/css" href="resource://devtools/client/themes/common.css">
|
||||||
<link rel="stylesheet" type="text/css" href="resource://devtools/client/shared/components/tabs/Tabs.css">
|
<link rel="stylesheet" type="text/css" href="resource://devtools/client/shared/components/tabs/Tabs.css">
|
||||||
<link rel="stylesheet" type="text/css" href="resource://devtools/client/shared/components/tabs/TabBar.css">
|
|
||||||
<link rel="stylesheet" type="text/css" href="resource://devtools/client/inspector/components/side-panel.css">
|
<link rel="stylesheet" type="text/css" href="resource://devtools/client/inspector/components/side-panel.css">
|
||||||
<link rel="stylesheet" type="text/css" href="resource://devtools/client/inspector/components/InspectorTabPanel.css">
|
<link rel="stylesheet" type="text/css" href="resource://devtools/client/inspector/components/InspectorTabPanel.css">
|
||||||
</head>
|
</head>
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
<link rel="stylesheet" href="resource://devtools/client/shared/components/SmartTrace.css"/>
|
<link rel="stylesheet" href="resource://devtools/client/shared/components/SmartTrace.css"/>
|
||||||
<link rel="stylesheet" href="resource://devtools/client/shared/components/reps/reps.css"/>
|
<link rel="stylesheet" href="resource://devtools/client/shared/components/reps/reps.css"/>
|
||||||
<link rel="stylesheet" href="resource://devtools/client/shared/components/tabs/Tabs.css"/>
|
<link rel="stylesheet" href="resource://devtools/client/shared/components/tabs/Tabs.css"/>
|
||||||
<link rel="stylesheet" href="resource://devtools/client/shared/components/tabs/TabBar.css"/>
|
|
||||||
<link rel="stylesheet" href="resource://devtools/client/shared/components/NotificationBox.css"/>
|
<link rel="stylesheet" href="resource://devtools/client/shared/components/NotificationBox.css"/>
|
||||||
<link rel="stylesheet" href="chrome://devtools/content/netmonitor/src/assets/styles/httpi.css"/>
|
<link rel="stylesheet" href="chrome://devtools/content/netmonitor/src/assets/styles/httpi.css"/>
|
||||||
<link rel="stylesheet" href="resource://devtools/client/webconsole/components/ReverseSearchInput.css"/>
|
<link rel="stylesheet" href="resource://devtools/client/webconsole/components/ReverseSearchInput.css"/>
|
||||||
|
@ -389,13 +389,13 @@ const AccessibleActor = ActorClassWithSpec(accessibleSpec, {
|
|||||||
|
|
||||||
const { DOMNode: rawNode } = this.rawAccessible;
|
const { DOMNode: rawNode } = this.rawAccessible;
|
||||||
const win = rawNode.ownerGlobal;
|
const win = rawNode.ownerGlobal;
|
||||||
this.walker.loadTransitionDisablingStyleSheet(win);
|
this.walker.clearStyles(win);
|
||||||
const contrastRatio = await getContrastRatioFor(rawNode.parentNode, {
|
const contrastRatio = await getContrastRatioFor(rawNode.parentNode, {
|
||||||
bounds: this.bounds,
|
bounds: this.bounds,
|
||||||
win,
|
win,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.walker.removeTransitionDisablingStyleSheet(win);
|
this.walker.restoreStyles(win);
|
||||||
|
|
||||||
return contrastRatio;
|
return contrastRatio;
|
||||||
},
|
},
|
||||||
@ -407,16 +407,27 @@ const AccessibleActor = ActorClassWithSpec(accessibleSpec, {
|
|||||||
* Audit results for the accessible object.
|
* Audit results for the accessible object.
|
||||||
*/
|
*/
|
||||||
async audit() {
|
async audit() {
|
||||||
// More audit steps will be added here in the near future. In addition to colour
|
if (this._auditing) {
|
||||||
// contrast ratio we will add autits for to the missing names, invalid states, etc.
|
return this._auditing;
|
||||||
// (For example see bug 1518808).
|
}
|
||||||
const [ contrastRatio ] = await Promise.all([
|
|
||||||
this._getContrastRatio(),
|
|
||||||
]);
|
|
||||||
|
|
||||||
return this.isDefunct ? null : {
|
// More audit steps will be added here in the near future. In addition to
|
||||||
|
// colour contrast ratio we will add autits for to the missing names,
|
||||||
|
// invalid states, etc. (For example see bug 1518808).
|
||||||
|
this._auditing = Promise.all([
|
||||||
|
this._getContrastRatio(),
|
||||||
|
]).then(([
|
||||||
contrastRatio,
|
contrastRatio,
|
||||||
};
|
]) => {
|
||||||
|
const audit = this.isDefunct ? null : {
|
||||||
|
contrastRatio,
|
||||||
|
};
|
||||||
|
|
||||||
|
this._auditing = null;
|
||||||
|
return audit;
|
||||||
|
});
|
||||||
|
|
||||||
|
return this._auditing;
|
||||||
},
|
},
|
||||||
|
|
||||||
snapshot() {
|
snapshot() {
|
||||||
|
@ -477,12 +477,14 @@ const AccessibleWalkerActor = ActorClassWithSpec(accessibleWalkerSpec, {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load accessibility highlighter style sheet used for preventing transitions and
|
* Ensure that nothing interferes with the audit for an accessible object
|
||||||
* applying transparency when calculating colour contrast.
|
* (CSS, overlays) by load accessibility highlighter style sheet used for
|
||||||
|
* preventing transitions and applying transparency when calculating colour
|
||||||
|
* contrast as well as temporarily hiding accessible highlighter overlay.
|
||||||
* @param {Object} win
|
* @param {Object} win
|
||||||
* Window where highlighting happens.
|
* Window where highlighting happens.
|
||||||
*/
|
*/
|
||||||
loadTransitionDisablingStyleSheet(win) {
|
clearStyles(win) {
|
||||||
if (this._sheetLoaded) {
|
if (this._sheetLoaded) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -493,23 +495,45 @@ const AccessibleWalkerActor = ActorClassWithSpec(accessibleWalkerSpec, {
|
|||||||
// taking a snapshot for contrast measurement).
|
// taking a snapshot for contrast measurement).
|
||||||
loadSheet(win, HIGHLIGHTER_STYLES_SHEET);
|
loadSheet(win, HIGHLIGHTER_STYLES_SHEET);
|
||||||
this._sheetLoaded = true;
|
this._sheetLoaded = true;
|
||||||
|
this.hideHighlighter();
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unload accessibility highlighter style sheet used for preventing transitions and
|
* Restore CSS and overlays that could've interfered with the audit for an
|
||||||
* applying transparency when calculating colour contrast.
|
* accessible object by unloading accessibility highlighter style sheet used
|
||||||
|
* for preventing transitions and applying transparency when calculating
|
||||||
|
* colour contrast and potentially restoring accessible highlighter overlay.
|
||||||
* @param {Object} win
|
* @param {Object} win
|
||||||
* Window where highlighting was happenning.
|
* Window where highlighting was happenning.
|
||||||
*/
|
*/
|
||||||
removeTransitionDisablingStyleSheet(win) {
|
restoreStyles(win) {
|
||||||
if (!this._sheetLoaded) {
|
if (!this._sheetLoaded) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.showHighlighter();
|
||||||
removeSheet(win, HIGHLIGHTER_STYLES_SHEET);
|
removeSheet(win, HIGHLIGHTER_STYLES_SHEET);
|
||||||
this._sheetLoaded = false;
|
this._sheetLoaded = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
hideHighlighter() {
|
||||||
|
// TODO: Fix this workaround that temporarily removes higlighter bounds
|
||||||
|
// overlay that can interfere with the contrast ratio calculation.
|
||||||
|
if (this._highlighter) {
|
||||||
|
const highlighter = this._highlighter.instance;
|
||||||
|
highlighter.hideAccessibleBounds();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
showHighlighter() {
|
||||||
|
// TODO: Fix this workaround that temporarily removes higlighter bounds
|
||||||
|
// overlay that can interfere with the contrast ratio calculation.
|
||||||
|
if (this._highlighter) {
|
||||||
|
const highlighter = this._highlighter.instance;
|
||||||
|
highlighter.showAccessibleBounds();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Public method used to show an accessible object highlighter on the client
|
* Public method used to show an accessible object highlighter on the client
|
||||||
* side.
|
* side.
|
||||||
|
@ -509,6 +509,13 @@ exports.CustomHighlighterActor = protocol.ActorClassWithSpec(customHighlighterSp
|
|||||||
|
|
||||||
release: function() {},
|
release: function() {},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get current instance of the highlighter object.
|
||||||
|
*/
|
||||||
|
get instance() {
|
||||||
|
return this._highlighter;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show the highlighter.
|
* Show the highlighter.
|
||||||
* This calls through to the highlighter instance's |show(node, options)|
|
* This calls through to the highlighter instance's |show(node, options)|
|
||||||
|
@ -232,18 +232,53 @@ class AccessibleHighlighter extends AutoRefreshHighlighter {
|
|||||||
this.highlighterEnv.window.document.documentElement);
|
this.highlighterEnv.window.document.documentElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public API method to temporarily hide accessible bounds for things like
|
||||||
|
* color contrast calculation.
|
||||||
|
*/
|
||||||
|
hideAccessibleBounds() {
|
||||||
|
if (this.getElement("elements").hasAttribute("hidden")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._hideAccessibleBounds();
|
||||||
|
this._shouldRestoreBoundsVisibility = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public API method to show accessible bounds in case they were temporarily
|
||||||
|
* hidden.
|
||||||
|
*/
|
||||||
|
showAccessibleBounds() {
|
||||||
|
if (this._shouldRestoreBoundsVisibility) {
|
||||||
|
this._showAccessibleBounds();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hide the accessible bounds container.
|
* Hide the accessible bounds container.
|
||||||
*/
|
*/
|
||||||
_hideAccessibleBounds() {
|
_hideAccessibleBounds() {
|
||||||
|
this._shouldRestoreBoundsVisibility = null;
|
||||||
|
setIgnoreLayoutChanges(true);
|
||||||
this.getElement("elements").setAttribute("hidden", "true");
|
this.getElement("elements").setAttribute("hidden", "true");
|
||||||
|
setIgnoreLayoutChanges(false,
|
||||||
|
this.highlighterEnv.window.document.documentElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show the accessible bounds container.
|
* Show the accessible bounds container.
|
||||||
*/
|
*/
|
||||||
_showAccessibleBounds() {
|
_showAccessibleBounds() {
|
||||||
|
this._shouldRestoreBoundsVisibility = null;
|
||||||
|
if (!this.currentNode || !this.highlighterEnv.window) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setIgnoreLayoutChanges(true);
|
||||||
this.getElement("elements").removeAttribute("hidden");
|
this.getElement("elements").removeAttribute("hidden");
|
||||||
|
setIgnoreLayoutChanges(false,
|
||||||
|
this.highlighterEnv.window.document.documentElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -337,11 +337,39 @@ class XULWindowAccessibleHighlighter {
|
|||||||
return isNodeValid(node) || isNodeValid(node, TEXT_NODE);
|
return isNodeValid(node) || isNodeValid(node, TEXT_NODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public API method to temporarily hide accessible bounds for things like
|
||||||
|
* color contrast calculation.
|
||||||
|
*/
|
||||||
|
hideAccessibleBounds() {
|
||||||
|
if (this.container.hasAttribute("hidden")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._hideAccessibleBounds();
|
||||||
|
this._shouldRestoreBoundsVisibility = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public API method to show accessible bounds in case they were temporarily
|
||||||
|
* hidden.
|
||||||
|
*/
|
||||||
|
showAccessibleBounds() {
|
||||||
|
if (this._shouldRestoreBoundsVisibility) {
|
||||||
|
this._showAccessibleBounds();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show accessible bounds highlighter.
|
* Show accessible bounds highlighter.
|
||||||
*/
|
*/
|
||||||
_showAccessibleBounds() {
|
_showAccessibleBounds() {
|
||||||
|
this._shouldRestoreBoundsVisibility = null;
|
||||||
if (this.container) {
|
if (this.container) {
|
||||||
|
if (!this.currentNode || !this.highlighterEnv.window) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.container.removeAttribute("hidden");
|
this.container.removeAttribute("hidden");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -350,6 +378,7 @@ class XULWindowAccessibleHighlighter {
|
|||||||
* Hide accessible bounds highlighter.
|
* Hide accessible bounds highlighter.
|
||||||
*/
|
*/
|
||||||
_hideAccessibleBounds() {
|
_hideAccessibleBounds() {
|
||||||
|
this._shouldRestoreBoundsVisibility = null;
|
||||||
if (this.container) {
|
if (this.container) {
|
||||||
this.container.setAttribute("hidden", "true");
|
this.container.setAttribute("hidden", "true");
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,8 @@
|
|||||||
#include "mozilla/dom/KeyframeEffectBinding.h"
|
#include "mozilla/dom/KeyframeEffectBinding.h"
|
||||||
#include "mozilla/dom/KeyframeEffect.h" // For PropertyValuesPair etc.
|
#include "mozilla/dom/KeyframeEffect.h" // For PropertyValuesPair etc.
|
||||||
#include "mozilla/dom/Nullable.h"
|
#include "mozilla/dom/Nullable.h"
|
||||||
#include "jsapi.h" // For ForOfIterator etc.
|
#include "jsapi.h" // For most JSAPI
|
||||||
|
#include "js/ForOfIterator.h" // For JS::ForOfIterator
|
||||||
#include "nsClassHashtable.h"
|
#include "nsClassHashtable.h"
|
||||||
#include "nsContentUtils.h" // For GetContextForContent
|
#include "nsContentUtils.h" // For GetContextForContent
|
||||||
#include "nsCSSPropertyIDSet.h"
|
#include "nsCSSPropertyIDSet.h"
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "mozilla/dom/ShadowRoot.h"
|
#include "mozilla/dom/ShadowRoot.h"
|
||||||
#include "nsHTMLTags.h"
|
#include "nsHTMLTags.h"
|
||||||
#include "jsapi.h"
|
#include "jsapi.h"
|
||||||
|
#include "js/ForOfIterator.h" // JS::ForOfIterator
|
||||||
#include "xpcprivate.h"
|
#include "xpcprivate.h"
|
||||||
#include "nsGlobalWindow.h"
|
#include "nsGlobalWindow.h"
|
||||||
|
|
||||||
|
@ -12,7 +12,8 @@
|
|||||||
|
|
||||||
#include "AccessCheck.h"
|
#include "AccessCheck.h"
|
||||||
#include "jsapi.h"
|
#include "jsapi.h"
|
||||||
#include "js/JSON.h"
|
#include "js/ForOfIterator.h" // JS::ForOfIterator
|
||||||
|
#include "js/JSON.h" // JS_ParseJSON
|
||||||
#include "mozAutoDocUpdate.h"
|
#include "mozAutoDocUpdate.h"
|
||||||
#include "mozilla/AsyncEventDispatcher.h"
|
#include "mozilla/AsyncEventDispatcher.h"
|
||||||
#include "mozilla/CORSMode.h"
|
#include "mozilla/CORSMode.h"
|
||||||
|
@ -1134,11 +1134,18 @@ class CGHeaders(CGWrapper):
|
|||||||
headerSet = declareIncludes
|
headerSet = declareIncludes
|
||||||
else:
|
else:
|
||||||
headerSet = bindingHeaders
|
headerSet = bindingHeaders
|
||||||
if t.nullable():
|
# Strip off outer layers and add headers they might (conservatively:
|
||||||
# Need to make sure that Nullable as a dictionary
|
# only nullable non-pointer types need Nullable.h, and only
|
||||||
# member works.
|
# sequences outside unions require ForOfIterator.h) require.
|
||||||
headerSet.add("mozilla/dom/Nullable.h")
|
unrolled = t
|
||||||
unrolled = t.unroll()
|
while True:
|
||||||
|
if unrolled.nullable():
|
||||||
|
headerSet.add("mozilla/dom/Nullable.h")
|
||||||
|
elif unrolled.isSequence():
|
||||||
|
bindingHeaders.add("js/ForOfIterator.h")
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
unrolled = unrolled.inner
|
||||||
if unrolled.isUnion():
|
if unrolled.isUnion():
|
||||||
headerSet.add(self.getUnionDeclarationFilename(config, unrolled))
|
headerSet.add(self.getUnionDeclarationFilename(config, unrolled))
|
||||||
bindingHeaders.add("mozilla/dom/UnionConversions.h")
|
bindingHeaders.add("mozilla/dom/UnionConversions.h")
|
||||||
@ -1371,6 +1378,10 @@ def UnionTypes(unionTypes, config):
|
|||||||
if f.nullable():
|
if f.nullable():
|
||||||
headers.add("mozilla/dom/Nullable.h")
|
headers.add("mozilla/dom/Nullable.h")
|
||||||
isSequence = f.isSequence()
|
isSequence = f.isSequence()
|
||||||
|
if isSequence:
|
||||||
|
# Dealing with sequences requires for-of-compatible
|
||||||
|
# iteration.
|
||||||
|
implheaders.add("js/ForOfIterator.h")
|
||||||
f = f.unroll()
|
f = f.unroll()
|
||||||
if f.isPromise():
|
if f.isPromise():
|
||||||
headers.add("mozilla/dom/Promise.h")
|
headers.add("mozilla/dom/Promise.h")
|
||||||
@ -1471,6 +1482,10 @@ def UnionConversions(unionTypes, config):
|
|||||||
unionConversions[name] = CGUnionConversionStruct(t, config)
|
unionConversions[name] = CGUnionConversionStruct(t, config)
|
||||||
|
|
||||||
def addHeadersForType(f):
|
def addHeadersForType(f):
|
||||||
|
if f.isSequence():
|
||||||
|
# Sequences require JSAPI C++ for-of iteration code to fill
|
||||||
|
# them.
|
||||||
|
headers.add("js/ForOfIterator.h")
|
||||||
f = f.unroll()
|
f = f.unroll()
|
||||||
if f.isPromise():
|
if f.isPromise():
|
||||||
headers.add("mozilla/dom/Promise.h")
|
headers.add("mozilla/dom/Promise.h")
|
||||||
|
7
dom/cache/PrincipalVerifier.cpp
vendored
7
dom/cache/PrincipalVerifier.cpp
vendored
@ -13,7 +13,6 @@
|
|||||||
#include "mozilla/ipc/BackgroundUtils.h"
|
#include "mozilla/ipc/BackgroundUtils.h"
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
#include "nsIPrincipal.h"
|
#include "nsIPrincipal.h"
|
||||||
#include "nsIScriptSecurityManager.h"
|
|
||||||
#include "nsNetUtil.h"
|
#include "nsNetUtil.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
@ -118,12 +117,6 @@ void PrincipalVerifier::VerifyOnMainThread() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIScriptSecurityManager> ssm = nsContentUtils::GetSecurityManager();
|
|
||||||
if (NS_WARN_IF(!ssm)) {
|
|
||||||
DispatchToInitiatingThread(NS_ERROR_ILLEGAL_DURING_SHUTDOWN);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify if a child process uses system principal, which is not allowed
|
// Verify if a child process uses system principal, which is not allowed
|
||||||
// to prevent system principal is spoofed.
|
// to prevent system principal is spoofed.
|
||||||
if (NS_WARN_IF(actor && principal->IsSystemPrincipal())) {
|
if (NS_WARN_IF(actor && principal->IsSystemPrincipal())) {
|
||||||
|
@ -606,6 +606,15 @@ dictionary WindowActorOptions {
|
|||||||
*/
|
*/
|
||||||
boolean includeChrome = false;
|
boolean includeChrome = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An array of URL match patterns (as accepted by the MatchPattern
|
||||||
|
* class in MatchPattern.webidl) which restrict which pages the actor
|
||||||
|
* may be instantiated for. If this is defined, only documents URL which match
|
||||||
|
* are allowed to have the given actor created for them. Other
|
||||||
|
* documents will fail to have their actor constructed, returning nullptr.
|
||||||
|
**/
|
||||||
|
sequence<DOMString> matches;
|
||||||
|
|
||||||
/** This fields are used for configuring individual sides of the actor. */
|
/** This fields are used for configuring individual sides of the actor. */
|
||||||
required WindowActorSidedOptions parent;
|
required WindowActorSidedOptions parent;
|
||||||
required WindowActorChildOptions child;
|
required WindowActorChildOptions child;
|
||||||
|
@ -651,7 +651,7 @@ void TextComposition::EndHandlingComposition(EditorBase* aEditorBase) {
|
|||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
RefPtr<EditorBase> editorBase = GetEditorBase();
|
RefPtr<EditorBase> editorBase = GetEditorBase();
|
||||||
MOZ_ASSERT(editorBase == aEditorBase,
|
MOZ_ASSERT(!editorBase || editorBase == aEditorBase,
|
||||||
"Another editor handled the composition?");
|
"Another editor handled the composition?");
|
||||||
#endif // #ifdef DEBUG
|
#endif // #ifdef DEBUG
|
||||||
mEditorBaseWeak = nullptr;
|
mEditorBaseWeak = nullptr;
|
||||||
|
@ -1168,7 +1168,9 @@ void ContentChild::LaunchRDDProcess() {
|
|||||||
nsresult rv;
|
nsresult rv;
|
||||||
Endpoint<PRemoteDecoderManagerChild> endpoint;
|
Endpoint<PRemoteDecoderManagerChild> endpoint;
|
||||||
Unused << SendLaunchRDDProcess(&rv, &endpoint);
|
Unused << SendLaunchRDDProcess(&rv, &endpoint);
|
||||||
if (rv == NS_OK) {
|
// Only call InitForContent if we got a valid enpoint back which
|
||||||
|
// indicates we needed to launch an RDD process.
|
||||||
|
if (rv == NS_OK && endpoint.IsValid()) {
|
||||||
RemoteDecoderManagerChild::InitForContent(std::move(endpoint));
|
RemoteDecoderManagerChild::InitForContent(std::move(endpoint));
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
@ -1064,6 +1064,14 @@ mozilla::ipc::IPCResult ContentParent::RecvLaunchRDDProcess(
|
|||||||
Preferences::GetBool("media.rdd-process.enabled", false)) {
|
Preferences::GetBool("media.rdd-process.enabled", false)) {
|
||||||
RDDProcessManager* rdd = RDDProcessManager::Get();
|
RDDProcessManager* rdd = RDDProcessManager::Get();
|
||||||
if (rdd) {
|
if (rdd) {
|
||||||
|
// If there is already an RDDChild, then we've already launched the
|
||||||
|
// RDD process. We don't need to do anything else. Specifically,
|
||||||
|
// we want to avoid calling CreateContentBridge again because that
|
||||||
|
// causes the RemoteDecoderManagerParent to rebuild needlessly.
|
||||||
|
if (rdd->GetRDDChild()) {
|
||||||
|
return IPC_OK();
|
||||||
|
}
|
||||||
|
|
||||||
rdd->LaunchRDDProcess();
|
rdd->LaunchRDDProcess();
|
||||||
|
|
||||||
bool rddOpened = rdd->CreateContentBridge(OtherPid(), aEndpoint);
|
bool rddOpened = rdd->CreateContentBridge(OtherPid(), aEndpoint);
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
#include "mozilla/dom/PContent.h"
|
#include "mozilla/dom/PContent.h"
|
||||||
#include "mozilla/StaticPtr.h"
|
#include "mozilla/StaticPtr.h"
|
||||||
#include "mozJSComponentLoader.h"
|
#include "mozJSComponentLoader.h"
|
||||||
|
#include "mozilla/extensions/WebExtensionContentScript.h"
|
||||||
|
#include "mozilla/Logging.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
@ -119,9 +121,6 @@ class JSWindowActorProtocol final : public nsIObserver,
|
|||||||
nsTArray<nsCString> mObservers;
|
nsTArray<nsCString> mObservers;
|
||||||
};
|
};
|
||||||
|
|
||||||
const nsAString& Name() const { return mName; }
|
|
||||||
bool AllFrames() const { return mAllFrames; }
|
|
||||||
bool IncludeChrome() const { return mIncludeChrome; }
|
|
||||||
const ParentSide& Parent() const { return mParent; }
|
const ParentSide& Parent() const { return mParent; }
|
||||||
const ChildSide& Child() const { return mChild; }
|
const ChildSide& Child() const { return mChild; }
|
||||||
|
|
||||||
@ -129,17 +128,22 @@ class JSWindowActorProtocol final : public nsIObserver,
|
|||||||
void UnregisterListenersFor(EventTarget* aRoot);
|
void UnregisterListenersFor(EventTarget* aRoot);
|
||||||
void AddObservers();
|
void AddObservers();
|
||||||
void RemoveObservers();
|
void RemoveObservers();
|
||||||
|
bool Matches(BrowsingContext* aBrowsingContext, nsIURI* aURI);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit JSWindowActorProtocol(const nsAString& aName) : mName(aName) {}
|
explicit JSWindowActorProtocol(const nsAString& aName) : mName(aName) {}
|
||||||
|
extensions::MatchPatternSet* GetURIMatcher();
|
||||||
~JSWindowActorProtocol() = default;
|
~JSWindowActorProtocol() = default;
|
||||||
|
|
||||||
nsString mName;
|
nsString mName;
|
||||||
bool mAllFrames = false;
|
bool mAllFrames = false;
|
||||||
bool mIncludeChrome = false;
|
bool mIncludeChrome = false;
|
||||||
|
nsTArray<nsString> mMatches;
|
||||||
|
|
||||||
ParentSide mParent;
|
ParentSide mParent;
|
||||||
ChildSide mChild;
|
ChildSide mChild;
|
||||||
|
|
||||||
|
RefPtr<extensions::MatchPatternSet> mURIMatcher;
|
||||||
};
|
};
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(JSWindowActorProtocol, nsIObserver, nsIDOMEventListener);
|
NS_IMPL_ISUPPORTS(JSWindowActorProtocol, nsIObserver, nsIDOMEventListener);
|
||||||
@ -153,6 +157,7 @@ JSWindowActorProtocol::FromIPC(const JSWindowActorInfo& aInfo) {
|
|||||||
// irrelevant and not propagated.
|
// irrelevant and not propagated.
|
||||||
proto->mIncludeChrome = false;
|
proto->mIncludeChrome = false;
|
||||||
proto->mAllFrames = aInfo.allFrames();
|
proto->mAllFrames = aInfo.allFrames();
|
||||||
|
proto->mMatches = aInfo.matches();
|
||||||
proto->mChild.mModuleURI.Assign(aInfo.url());
|
proto->mChild.mModuleURI.Assign(aInfo.url());
|
||||||
|
|
||||||
proto->mChild.mEvents.SetCapacity(aInfo.events().Length());
|
proto->mChild.mEvents.SetCapacity(aInfo.events().Length());
|
||||||
@ -177,6 +182,7 @@ JSWindowActorInfo JSWindowActorProtocol::ToIPC() {
|
|||||||
JSWindowActorInfo info;
|
JSWindowActorInfo info;
|
||||||
info.name() = mName;
|
info.name() = mName;
|
||||||
info.allFrames() = mAllFrames;
|
info.allFrames() = mAllFrames;
|
||||||
|
info.matches() = mMatches;
|
||||||
info.url() = mChild.mModuleURI;
|
info.url() = mChild.mModuleURI;
|
||||||
|
|
||||||
info.events().SetCapacity(mChild.mEvents.Length());
|
info.events().SetCapacity(mChild.mEvents.Length());
|
||||||
@ -205,6 +211,11 @@ JSWindowActorProtocol::FromWebIDLOptions(const nsAString& aName,
|
|||||||
proto->mAllFrames = aOptions.mAllFrames;
|
proto->mAllFrames = aOptions.mAllFrames;
|
||||||
proto->mIncludeChrome = aOptions.mIncludeChrome;
|
proto->mIncludeChrome = aOptions.mIncludeChrome;
|
||||||
|
|
||||||
|
if (aOptions.mMatches.WasPassed()) {
|
||||||
|
MOZ_ASSERT(aOptions.mMatches.Value().Length());
|
||||||
|
proto->mMatches = aOptions.mMatches.Value();
|
||||||
|
}
|
||||||
|
|
||||||
proto->mParent.mModuleURI = aOptions.mParent.mModuleURI;
|
proto->mParent.mModuleURI = aOptions.mParent.mModuleURI;
|
||||||
proto->mChild.mModuleURI = aOptions.mChild.mModuleURI;
|
proto->mChild.mModuleURI = aOptions.mChild.mModuleURI;
|
||||||
|
|
||||||
@ -302,7 +313,13 @@ NS_IMETHODIMP JSWindowActorProtocol::Observe(nsISupports* aSubject,
|
|||||||
ErrorResult error;
|
ErrorResult error;
|
||||||
RefPtr<JSWindowActorChild> actor = wgc->GetActor(mName, error);
|
RefPtr<JSWindowActorChild> actor = wgc->GetActor(mName, error);
|
||||||
if (NS_WARN_IF(error.Failed())) {
|
if (NS_WARN_IF(error.Failed())) {
|
||||||
return error.StealNSResult();
|
nsresult rv = error.StealNSResult();
|
||||||
|
|
||||||
|
// Don't raise an error if creation of our actor was vetoed.
|
||||||
|
if (rv == NS_ERROR_NOT_AVAILABLE) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the wrapper for our actor. If we don't have a wrapper, the target
|
// Get the wrapper for our actor. If we don't have a wrapper, the target
|
||||||
@ -382,6 +399,52 @@ void JSWindowActorProtocol::RemoveObservers() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extensions::MatchPatternSet* JSWindowActorProtocol::GetURIMatcher() {
|
||||||
|
// If we've already created the pattern set, return it.
|
||||||
|
if (mURIMatcher || mMatches.IsEmpty()) {
|
||||||
|
return mURIMatcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructing the MatchPatternSet requires a JS environment to be run in.
|
||||||
|
// We can construct it here in the JSM scope, as we will be keeping it around.
|
||||||
|
AutoJSAPI jsapi;
|
||||||
|
MOZ_ALWAYS_TRUE(jsapi.Init(xpc::PrivilegedJunkScope()));
|
||||||
|
GlobalObject global(jsapi.cx(), xpc::PrivilegedJunkScope());
|
||||||
|
|
||||||
|
nsTArray<OwningStringOrMatchPattern> patterns;
|
||||||
|
patterns.SetCapacity(mMatches.Length());
|
||||||
|
for (nsString& s : mMatches) {
|
||||||
|
auto* entry = patterns.AppendElement();
|
||||||
|
entry->SetAsString() = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
MatchPatternOptions matchPatternOptions;
|
||||||
|
// Make MatchPattern's mSchemes create properly.
|
||||||
|
matchPatternOptions.mRestrictSchemes = false;
|
||||||
|
mURIMatcher = extensions::MatchPatternSet::Constructor(
|
||||||
|
global, patterns, matchPatternOptions, IgnoreErrors());
|
||||||
|
return mURIMatcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JSWindowActorProtocol::Matches(BrowsingContext* aBrowsingContext,
|
||||||
|
nsIURI* aURI) {
|
||||||
|
if (!mAllFrames && aBrowsingContext->GetParent()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mIncludeChrome && !aBrowsingContext->IsContent()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extensions::MatchPatternSet* uriMatcher = GetURIMatcher()) {
|
||||||
|
if (!uriMatcher->Matches(aURI)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
JSWindowActorService::JSWindowActorService() { MOZ_ASSERT(NS_IsMainThread()); }
|
JSWindowActorService::JSWindowActorService() { MOZ_ASSERT(NS_IsMainThread()); }
|
||||||
|
|
||||||
JSWindowActorService::~JSWindowActorService() { MOZ_ASSERT(NS_IsMainThread()); }
|
JSWindowActorService::~JSWindowActorService() { MOZ_ASSERT(NS_IsMainThread()); }
|
||||||
@ -489,13 +552,12 @@ void JSWindowActorService::GetJSWindowActorInfos(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JSWindowActorService::ConstructActor(const nsAString& aName,
|
void JSWindowActorService::ConstructActor(
|
||||||
bool aParentSide,
|
const nsAString& aName, bool aParentSide, BrowsingContext* aBrowsingContext,
|
||||||
BrowsingContext* aBrowsingContext,
|
nsIURI* aURI, JS::MutableHandleObject aActor, ErrorResult& aRv) {
|
||||||
JS::MutableHandleObject aActor,
|
|
||||||
ErrorResult& aRv) {
|
|
||||||
MOZ_ASSERT_IF(aParentSide, XRE_IsParentProcess());
|
MOZ_ASSERT_IF(aParentSide, XRE_IsParentProcess());
|
||||||
|
MOZ_ASSERT(aBrowsingContext, "DocShell without a BrowsingContext!");
|
||||||
|
MOZ_ASSERT(aURI, "Must have URI!");
|
||||||
// Constructing an actor requires a running script, so push an AutoEntryScript
|
// Constructing an actor requires a running script, so push an AutoEntryScript
|
||||||
// onto the stack.
|
// onto the stack.
|
||||||
AutoEntryScript aes(xpc::PrivilegedJunkScope(), "JSWindowActor construction");
|
AutoEntryScript aes(xpc::PrivilegedJunkScope(), "JSWindowActor construction");
|
||||||
@ -515,14 +577,9 @@ void JSWindowActorService::ConstructActor(const nsAString& aName,
|
|||||||
side = &proto->Child();
|
side = &proto->Child();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if our current BrowsingContext matches the requirements for this
|
// Check if our current BrowsingContext and URI matches the requirements for
|
||||||
// actor to load.
|
// this actor to load.
|
||||||
if (!proto->AllFrames() && aBrowsingContext->GetParent()) {
|
if (!proto->Matches(aBrowsingContext, aURI)) {
|
||||||
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!proto->IncludeChrome() && !aBrowsingContext->IsContent()) {
|
|
||||||
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
|
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ class JSWindowActorService final {
|
|||||||
// This method will not initialize the actor or set its manager,
|
// This method will not initialize the actor or set its manager,
|
||||||
// which is handled by callers.
|
// which is handled by callers.
|
||||||
void ConstructActor(const nsAString& aName, bool aParentSide,
|
void ConstructActor(const nsAString& aName, bool aParentSide,
|
||||||
BrowsingContext* aBrowsingContext,
|
BrowsingContext* aBrowsingContext, nsIURI* aURI,
|
||||||
JS::MutableHandleObject aActor, ErrorResult& aRv);
|
JS::MutableHandleObject aActor, ErrorResult& aRv);
|
||||||
|
|
||||||
void ReceiveMessage(nsISupports* aActor, JS::RootedObject& aObj,
|
void ReceiveMessage(nsISupports* aActor, JS::RootedObject& aObj,
|
||||||
|
@ -242,6 +242,7 @@ struct JSWindowActorInfo
|
|||||||
|
|
||||||
JSWindowActorEventDecl[] events;
|
JSWindowActorEventDecl[] events;
|
||||||
nsCString[] observers;
|
nsCString[] observers;
|
||||||
|
nsString[] matches;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GMPAPITags
|
struct GMPAPITags
|
||||||
|
@ -70,6 +70,8 @@ already_AddRefed<WindowGlobalChild> WindowGlobalChild::Create(
|
|||||||
MOZ_RELEASE_ASSERT(!entry, "Duplicate WindowGlobalChild entry for ID!");
|
MOZ_RELEASE_ASSERT(!entry, "Duplicate WindowGlobalChild entry for ID!");
|
||||||
entry.OrInsert([&] { return wgc; });
|
entry.OrInsert([&] { return wgc; });
|
||||||
|
|
||||||
|
// Send down our initial document URI.
|
||||||
|
wgc->SendUpdateDocumentURI(aWindow->GetDocumentURI());
|
||||||
return wgc.forget();
|
return wgc.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,7 +169,7 @@ already_AddRefed<JSWindowActorChild> WindowGlobalChild::GetActor(
|
|||||||
|
|
||||||
JS::RootedObject obj(RootingCx());
|
JS::RootedObject obj(RootingCx());
|
||||||
actorSvc->ConstructActor(aName, /* aChildSide */ false, mBrowsingContext,
|
actorSvc->ConstructActor(aName, /* aChildSide */ false, mBrowsingContext,
|
||||||
&obj, aRv);
|
mWindowGlobal->GetDocumentURI(), &obj, aRv);
|
||||||
if (aRv.Failed()) {
|
if (aRv.Failed()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -210,7 +210,7 @@ already_AddRefed<JSWindowActorParent> WindowGlobalParent::GetActor(
|
|||||||
|
|
||||||
JS::RootedObject obj(RootingCx());
|
JS::RootedObject obj(RootingCx());
|
||||||
actorSvc->ConstructActor(aName, /* aParentSide */ true, mBrowsingContext,
|
actorSvc->ConstructActor(aName, /* aParentSide */ true, mBrowsingContext,
|
||||||
&obj, aRv);
|
mDocumentURI, &obj, aRv);
|
||||||
if (aRv.Failed()) {
|
if (aRv.Failed()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const URL = "about:blank";
|
const URL = "about:blank";
|
||||||
|
const TEST_URL = "http://test2.example.org/";
|
||||||
let windowActorOptions = {
|
let windowActorOptions = {
|
||||||
parent: {
|
parent: {
|
||||||
moduleURI: "resource://testing-common/TestParent.jsm",
|
moduleURI: "resource://testing-common/TestParent.jsm",
|
||||||
@ -20,6 +21,12 @@ let windowActorOptions = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function teardown() {
|
||||||
|
windowActorOptions.allFrames = false;
|
||||||
|
delete windowActorOptions.matches;
|
||||||
|
ChromeUtils.unregisterWindowActor("Test");
|
||||||
|
}
|
||||||
|
|
||||||
add_task(function test_registerWindowActor() {
|
add_task(function test_registerWindowActor() {
|
||||||
ok(ChromeUtils, "Should be able to get the ChromeUtils interface");
|
ok(ChromeUtils, "Should be able to get the ChromeUtils interface");
|
||||||
ChromeUtils.registerWindowActor("Test", windowActorOptions);
|
ChromeUtils.registerWindowActor("Test", windowActorOptions);
|
||||||
@ -52,63 +59,6 @@ add_task(async function test_getActor() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(async function test_getActor_without_allFrames() {
|
|
||||||
windowActorOptions.allFrames = false;
|
|
||||||
await BrowserTestUtils.withNewTab({gBrowser, url: URL},
|
|
||||||
async function(browser) {
|
|
||||||
ChromeUtils.registerWindowActor("Test", windowActorOptions);
|
|
||||||
await ContentTask.spawn(
|
|
||||||
browser, {}, async function() {
|
|
||||||
// Create and append an iframe into the window's document.
|
|
||||||
let frame = content.document.createElement("iframe");
|
|
||||||
content.document.body.appendChild(frame);
|
|
||||||
is(content.window.frames.length, 1, "There should be an iframe.");
|
|
||||||
let child = frame.contentWindow.window.getWindowGlobalChild();
|
|
||||||
Assert.throws(() => child.getActor("Test"),
|
|
||||||
/NS_ERROR_NOT_AVAILABLE/, "Should throw if allFrames is false.");
|
|
||||||
});
|
|
||||||
ChromeUtils.unregisterWindowActor("Test");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
add_task(async function test_getActor_with_allFrames() {
|
|
||||||
windowActorOptions.allFrames = true;
|
|
||||||
ChromeUtils.registerWindowActor("Test", windowActorOptions);
|
|
||||||
await BrowserTestUtils.withNewTab({gBrowser, url: URL},
|
|
||||||
async function(browser) {
|
|
||||||
await ContentTask.spawn(
|
|
||||||
browser, {}, async function() {
|
|
||||||
// Create and append an iframe into the window's document.
|
|
||||||
let frame = content.document.createElement("iframe");
|
|
||||||
content.document.body.appendChild(frame);
|
|
||||||
is(content.window.frames.length, 1, "There should be an iframe.");
|
|
||||||
let child = frame.contentWindow.window.getWindowGlobalChild();
|
|
||||||
let actorChild = child.getActor("Test");
|
|
||||||
ok(actorChild, "JSWindowActorChild should have value.");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
ChromeUtils.unregisterWindowActor("Test");
|
|
||||||
});
|
|
||||||
|
|
||||||
add_task(async function test_getActor_without_includeChrome() {
|
|
||||||
windowActorOptions.includeChrome = false;
|
|
||||||
let parent = window.docShell.browsingContext.currentWindowGlobal;
|
|
||||||
ChromeUtils.registerWindowActor("Test", windowActorOptions);
|
|
||||||
SimpleTest.doesThrow(() =>
|
|
||||||
parent.getActor("Test"),
|
|
||||||
"Should throw if includeChrome is false.");
|
|
||||||
ChromeUtils.unregisterWindowActor("Test");
|
|
||||||
});
|
|
||||||
|
|
||||||
add_task(async function test_getActor_with_includeChrome() {
|
|
||||||
windowActorOptions.includeChrome = true;
|
|
||||||
ChromeUtils.registerWindowActor("Test", windowActorOptions);
|
|
||||||
let parent = window.docShell.browsingContext.currentWindowGlobal;
|
|
||||||
let actorParent = parent.getActor("Test");
|
|
||||||
ok(actorParent, "JSWindowActorParent should have value.");
|
|
||||||
ChromeUtils.unregisterWindowActor("Test");
|
|
||||||
});
|
|
||||||
|
|
||||||
add_task(async function test_asyncMessage() {
|
add_task(async function test_asyncMessage() {
|
||||||
await BrowserTestUtils.withNewTab({gBrowser, url: URL},
|
await BrowserTestUtils.withNewTab({gBrowser, url: URL},
|
||||||
async function(browser) {
|
async function(browser) {
|
||||||
@ -257,3 +207,150 @@ add_task(async function test_observers_dont_notify_with_wrong_window() {
|
|||||||
});
|
});
|
||||||
ChromeUtils.unregisterWindowActor("Test");
|
ChromeUtils.unregisterWindowActor("Test");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
add_task(async function test_getActor_with_mismatch() {
|
||||||
|
await BrowserTestUtils.withNewTab({gBrowser, url: URL},
|
||||||
|
async function(browser) {
|
||||||
|
windowActorOptions.matches = ["*://*/*"];
|
||||||
|
ChromeUtils.registerWindowActor("Test", windowActorOptions);
|
||||||
|
let parent = browser.browsingContext.currentWindowGlobal;
|
||||||
|
ok(parent, "WindowGlobalParent should have value.");
|
||||||
|
Assert.throws(() => parent.getActor("Test"),
|
||||||
|
/NS_ERROR_NOT_AVAILABLE/, "Should throw if it doesn't match.");
|
||||||
|
|
||||||
|
await ContentTask.spawn(
|
||||||
|
browser, {}, async function() {
|
||||||
|
let child = content.window.getWindowGlobalChild();
|
||||||
|
ok(child, "WindowGlobalChild should have value.");
|
||||||
|
|
||||||
|
Assert.throws(() => child.getActor("Test"),
|
||||||
|
/NS_ERROR_NOT_AVAILABLE/, "Should throw if it doesn't match.");
|
||||||
|
});
|
||||||
|
teardown();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function test_getActor_with_matches() {
|
||||||
|
await BrowserTestUtils.withNewTab({gBrowser, url: TEST_URL},
|
||||||
|
async function(browser) {
|
||||||
|
windowActorOptions.matches = ["*://*/*"];
|
||||||
|
ChromeUtils.registerWindowActor("Test", windowActorOptions);
|
||||||
|
let parent = browser.browsingContext.currentWindowGlobal;
|
||||||
|
ok(parent.getActor("Test"), "JSWindowActorParent should have value.");
|
||||||
|
|
||||||
|
await ContentTask.spawn(
|
||||||
|
browser, {}, async function() {
|
||||||
|
let child = content.window.getWindowGlobalChild();
|
||||||
|
ok(child, "WindowGlobalChild should have value.");
|
||||||
|
ok(child.getActor("Test"), "JSWindowActorChild should have value.");
|
||||||
|
});
|
||||||
|
|
||||||
|
teardown();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function test_getActor_with_iframe_matches() {
|
||||||
|
await BrowserTestUtils.withNewTab({gBrowser, url: URL},
|
||||||
|
async function(browser) {
|
||||||
|
windowActorOptions.allFrames = true;
|
||||||
|
windowActorOptions.matches = ["*://*/*"];
|
||||||
|
ChromeUtils.registerWindowActor("Test", windowActorOptions);
|
||||||
|
|
||||||
|
await ContentTask.spawn(
|
||||||
|
browser, TEST_URL, async function(url) {
|
||||||
|
// Create and append an iframe into the window's document.
|
||||||
|
let frame = content.document.createElement("iframe");
|
||||||
|
frame.src = url;
|
||||||
|
content.document.body.appendChild(frame);
|
||||||
|
await ContentTaskUtils.waitForEvent(frame, "load");
|
||||||
|
|
||||||
|
is(content.window.frames.length, 1, "There should be an iframe.");
|
||||||
|
let child = frame.contentWindow.window.getWindowGlobalChild();
|
||||||
|
ok(child.getActor("Test"), "JSWindowActorChild should have value.");
|
||||||
|
});
|
||||||
|
teardown();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function test_getActor_with_iframe_mismatch() {
|
||||||
|
await BrowserTestUtils.withNewTab({gBrowser, url: URL},
|
||||||
|
async function(browser) {
|
||||||
|
windowActorOptions.allFrames = true;
|
||||||
|
windowActorOptions.matches = ["about:home"];
|
||||||
|
ChromeUtils.registerWindowActor("Test", windowActorOptions);
|
||||||
|
|
||||||
|
await ContentTask.spawn(
|
||||||
|
browser, TEST_URL, async function(url) {
|
||||||
|
// Create and append an iframe into the window's document.
|
||||||
|
let frame = content.document.createElement("iframe");
|
||||||
|
frame.src = url;
|
||||||
|
content.document.body.appendChild(frame);
|
||||||
|
await ContentTaskUtils.waitForEvent(frame, "load");
|
||||||
|
|
||||||
|
is(content.window.frames.length, 1, "There should be an iframe.");
|
||||||
|
let child = frame.contentWindow.window.getWindowGlobalChild();
|
||||||
|
Assert.throws(() => child.getActor("Test"),
|
||||||
|
/NS_ERROR_NOT_AVAILABLE/, "Should throw if it doesn't match.");
|
||||||
|
});
|
||||||
|
teardown();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function test_getActor_without_allFrames() {
|
||||||
|
await BrowserTestUtils.withNewTab({gBrowser, url: URL},
|
||||||
|
async function(browser) {
|
||||||
|
windowActorOptions.allFrames = false;
|
||||||
|
ChromeUtils.registerWindowActor("Test", windowActorOptions);
|
||||||
|
|
||||||
|
await ContentTask.spawn(
|
||||||
|
browser, {}, async function() {
|
||||||
|
// Create and append an iframe into the window's document.
|
||||||
|
let frame = content.document.createElement("iframe");
|
||||||
|
content.document.body.appendChild(frame);
|
||||||
|
is(content.window.frames.length, 1, "There should be an iframe.");
|
||||||
|
let child = frame.contentWindow.window.getWindowGlobalChild();
|
||||||
|
Assert.throws(() => child.getActor("Test"),
|
||||||
|
/NS_ERROR_NOT_AVAILABLE/, "Should throw if allFrames is false.");
|
||||||
|
});
|
||||||
|
ChromeUtils.unregisterWindowActor("Test");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function test_getActor_with_allFrames() {
|
||||||
|
await BrowserTestUtils.withNewTab({gBrowser, url: URL},
|
||||||
|
async function(browser) {
|
||||||
|
windowActorOptions.allFrames = true;
|
||||||
|
ChromeUtils.registerWindowActor("Test", windowActorOptions);
|
||||||
|
|
||||||
|
await ContentTask.spawn(
|
||||||
|
browser, {}, async function() {
|
||||||
|
// Create and append an iframe into the window's document.
|
||||||
|
let frame = content.document.createElement("iframe");
|
||||||
|
content.document.body.appendChild(frame);
|
||||||
|
is(content.window.frames.length, 1, "There should be an iframe.");
|
||||||
|
let child = frame.contentWindow.window.getWindowGlobalChild();
|
||||||
|
let actorChild = child.getActor("Test");
|
||||||
|
ok(actorChild, "JSWindowActorChild should have value.");
|
||||||
|
});
|
||||||
|
ChromeUtils.unregisterWindowActor("Test");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function test_getActor_without_includeChrome() {
|
||||||
|
windowActorOptions.includeChrome = false;
|
||||||
|
let parent = window.docShell.browsingContext.currentWindowGlobal;
|
||||||
|
ChromeUtils.registerWindowActor("Test", windowActorOptions);
|
||||||
|
SimpleTest.doesThrow(() =>
|
||||||
|
parent.getActor("Test"),
|
||||||
|
"Should throw if includeChrome is false.");
|
||||||
|
ChromeUtils.unregisterWindowActor("Test");
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function test_getActor_with_includeChrome() {
|
||||||
|
windowActorOptions.includeChrome = true;
|
||||||
|
ChromeUtils.registerWindowActor("Test", windowActorOptions);
|
||||||
|
let parent = window.docShell.browsingContext.currentWindowGlobal;
|
||||||
|
let actorParent = parent.getActor("Test");
|
||||||
|
ok(actorParent, "JSWindowActorParent should have value.");
|
||||||
|
ChromeUtils.unregisterWindowActor("Test");
|
||||||
|
});
|
||||||
|
@ -32,7 +32,7 @@ function nativeVerticalWheelEventMsg() {
|
|||||||
case "mac": return 0; // value is unused, can be anything
|
case "mac": return 0; // value is unused, can be anything
|
||||||
case "linux": return 4; // value is unused, pass GDK_SCROLL_SMOOTH anyway
|
case "linux": return 4; // value is unused, pass GDK_SCROLL_SMOOTH anyway
|
||||||
}
|
}
|
||||||
throw "Native wheel events not supported on platform " + getPlatform();
|
throw new Error("Native wheel events not supported on platform " + getPlatform());
|
||||||
}
|
}
|
||||||
|
|
||||||
function nativeHorizontalWheelEventMsg() {
|
function nativeHorizontalWheelEventMsg() {
|
||||||
@ -41,7 +41,7 @@ function nativeHorizontalWheelEventMsg() {
|
|||||||
case "mac": return 0; // value is unused, can be anything
|
case "mac": return 0; // value is unused, can be anything
|
||||||
case "linux": return 4; // value is unused, pass GDK_SCROLL_SMOOTH anyway
|
case "linux": return 4; // value is unused, pass GDK_SCROLL_SMOOTH anyway
|
||||||
}
|
}
|
||||||
throw "Native wheel events not supported on platform " + getPlatform();
|
throw new Error("Native wheel events not supported on platform " + getPlatform());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Given an event target which may be a window or an element, get the associated window.
|
// Given an event target which may be a window or an element, get the associated window.
|
||||||
@ -81,7 +81,7 @@ function nativeMouseDownEventMsg() {
|
|||||||
case "linux": return 4; // GDK_BUTTON_PRESS
|
case "linux": return 4; // GDK_BUTTON_PRESS
|
||||||
case "android": return 5; // ACTION_POINTER_DOWN
|
case "android": return 5; // ACTION_POINTER_DOWN
|
||||||
}
|
}
|
||||||
throw "Native mouse-down events not supported on platform " + getPlatform();
|
throw new Error("Native mouse-down events not supported on platform " + getPlatform());
|
||||||
}
|
}
|
||||||
|
|
||||||
function nativeMouseMoveEventMsg() {
|
function nativeMouseMoveEventMsg() {
|
||||||
@ -91,7 +91,7 @@ function nativeMouseMoveEventMsg() {
|
|||||||
case "linux": return 3; // GDK_MOTION_NOTIFY
|
case "linux": return 3; // GDK_MOTION_NOTIFY
|
||||||
case "android": return 7; // ACTION_HOVER_MOVE
|
case "android": return 7; // ACTION_HOVER_MOVE
|
||||||
}
|
}
|
||||||
throw "Native mouse-move events not supported on platform " + getPlatform();
|
throw new Error("Native mouse-move events not supported on platform " + getPlatform());
|
||||||
}
|
}
|
||||||
|
|
||||||
function nativeMouseUpEventMsg() {
|
function nativeMouseUpEventMsg() {
|
||||||
@ -101,7 +101,7 @@ function nativeMouseUpEventMsg() {
|
|||||||
case "linux": return 7; // GDK_BUTTON_RELEASE
|
case "linux": return 7; // GDK_BUTTON_RELEASE
|
||||||
case "android": return 6; // ACTION_POINTER_UP
|
case "android": return 6; // ACTION_POINTER_UP
|
||||||
}
|
}
|
||||||
throw "Native mouse-up events not supported on platform " + getPlatform();
|
throw new Error("Native mouse-up events not supported on platform " + getPlatform());
|
||||||
}
|
}
|
||||||
|
|
||||||
function getBoundingClientRectRelativeToVisualViewport(aElement) {
|
function getBoundingClientRectRelativeToVisualViewport(aElement) {
|
||||||
@ -164,7 +164,7 @@ function rectRelativeToScreen(aElement) {
|
|||||||
function synthesizeNativeWheel(aTarget, aX, aY, aDeltaX, aDeltaY, aObserver) {
|
function synthesizeNativeWheel(aTarget, aX, aY, aDeltaX, aDeltaY, aObserver) {
|
||||||
var pt = coordinatesRelativeToScreen(aX, aY, aTarget);
|
var pt = coordinatesRelativeToScreen(aX, aY, aTarget);
|
||||||
if (aDeltaX && aDeltaY) {
|
if (aDeltaX && aDeltaY) {
|
||||||
throw "Simultaneous wheeling of horizontal and vertical is not supported on all platforms.";
|
throw new Error("Simultaneous wheeling of horizontal and vertical is not supported on all platforms.");
|
||||||
}
|
}
|
||||||
aDeltaX = nativeScrollUnits(aTarget, aDeltaX);
|
aDeltaX = nativeScrollUnits(aTarget, aDeltaX);
|
||||||
aDeltaY = nativeScrollUnits(aTarget, aDeltaY);
|
aDeltaY = nativeScrollUnits(aTarget, aDeltaY);
|
||||||
@ -277,7 +277,10 @@ function* synthesizeNativeTouchSequences(aTarget, aPositions, aObserver = null,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (aPositions[i].length != aTouchIds.length) {
|
if (aPositions[i].length != aTouchIds.length) {
|
||||||
throw "aPositions[" + i + "] did not have the expected number of positions; expected " + aTouchIds.length + " touch points but found " + aPositions[i].length;
|
throw new Error(
|
||||||
|
`aPositions[${i}] did not have the expected number of positions; ` +
|
||||||
|
`expected ${aTouchIds.length} touch points but found ${aPositions[i].length}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
for (let j = 0; j < aTouchIds.length; j++) {
|
for (let j = 0; j < aTouchIds.length; j++) {
|
||||||
if (aPositions[i][j] != null) {
|
if (aPositions[i][j] != null) {
|
||||||
@ -286,7 +289,7 @@ function* synthesizeNativeTouchSequences(aTarget, aPositions, aObserver = null,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (lastNonNullValue < 0) {
|
if (lastNonNullValue < 0) {
|
||||||
throw "All values in positions array were null!";
|
throw new Error("All values in positions array were null!");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert a row of nulls at the end of aPositions, to ensure that all
|
// Insert a row of nulls at the end of aPositions, to ensure that all
|
||||||
|
@ -162,7 +162,7 @@ function promiseApzRepaintsFlushed(aWindow = window) {
|
|||||||
|
|
||||||
function flushApzRepaints(aCallback, aWindow = window) {
|
function flushApzRepaints(aCallback, aWindow = window) {
|
||||||
if (!aCallback) {
|
if (!aCallback) {
|
||||||
throw "A callback must be provided!";
|
throw new Error("A callback must be provided!");
|
||||||
}
|
}
|
||||||
promiseApzRepaintsFlushed(aWindow).then(aCallback);
|
promiseApzRepaintsFlushed(aWindow).then(aCallback);
|
||||||
}
|
}
|
||||||
|
@ -24,3 +24,4 @@ use Mozilla's I18n APIs.
|
|||||||
locale
|
locale
|
||||||
dataintl
|
dataintl
|
||||||
localization
|
localization
|
||||||
|
l10n/l10n/index
|
||||||
|
118
js/public/ForOfIterator.h
Normal file
118
js/public/ForOfIterator.h
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||||
|
* vim: set ts=8 sts=2 et sw=2 tw=80:
|
||||||
|
* 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/. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A convenience class that makes it easy to perform the operations of a for-of
|
||||||
|
* loop.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef js_ForOfIterator_h
|
||||||
|
#define js_ForOfIterator_h
|
||||||
|
|
||||||
|
#include "mozilla/Attributes.h" // MOZ_MUST_USE, MOZ_STACK_CLASS
|
||||||
|
|
||||||
|
#include <stdint.h> // UINT32_MAX, uint32_t
|
||||||
|
|
||||||
|
#include "jstypes.h" // JS_PUBLIC_API
|
||||||
|
|
||||||
|
#include "js/RootingAPI.h" // JS::{Handle,Rooted}
|
||||||
|
#include "js/Value.h" // JS::Value, JS::{,Mutable}Handle<JS::Value>
|
||||||
|
|
||||||
|
struct JSContext;
|
||||||
|
class JSObject;
|
||||||
|
|
||||||
|
namespace JS {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A convenience class for imitating a JS for-of loop. Typical usage:
|
||||||
|
*
|
||||||
|
* JS::ForOfIterator it(cx);
|
||||||
|
* if (!it.init(iterable)) {
|
||||||
|
* return false;
|
||||||
|
* }
|
||||||
|
* JS::Rooted<JS::Value> val(cx);
|
||||||
|
* while (true) {
|
||||||
|
* bool done;
|
||||||
|
* if (!it.next(&val, &done)) {
|
||||||
|
* return false;
|
||||||
|
* }
|
||||||
|
* if (done) {
|
||||||
|
* break;
|
||||||
|
* }
|
||||||
|
* if (!DoStuff(cx, val)) {
|
||||||
|
* return false;
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
class MOZ_STACK_CLASS JS_PUBLIC_API ForOfIterator {
|
||||||
|
protected:
|
||||||
|
JSContext* cx_;
|
||||||
|
|
||||||
|
// Use the ForOfPIC on the global object (see vm/GlobalObject.h) to try to
|
||||||
|
// optimize iteration across arrays.
|
||||||
|
//
|
||||||
|
// Case 1: Regular Iteration
|
||||||
|
// iterator - pointer to the iterator object.
|
||||||
|
// nextMethod - value of |iterator|.next.
|
||||||
|
// index - fixed to NOT_ARRAY (== UINT32_MAX)
|
||||||
|
//
|
||||||
|
// Case 2: Optimized Array Iteration
|
||||||
|
// iterator - pointer to the array object.
|
||||||
|
// nextMethod - the undefined value.
|
||||||
|
// index - current position in array.
|
||||||
|
//
|
||||||
|
// The cases are distinguished by whether |index == NOT_ARRAY|.
|
||||||
|
Rooted<JSObject*> iterator;
|
||||||
|
Rooted<Value> nextMethod;
|
||||||
|
|
||||||
|
static constexpr uint32_t NOT_ARRAY = UINT32_MAX;
|
||||||
|
|
||||||
|
uint32_t index = NOT_ARRAY;
|
||||||
|
|
||||||
|
ForOfIterator(const ForOfIterator&) = delete;
|
||||||
|
ForOfIterator& operator=(const ForOfIterator&) = delete;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ForOfIterator(JSContext* cx)
|
||||||
|
: cx_(cx), iterator(cx), nextMethod(cx) {}
|
||||||
|
|
||||||
|
enum NonIterableBehavior { ThrowOnNonIterable, AllowNonIterable };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the iterator. If AllowNonIterable is passed then if getting
|
||||||
|
* the @@iterator property from iterable returns undefined init() will just
|
||||||
|
* return true instead of throwing. Callers must then check
|
||||||
|
* valueIsIterable() before continuing with the iteration.
|
||||||
|
*/
|
||||||
|
MOZ_MUST_USE bool init(
|
||||||
|
Handle<Value> iterable,
|
||||||
|
NonIterableBehavior nonIterableBehavior = ThrowOnNonIterable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the next value from the iterator. If false *done is true
|
||||||
|
* after this call, do not examine val.
|
||||||
|
*/
|
||||||
|
MOZ_MUST_USE bool next(MutableHandle<Value> val, bool* done);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close the iterator.
|
||||||
|
* For the case that completion type is throw.
|
||||||
|
*/
|
||||||
|
void closeThrow();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If initialized with throwOnNonCallable = false, check whether
|
||||||
|
* the value is iterable.
|
||||||
|
*/
|
||||||
|
bool valueIsIterable() const { return iterator; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline bool nextFromOptimizedArray(MutableHandle<Value> val, bool* done);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace JS
|
||||||
|
|
||||||
|
#endif // js_ForOfIterator_h
|
@ -19,6 +19,7 @@ typedef uint32_t HashNumber;
|
|||||||
#include "js/ContextOptions.h"
|
#include "js/ContextOptions.h"
|
||||||
#include "js/Conversions.h"
|
#include "js/Conversions.h"
|
||||||
#include "js/Date.h"
|
#include "js/Date.h"
|
||||||
|
#include "js/ForOfIterator.h"
|
||||||
#include "js/Initialization.h"
|
#include "js/Initialization.h"
|
||||||
#include "js/MemoryMetrics.h"
|
#include "js/MemoryMetrics.h"
|
||||||
#include "js/PropertySpec.h"
|
#include "js/PropertySpec.h"
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include "gc/Heap.h"
|
#include "gc/Heap.h"
|
||||||
#include "js/Debug.h"
|
#include "js/Debug.h"
|
||||||
|
#include "js/ForOfIterator.h" // JS::ForOfIterator
|
||||||
#include "js/PropertySpec.h"
|
#include "js/PropertySpec.h"
|
||||||
#include "vm/AsyncFunction.h"
|
#include "vm/AsyncFunction.h"
|
||||||
#include "vm/AsyncIteration.h"
|
#include "vm/AsyncIteration.h"
|
||||||
|
@ -693,21 +693,6 @@ struct GlobalAccess {
|
|||||||
|
|
||||||
typedef Vector<GlobalAccess, 0, SystemAllocPolicy> GlobalAccessVector;
|
typedef Vector<GlobalAccess, 0, SystemAllocPolicy> GlobalAccessVector;
|
||||||
|
|
||||||
// A CallFarJump records the offset of a jump that needs to be patched to a
|
|
||||||
// call at the end of the module when all calls have been emitted.
|
|
||||||
|
|
||||||
struct CallFarJump {
|
|
||||||
uint32_t funcIndex;
|
|
||||||
jit::CodeOffset jump;
|
|
||||||
|
|
||||||
CallFarJump(uint32_t funcIndex, jit::CodeOffset jump)
|
|
||||||
: funcIndex(funcIndex), jump(jump) {}
|
|
||||||
|
|
||||||
void offsetBy(size_t delta) { jump.offsetBy(delta); }
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef Vector<CallFarJump, 0, SystemAllocPolicy> CallFarJumpVector;
|
|
||||||
|
|
||||||
} // namespace wasm
|
} // namespace wasm
|
||||||
|
|
||||||
namespace jit {
|
namespace jit {
|
||||||
@ -717,7 +702,6 @@ class AssemblerShared {
|
|||||||
wasm::CallSiteVector callSites_;
|
wasm::CallSiteVector callSites_;
|
||||||
wasm::CallSiteTargetVector callSiteTargets_;
|
wasm::CallSiteTargetVector callSiteTargets_;
|
||||||
wasm::TrapSiteVectorArray trapSites_;
|
wasm::TrapSiteVectorArray trapSites_;
|
||||||
wasm::CallFarJumpVector callFarJumps_;
|
|
||||||
wasm::SymbolicAccessVector symbolicAccesses_;
|
wasm::SymbolicAccessVector symbolicAccesses_;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -756,9 +740,6 @@ class AssemblerShared {
|
|||||||
void append(wasm::Trap trap, wasm::TrapSite site) {
|
void append(wasm::Trap trap, wasm::TrapSite site) {
|
||||||
enoughMemory_ &= trapSites_[trap].append(site);
|
enoughMemory_ &= trapSites_[trap].append(site);
|
||||||
}
|
}
|
||||||
void append(wasm::CallFarJump jmp) {
|
|
||||||
enoughMemory_ &= callFarJumps_.append(jmp);
|
|
||||||
}
|
|
||||||
void append(const wasm::MemoryAccessDesc& access, uint32_t pcOffset) {
|
void append(const wasm::MemoryAccessDesc& access, uint32_t pcOffset) {
|
||||||
appendOutOfBoundsTrap(access.trapOffset(), pcOffset);
|
appendOutOfBoundsTrap(access.trapOffset(), pcOffset);
|
||||||
}
|
}
|
||||||
@ -773,7 +754,6 @@ class AssemblerShared {
|
|||||||
wasm::CallSiteVector& callSites() { return callSites_; }
|
wasm::CallSiteVector& callSites() { return callSites_; }
|
||||||
wasm::CallSiteTargetVector& callSiteTargets() { return callSiteTargets_; }
|
wasm::CallSiteTargetVector& callSiteTargets() { return callSiteTargets_; }
|
||||||
wasm::TrapSiteVectorArray& trapSites() { return trapSites_; }
|
wasm::TrapSiteVectorArray& trapSites() { return trapSites_; }
|
||||||
wasm::CallFarJumpVector& callFarJumps() { return callFarJumps_; }
|
|
||||||
wasm::SymbolicAccessVector& symbolicAccesses() { return symbolicAccesses_; }
|
wasm::SymbolicAccessVector& symbolicAccesses() { return symbolicAccesses_; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "js/ForOfIterator.h"
|
||||||
#include "jsapi-tests/tests.h"
|
#include "jsapi-tests/tests.h"
|
||||||
|
|
||||||
BEGIN_TEST(testForOfIterator_basicNonIterable) {
|
BEGIN_TEST(testForOfIterator_basicNonIterable) {
|
||||||
|
@ -3165,93 +3165,6 @@ extern JS_PUBLIC_API RefPtr<WasmModule> GetWasmModule(HandleObject obj);
|
|||||||
extern JS_PUBLIC_API RefPtr<WasmModule> DeserializeWasmModule(
|
extern JS_PUBLIC_API RefPtr<WasmModule> DeserializeWasmModule(
|
||||||
PRFileDesc* bytecode, JS::UniqueChars filename, unsigned line);
|
PRFileDesc* bytecode, JS::UniqueChars filename, unsigned line);
|
||||||
|
|
||||||
/**
|
|
||||||
* Convenience class for imitating a JS level for-of loop. Typical usage:
|
|
||||||
*
|
|
||||||
* ForOfIterator it(cx);
|
|
||||||
* if (!it.init(iterable)) {
|
|
||||||
* return false;
|
|
||||||
* }
|
|
||||||
* RootedValue val(cx);
|
|
||||||
* while (true) {
|
|
||||||
* bool done;
|
|
||||||
* if (!it.next(&val, &done)) {
|
|
||||||
* return false;
|
|
||||||
* }
|
|
||||||
* if (done) {
|
|
||||||
* break;
|
|
||||||
* }
|
|
||||||
* if (!DoStuff(cx, val)) {
|
|
||||||
* return false;
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
class MOZ_STACK_CLASS JS_PUBLIC_API ForOfIterator {
|
|
||||||
protected:
|
|
||||||
JSContext* cx_;
|
|
||||||
/*
|
|
||||||
* Use the ForOfPIC on the global object (see vm/GlobalObject.h) to try
|
|
||||||
* to optimize iteration across arrays.
|
|
||||||
*
|
|
||||||
* Case 1: Regular Iteration
|
|
||||||
* iterator - pointer to the iterator object.
|
|
||||||
* nextMethod - value of |iterator|.next.
|
|
||||||
* index - fixed to NOT_ARRAY (== UINT32_MAX)
|
|
||||||
*
|
|
||||||
* Case 2: Optimized Array Iteration
|
|
||||||
* iterator - pointer to the array object.
|
|
||||||
* nextMethod - the undefined value.
|
|
||||||
* index - current position in array.
|
|
||||||
*
|
|
||||||
* The cases are distinguished by whether or not |index| is equal to
|
|
||||||
* NOT_ARRAY.
|
|
||||||
*/
|
|
||||||
JS::RootedObject iterator;
|
|
||||||
JS::RootedValue nextMethod;
|
|
||||||
uint32_t index;
|
|
||||||
|
|
||||||
static const uint32_t NOT_ARRAY = UINT32_MAX;
|
|
||||||
|
|
||||||
ForOfIterator(const ForOfIterator&) = delete;
|
|
||||||
ForOfIterator& operator=(const ForOfIterator&) = delete;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit ForOfIterator(JSContext* cx)
|
|
||||||
: cx_(cx), iterator(cx_), nextMethod(cx), index(NOT_ARRAY) {}
|
|
||||||
|
|
||||||
enum NonIterableBehavior { ThrowOnNonIterable, AllowNonIterable };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize the iterator. If AllowNonIterable is passed then if getting
|
|
||||||
* the @@iterator property from iterable returns undefined init() will just
|
|
||||||
* return true instead of throwing. Callers must then check
|
|
||||||
* valueIsIterable() before continuing with the iteration.
|
|
||||||
*/
|
|
||||||
bool init(JS::HandleValue iterable,
|
|
||||||
NonIterableBehavior nonIterableBehavior = ThrowOnNonIterable);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the next value from the iterator. If false *done is true
|
|
||||||
* after this call, do not examine val.
|
|
||||||
*/
|
|
||||||
bool next(JS::MutableHandleValue val, bool* done);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Close the iterator.
|
|
||||||
* For the case that completion type is throw.
|
|
||||||
*/
|
|
||||||
void closeThrow();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If initialized with throwOnNonCallable = false, check whether
|
|
||||||
* the value is iterable.
|
|
||||||
*/
|
|
||||||
bool valueIsIterable() const { return iterator; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
inline bool nextFromOptimizedArray(MutableHandleValue val, bool* done);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If a large allocation fails when calling pod_{calloc,realloc}CanGC, the JS
|
* If a large allocation fails when calling pod_{calloc,realloc}CanGC, the JS
|
||||||
* engine may call the large-allocation-failure callback, if set, to allow the
|
* engine may call the large-allocation-failure callback, if set, to allow the
|
||||||
|
@ -131,6 +131,7 @@ EXPORTS.js += [
|
|||||||
'../public/Debug.h',
|
'../public/Debug.h',
|
||||||
'../public/Equality.h',
|
'../public/Equality.h',
|
||||||
'../public/ErrorReport.h',
|
'../public/ErrorReport.h',
|
||||||
|
'../public/ForOfIterator.h',
|
||||||
'../public/GCAnnotations.h',
|
'../public/GCAnnotations.h',
|
||||||
'../public/GCAPI.h',
|
'../public/GCAPI.h',
|
||||||
'../public/GCHashTable.h',
|
'../public/GCHashTable.h',
|
||||||
|
@ -4,8 +4,7 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "jsapi.h"
|
#include "js/ForOfIterator.h"
|
||||||
|
|
||||||
#include "vm/Interpreter.h"
|
#include "vm/Interpreter.h"
|
||||||
#include "vm/JSContext.h"
|
#include "vm/JSContext.h"
|
||||||
#include "vm/JSObject.h"
|
#include "vm/JSObject.h"
|
||||||
|
@ -1149,9 +1149,7 @@ bool wasm::EnsureBuiltinThunksInitialized() {
|
|||||||
|
|
||||||
MOZ_ASSERT(masm.callSites().empty());
|
MOZ_ASSERT(masm.callSites().empty());
|
||||||
MOZ_ASSERT(masm.callSiteTargets().empty());
|
MOZ_ASSERT(masm.callSiteTargets().empty());
|
||||||
MOZ_ASSERT(masm.callFarJumps().empty());
|
|
||||||
MOZ_ASSERT(masm.trapSites().empty());
|
MOZ_ASSERT(masm.trapSites().empty());
|
||||||
MOZ_ASSERT(masm.callFarJumps().empty());
|
|
||||||
|
|
||||||
ExecutableAllocator::cacheFlush(thunks->codeBase, thunks->codeSize);
|
ExecutableAllocator::cacheFlush(thunks->codeBase, thunks->codeSize);
|
||||||
if (!ExecutableAllocator::makeExecutable(thunks->codeBase,
|
if (!ExecutableAllocator::makeExecutable(thunks->codeBase,
|
||||||
|
@ -685,9 +685,7 @@ bool LazyStubTier::createMany(const Uint32Vector& funcExportIndices,
|
|||||||
|
|
||||||
MOZ_ASSERT(masm.callSites().empty());
|
MOZ_ASSERT(masm.callSites().empty());
|
||||||
MOZ_ASSERT(masm.callSiteTargets().empty());
|
MOZ_ASSERT(masm.callSiteTargets().empty());
|
||||||
MOZ_ASSERT(masm.callFarJumps().empty());
|
|
||||||
MOZ_ASSERT(masm.trapSites().empty());
|
MOZ_ASSERT(masm.trapSites().empty());
|
||||||
MOZ_ASSERT(masm.callFarJumps().empty());
|
|
||||||
|
|
||||||
if (masm.oom()) {
|
if (masm.oom()) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -52,7 +52,6 @@ bool CompiledCode::swap(MacroAssembler& masm) {
|
|||||||
callSites.swap(masm.callSites());
|
callSites.swap(masm.callSites());
|
||||||
callSiteTargets.swap(masm.callSiteTargets());
|
callSiteTargets.swap(masm.callSiteTargets());
|
||||||
trapSites.swap(masm.trapSites());
|
trapSites.swap(masm.trapSites());
|
||||||
callFarJumps.swap(masm.callFarJumps());
|
|
||||||
symbolicAccesses.swap(masm.symbolicAccesses());
|
symbolicAccesses.swap(masm.symbolicAccesses());
|
||||||
codeLabels.swap(masm.codeLabels());
|
codeLabels.swap(masm.codeLabels());
|
||||||
return true;
|
return true;
|
||||||
@ -668,13 +667,6 @@ bool ModuleGenerator::linkCompiledCode(CompiledCode& code) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto callFarJumpOp = [=](uint32_t, CallFarJump* cfj) {
|
|
||||||
cfj->offsetBy(offsetInModule);
|
|
||||||
};
|
|
||||||
if (!AppendForEach(&callFarJumps_, code.callFarJumps, callFarJumpOp)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const SymbolicAccess& access : code.symbolicAccesses) {
|
for (const SymbolicAccess& access : code.symbolicAccesses) {
|
||||||
uint32_t patchAt = offsetInModule + access.patchAt.offset();
|
uint32_t patchAt = offsetInModule + access.patchAt.offset();
|
||||||
if (!linkData_->symbolicLinks[access.target].append(patchAt)) {
|
if (!linkData_->symbolicLinks[access.target].append(patchAt)) {
|
||||||
@ -923,7 +915,6 @@ bool ModuleGenerator::finishCodegen() {
|
|||||||
MOZ_ASSERT(masm_.callSites().empty());
|
MOZ_ASSERT(masm_.callSites().empty());
|
||||||
MOZ_ASSERT(masm_.callSiteTargets().empty());
|
MOZ_ASSERT(masm_.callSiteTargets().empty());
|
||||||
MOZ_ASSERT(masm_.trapSites().empty());
|
MOZ_ASSERT(masm_.trapSites().empty());
|
||||||
MOZ_ASSERT(masm_.callFarJumps().empty());
|
|
||||||
MOZ_ASSERT(masm_.symbolicAccesses().empty());
|
MOZ_ASSERT(masm_.symbolicAccesses().empty());
|
||||||
MOZ_ASSERT(masm_.codeLabels().empty());
|
MOZ_ASSERT(masm_.codeLabels().empty());
|
||||||
|
|
||||||
@ -1262,7 +1253,6 @@ size_t CompiledCode::sizeOfExcludingThis(
|
|||||||
codeRanges.sizeOfExcludingThis(mallocSizeOf) +
|
codeRanges.sizeOfExcludingThis(mallocSizeOf) +
|
||||||
callSites.sizeOfExcludingThis(mallocSizeOf) +
|
callSites.sizeOfExcludingThis(mallocSizeOf) +
|
||||||
callSiteTargets.sizeOfExcludingThis(mallocSizeOf) + trapSitesSize +
|
callSiteTargets.sizeOfExcludingThis(mallocSizeOf) + trapSitesSize +
|
||||||
callFarJumps.sizeOfExcludingThis(mallocSizeOf) +
|
|
||||||
symbolicAccesses.sizeOfExcludingThis(mallocSizeOf) +
|
symbolicAccesses.sizeOfExcludingThis(mallocSizeOf) +
|
||||||
codeLabels.sizeOfExcludingThis(mallocSizeOf);
|
codeLabels.sizeOfExcludingThis(mallocSizeOf);
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,6 @@ struct CompiledCode {
|
|||||||
CallSiteVector callSites;
|
CallSiteVector callSites;
|
||||||
CallSiteTargetVector callSiteTargets;
|
CallSiteTargetVector callSiteTargets;
|
||||||
TrapSiteVectorArray trapSites;
|
TrapSiteVectorArray trapSites;
|
||||||
CallFarJumpVector callFarJumps;
|
|
||||||
SymbolicAccessVector symbolicAccesses;
|
SymbolicAccessVector symbolicAccesses;
|
||||||
jit::CodeLabelVector codeLabels;
|
jit::CodeLabelVector codeLabels;
|
||||||
StackMaps stackMaps;
|
StackMaps stackMaps;
|
||||||
@ -75,7 +74,6 @@ struct CompiledCode {
|
|||||||
callSites.clear();
|
callSites.clear();
|
||||||
callSiteTargets.clear();
|
callSiteTargets.clear();
|
||||||
trapSites.clear();
|
trapSites.clear();
|
||||||
callFarJumps.clear();
|
|
||||||
symbolicAccesses.clear();
|
symbolicAccesses.clear();
|
||||||
codeLabels.clear();
|
codeLabels.clear();
|
||||||
stackMaps.clear();
|
stackMaps.clear();
|
||||||
@ -85,8 +83,7 @@ struct CompiledCode {
|
|||||||
bool empty() {
|
bool empty() {
|
||||||
return bytes.empty() && codeRanges.empty() && callSites.empty() &&
|
return bytes.empty() && codeRanges.empty() && callSites.empty() &&
|
||||||
callSiteTargets.empty() && trapSites.empty() &&
|
callSiteTargets.empty() && trapSites.empty() &&
|
||||||
callFarJumps.empty() && symbolicAccesses.empty() &&
|
symbolicAccesses.empty() && codeLabels.empty() && stackMaps.empty();
|
||||||
codeLabels.empty() && stackMaps.empty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
|
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
|
||||||
@ -137,6 +134,12 @@ struct CompileTask {
|
|||||||
class MOZ_STACK_CLASS ModuleGenerator {
|
class MOZ_STACK_CLASS ModuleGenerator {
|
||||||
typedef Vector<CompileTask, 0, SystemAllocPolicy> CompileTaskVector;
|
typedef Vector<CompileTask, 0, SystemAllocPolicy> CompileTaskVector;
|
||||||
typedef Vector<jit::CodeOffset, 0, SystemAllocPolicy> CodeOffsetVector;
|
typedef Vector<jit::CodeOffset, 0, SystemAllocPolicy> CodeOffsetVector;
|
||||||
|
struct CallFarJump {
|
||||||
|
uint32_t funcIndex;
|
||||||
|
jit::CodeOffset jump;
|
||||||
|
CallFarJump(uint32_t fi, jit::CodeOffset j) : funcIndex(fi), jump(j) {}
|
||||||
|
};
|
||||||
|
typedef Vector<CallFarJump, 0, SystemAllocPolicy> CallFarJumpVector;
|
||||||
|
|
||||||
// Constant parameters
|
// Constant parameters
|
||||||
SharedCompileArgs const compileArgs_;
|
SharedCompileArgs const compileArgs_;
|
||||||
|
@ -5528,6 +5528,26 @@ TEST_F(JsepSessionTest, AudioCallAnswererUsesActpass) {
|
|||||||
ASSERT_EQ(kJsepStateHaveLocalOffer, mSessionOff->GetState());
|
ASSERT_EQ(kJsepStateHaveLocalOffer, mSessionOff->GetState());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Verify that 'actpass' in reoffer from previous answerer doesn't result
|
||||||
|
// in a role switch.
|
||||||
|
TEST_F(JsepSessionTest, AudioCallPreviousAnswererUsesActpassInReoffer) {
|
||||||
|
types.push_back(SdpMediaSection::kAudio);
|
||||||
|
AddTracks(*mSessionOff, "audio");
|
||||||
|
AddTracks(*mSessionAns, "audio");
|
||||||
|
|
||||||
|
OfferAnswer();
|
||||||
|
|
||||||
|
ValidateSetupAttribute(*mSessionOff, SdpSetupAttribute::kActpass);
|
||||||
|
ValidateSetupAttribute(*mSessionAns, SdpSetupAttribute::kActive);
|
||||||
|
|
||||||
|
SwapOfferAnswerRoles();
|
||||||
|
|
||||||
|
OfferAnswer();
|
||||||
|
|
||||||
|
ValidateSetupAttribute(*mSessionOff, SdpSetupAttribute::kActpass);
|
||||||
|
ValidateSetupAttribute(*mSessionAns, SdpSetupAttribute::kPassive);
|
||||||
|
}
|
||||||
|
|
||||||
// Disabled: See Bug 1329028
|
// Disabled: See Bug 1329028
|
||||||
TEST_F(JsepSessionTest, DISABLED_AudioCallOffererAttemptsSetupRoleSwitch) {
|
TEST_F(JsepSessionTest, DISABLED_AudioCallOffererAttemptsSetupRoleSwitch) {
|
||||||
types.push_back(SdpMediaSection::kAudio);
|
types.push_back(SdpMediaSection::kAudio);
|
||||||
|
@ -546,8 +546,15 @@ nsresult JsepSessionImpl::CreateAnswerMsection(
|
|||||||
MOZ_ASSERT(transceiver.GetMid() == msection.GetAttributeList().GetMid());
|
MOZ_ASSERT(transceiver.GetMid() == msection.GetAttributeList().GetMid());
|
||||||
|
|
||||||
SdpSetupAttribute::Role role;
|
SdpSetupAttribute::Role role;
|
||||||
rv = DetermineAnswererSetupRole(remoteMsection, &role);
|
if (transceiver.mTransport.mDtls && !IsIceRestarting()) {
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
role = (transceiver.mTransport.mDtls->mRole ==
|
||||||
|
JsepDtlsTransport::kJsepDtlsClient)
|
||||||
|
? SdpSetupAttribute::kActive
|
||||||
|
: SdpSetupAttribute::kPassive;
|
||||||
|
} else {
|
||||||
|
rv = DetermineAnswererSetupRole(remoteMsection, &role);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
}
|
||||||
|
|
||||||
rv = AddTransportAttributes(&msection, role);
|
rv = AddTransportAttributes(&msection, role);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
@ -1072,6 +1079,7 @@ nsresult JsepSessionImpl::FinalizeTransport(const SdpAttributeList& remote,
|
|||||||
if (!transport->mIce || transport->mIce->mUfrag != remote.GetIceUfrag() ||
|
if (!transport->mIce || transport->mIce->mUfrag != remote.GetIceUfrag() ||
|
||||||
transport->mIce->mPwd != remote.GetIcePwd()) {
|
transport->mIce->mPwd != remote.GetIcePwd()) {
|
||||||
UniquePtr<JsepIceTransport> ice = MakeUnique<JsepIceTransport>();
|
UniquePtr<JsepIceTransport> ice = MakeUnique<JsepIceTransport>();
|
||||||
|
transport->mDtls = nullptr;
|
||||||
|
|
||||||
// We do sanity-checking for these in ParseSdp
|
// We do sanity-checking for these in ParseSdp
|
||||||
ice->mUfrag = remote.GetIceUfrag();
|
ice->mUfrag = remote.GetIceUfrag();
|
||||||
|
@ -48,7 +48,7 @@ LoginManagerPrompter.prototype = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (!this.__strBundle)
|
if (!this.__strBundle)
|
||||||
throw "String bundle for Login Manager not present!";
|
throw new Error("String bundle for Login Manager not present!");
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.__strBundle;
|
return this.__strBundle;
|
||||||
|
@ -109,7 +109,7 @@ NSSDialogs.prototype = {
|
|||||||
setPKCS12FilePassword: function(aCtx, aPassword) {
|
setPKCS12FilePassword: function(aCtx, aPassword) {
|
||||||
// this dialog is never shown in Fennec; in Desktop it is shown while backing up a personal
|
// this dialog is never shown in Fennec; in Desktop it is shown while backing up a personal
|
||||||
// certificate to a file via Preferences->Advanced->Encryption->View Certificates->Your Certificates
|
// certificate to a file via Preferences->Advanced->Encryption->View Certificates->Your Certificates
|
||||||
throw "Unimplemented";
|
throw new Error("Unimplemented");
|
||||||
},
|
},
|
||||||
|
|
||||||
getPKCS12FilePassword: function(aCtx, aPassword) {
|
getPKCS12FilePassword: function(aCtx, aPassword) {
|
||||||
|
@ -719,11 +719,11 @@ var PromptUtils = {
|
|||||||
// channel's actual destination.
|
// channel's actual destination.
|
||||||
if (aAuthInfo.flags & Ci.nsIAuthInformation.AUTH_PROXY) {
|
if (aAuthInfo.flags & Ci.nsIAuthInformation.AUTH_PROXY) {
|
||||||
if (!(aChannel instanceof Ci.nsIProxiedChannel))
|
if (!(aChannel instanceof Ci.nsIProxiedChannel))
|
||||||
throw "proxy auth needs nsIProxiedChannel";
|
throw new Error("proxy auth needs nsIProxiedChannel");
|
||||||
|
|
||||||
let info = aChannel.proxyInfo;
|
let info = aChannel.proxyInfo;
|
||||||
if (!info)
|
if (!info)
|
||||||
throw "proxy auth needs nsIProxyInfo";
|
throw new Error("proxy auth needs nsIProxyInfo");
|
||||||
|
|
||||||
// Proxies don't have a scheme, but we'll use "moz-proxy://"
|
// Proxies don't have a scheme, but we'll use "moz-proxy://"
|
||||||
// so that it's more obvious what the login is for.
|
// so that it's more obvious what the login is for.
|
||||||
|
@ -1422,12 +1422,12 @@ SessionStore.prototype = {
|
|||||||
try {
|
try {
|
||||||
state = JSON.parse(aData);
|
state = JSON.parse(aData);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw "Invalid session JSON: " + aData;
|
throw new Error("Invalid session JSON: " + aData);
|
||||||
}
|
}
|
||||||
|
|
||||||
// To do a restore, we must have at least one window with one tab
|
// To do a restore, we must have at least one window with one tab
|
||||||
if (!state || state.windows.length == 0 || !state.windows[0].tabs || state.windows[0].tabs.length == 0) {
|
if (!state || state.windows.length == 0 || !state.windows[0].tabs || state.windows[0].tabs.length == 0) {
|
||||||
throw "Invalid session JSON: " + aData;
|
throw new Error("Invalid session JSON: " + aData);
|
||||||
}
|
}
|
||||||
|
|
||||||
let window = Services.wm.getMostRecentWindow("navigator:browser");
|
let window = Services.wm.getMostRecentWindow("navigator:browser");
|
||||||
@ -1491,7 +1491,7 @@ SessionStore.prototype = {
|
|||||||
|
|
||||||
getClosedTabs(aWindow) {
|
getClosedTabs(aWindow) {
|
||||||
if (!aWindow.__SSID) {
|
if (!aWindow.__SSID) {
|
||||||
throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
|
throw new Error(Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this._windows[aWindow.__SSID].closedTabs;
|
return this._windows[aWindow.__SSID].closedTabs;
|
||||||
@ -1499,7 +1499,7 @@ SessionStore.prototype = {
|
|||||||
|
|
||||||
undoCloseTab(aWindow, aCloseTabData) {
|
undoCloseTab(aWindow, aCloseTabData) {
|
||||||
if (!aWindow.__SSID) {
|
if (!aWindow.__SSID) {
|
||||||
throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
|
throw new Error(Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the tab data is in the closedTabs array, remove it.
|
// If the tab data is in the closedTabs array, remove it.
|
||||||
@ -1562,7 +1562,7 @@ SessionStore.prototype = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!aWindow.__SSID) {
|
if (!aWindow.__SSID) {
|
||||||
throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
|
throw new Error(Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
|
||||||
}
|
}
|
||||||
|
|
||||||
let closedTabs = this._windows[aWindow.__SSID].closedTabs;
|
let closedTabs = this._windows[aWindow.__SSID].closedTabs;
|
||||||
|
@ -118,9 +118,9 @@ GeckoViewPermission.prototype = {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (constraints.video && !sources.some(source => source.type === "videoinput")) {
|
if (constraints.video && !sources.some(source => source.type === "videoinput")) {
|
||||||
throw "no video source";
|
throw new Error("no video source");
|
||||||
} else if (constraints.audio && !sources.some(source => source.type === "audioinput")) {
|
} else if (constraints.audio && !sources.some(source => source.type === "audioinput")) {
|
||||||
throw "no audio source";
|
throw new Error("no audio source");
|
||||||
}
|
}
|
||||||
|
|
||||||
let dispatcher = GeckoViewUtils.getDispatcherForWindow(win);
|
let dispatcher = GeckoViewUtils.getDispatcherForWindow(win);
|
||||||
|
@ -760,11 +760,11 @@ PromptDelegate.prototype = {
|
|||||||
// channel's actual destination.
|
// channel's actual destination.
|
||||||
if (aAuthInfo.flags & Ci.nsIAuthInformation.AUTH_PROXY) {
|
if (aAuthInfo.flags & Ci.nsIAuthInformation.AUTH_PROXY) {
|
||||||
if (!(aChannel instanceof Ci.nsIProxiedChannel)) {
|
if (!(aChannel instanceof Ci.nsIProxiedChannel)) {
|
||||||
throw "proxy auth needs nsIProxiedChannel";
|
throw new Error("proxy auth needs nsIProxiedChannel");
|
||||||
}
|
}
|
||||||
let info = aChannel.proxyInfo;
|
let info = aChannel.proxyInfo;
|
||||||
if (!info) {
|
if (!info) {
|
||||||
throw "proxy auth needs nsIProxyInfo";
|
throw new Error("proxy auth needs nsIProxyInfo");
|
||||||
}
|
}
|
||||||
// Proxies don't have a scheme, but we'll use "moz-proxy://"
|
// Proxies don't have a scheme, but we'll use "moz-proxy://"
|
||||||
// so that it's more obvious what the login is for.
|
// so that it's more obvious what the login is for.
|
||||||
|
@ -132,7 +132,7 @@ var DownloadNotifications = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw "Couldn't find download for " + cookie;
|
throw new Error("Couldn't find download for " + cookie);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ const DEFAULT_WEIGHT = 100;
|
|||||||
// See bug 915424
|
// See bug 915424
|
||||||
function resolveGeckoURI(aURI) {
|
function resolveGeckoURI(aURI) {
|
||||||
if (!aURI)
|
if (!aURI)
|
||||||
throw "Can't resolve an empty uri";
|
throw new Error("Can't resolve an empty uri");
|
||||||
|
|
||||||
if (aURI.startsWith("chrome://")) {
|
if (aURI.startsWith("chrome://")) {
|
||||||
let registry = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIChromeRegistry);
|
let registry = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIChromeRegistry);
|
||||||
@ -168,7 +168,7 @@ var HomeBanner = (function() {
|
|||||||
*/
|
*/
|
||||||
remove: function(id) {
|
remove: function(id) {
|
||||||
if (!(id in _messages)) {
|
if (!(id in _messages)) {
|
||||||
throw "Home.banner: Can't remove message that doesn't exist: id = " + id;
|
throw new Error("Home.banner: Can't remove message that doesn't exist: id = " + id);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete _messages[id];
|
delete _messages[id];
|
||||||
@ -220,10 +220,10 @@ var HomePanels = (function() {
|
|||||||
let id = data.id;
|
let id = data.id;
|
||||||
let options = _registeredPanels[id]();
|
let options = _registeredPanels[id]();
|
||||||
if (!options.auth) {
|
if (!options.auth) {
|
||||||
throw "Home.panels: Invalid auth for panel.id = " + id;
|
throw new Error("Home.panels: Invalid auth for panel.id = " + id);
|
||||||
}
|
}
|
||||||
if (!options.auth.authenticate || typeof options.auth.authenticate !== "function") {
|
if (!options.auth.authenticate || typeof options.auth.authenticate !== "function") {
|
||||||
throw "Home.panels: Invalid auth authenticate function: panel.id = " + this.id;
|
throw new Error("Home.panels: Invalid auth authenticate function: panel.id = " + this.id);
|
||||||
}
|
}
|
||||||
options.auth.authenticate();
|
options.auth.authenticate();
|
||||||
},
|
},
|
||||||
@ -233,13 +233,13 @@ var HomePanels = (function() {
|
|||||||
let view = options.views[data.viewIndex];
|
let view = options.views[data.viewIndex];
|
||||||
|
|
||||||
if (!view) {
|
if (!view) {
|
||||||
throw "Home.panels: Invalid view for panel.id = " + data.panelId
|
throw new Error("Home.panels: Invalid view for panel.id = " +
|
||||||
+ ", view.index = " + data.viewIndex;
|
`${data.panelId}, view.index = ${data.viewIndex}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!view.onrefresh || typeof view.onrefresh !== "function") {
|
if (!view.onrefresh || typeof view.onrefresh !== "function") {
|
||||||
throw "Home.panels: Invalid onrefresh for panel.id = " + data.panelId
|
throw new Error("Home.panels: Invalid onrefresh for panel.id = " +
|
||||||
+ ", view.index = " + data.viewIndex;
|
`${data.panelId}, view.index = ${data.viewIndex}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
view.onrefresh();
|
view.onrefresh();
|
||||||
@ -254,7 +254,7 @@ var HomePanels = (function() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (typeof options.oninstall !== "function") {
|
if (typeof options.oninstall !== "function") {
|
||||||
throw "Home.panels: Invalid oninstall function: panel.id = " + this.id;
|
throw new Error("Home.panels: Invalid oninstall function: panel.id = " + this.id);
|
||||||
}
|
}
|
||||||
options.oninstall();
|
options.oninstall();
|
||||||
},
|
},
|
||||||
@ -268,7 +268,7 @@ var HomePanels = (function() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (typeof options.onuninstall !== "function") {
|
if (typeof options.onuninstall !== "function") {
|
||||||
throw "Home.panels: Invalid onuninstall function: panel.id = " + this.id;
|
throw new Error("Home.panels: Invalid onuninstall function: panel.id = " + this.id);
|
||||||
}
|
}
|
||||||
options.onuninstall();
|
options.onuninstall();
|
||||||
},
|
},
|
||||||
@ -314,19 +314,21 @@ var HomePanels = (function() {
|
|||||||
this.default = !!options.default;
|
this.default = !!options.default;
|
||||||
|
|
||||||
if (!this.id || !this.title) {
|
if (!this.id || !this.title) {
|
||||||
throw "Home.panels: Can't create a home panel without an id and title!";
|
throw new Error("Home.panels: Can't create a home panel without an id and title!");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.layout) {
|
if (!this.layout) {
|
||||||
// Use FRAME layout by default
|
// Use FRAME layout by default
|
||||||
this.layout = Layout.FRAME;
|
this.layout = Layout.FRAME;
|
||||||
} else if (!_valueExists(Layout, this.layout)) {
|
} else if (!_valueExists(Layout, this.layout)) {
|
||||||
throw "Home.panels: Invalid layout for panel: panel.id = " + this.id + ", panel.layout =" + this.layout;
|
throw new Error("Home.panels: Invalid layout for panel: panel.id = " +
|
||||||
|
`${this.id}, panel.layout =${this.layout}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let view of this.views) {
|
for (let view of this.views) {
|
||||||
if (!_valueExists(View, view.type)) {
|
if (!_valueExists(View, view.type)) {
|
||||||
throw "Home.panels: Invalid view type: panel.id = " + this.id + ", view.type = " + view.type;
|
throw new Error("Home.panels: Invalid view type: panel.id = " +
|
||||||
|
`${this.id}, view.type = ${view.type}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!view.itemType) {
|
if (!view.itemType) {
|
||||||
@ -338,18 +340,21 @@ var HomePanels = (function() {
|
|||||||
view.itemType = Item.IMAGE;
|
view.itemType = Item.IMAGE;
|
||||||
}
|
}
|
||||||
} else if (!_valueExists(Item, view.itemType)) {
|
} else if (!_valueExists(Item, view.itemType)) {
|
||||||
throw "Home.panels: Invalid item type: panel.id = " + this.id + ", view.itemType = " + view.itemType;
|
throw new Error("Home.panels: Invalid item type: panel.id = " +
|
||||||
|
`${this.id}, view.itemType = ${view.itemType}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!view.itemHandler) {
|
if (!view.itemHandler) {
|
||||||
// Use BROWSER item handler by default
|
// Use BROWSER item handler by default
|
||||||
view.itemHandler = ItemHandler.BROWSER;
|
view.itemHandler = ItemHandler.BROWSER;
|
||||||
} else if (!_valueExists(ItemHandler, view.itemHandler)) {
|
} else if (!_valueExists(ItemHandler, view.itemHandler)) {
|
||||||
throw "Home.panels: Invalid item handler: panel.id = " + this.id + ", view.itemHandler = " + view.itemHandler;
|
throw new Error("Home.panels: Invalid item handler: panel.id = " +
|
||||||
|
`${this.id}, view.itemHandler = ${view.itemHandler}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!view.dataset) {
|
if (!view.dataset) {
|
||||||
throw "Home.panels: No dataset provided for view: panel.id = " + this.id + ", view.type = " + view.type;
|
throw new Error("Home.panels: No dataset provided for view: panel.id = " +
|
||||||
|
`${this.id}, view.type = ${view.type}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (view.onrefresh) {
|
if (view.onrefresh) {
|
||||||
@ -359,10 +364,10 @@ var HomePanels = (function() {
|
|||||||
|
|
||||||
if (options.auth) {
|
if (options.auth) {
|
||||||
if (!options.auth.messageText) {
|
if (!options.auth.messageText) {
|
||||||
throw "Home.panels: Invalid auth messageText: panel.id = " + this.id;
|
throw new Error("Home.panels: Invalid auth messageText: panel.id = " + this.id);
|
||||||
}
|
}
|
||||||
if (!options.auth.buttonText) {
|
if (!options.auth.buttonText) {
|
||||||
throw "Home.panels: Invalid auth buttonText: panel.id = " + this.id;
|
throw new Error("Home.panels: Invalid auth buttonText: panel.id = " + this.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.authConfig = {
|
this.authConfig = {
|
||||||
@ -398,7 +403,7 @@ var HomePanels = (function() {
|
|||||||
|
|
||||||
let _assertPanelExists = function(id) {
|
let _assertPanelExists = function(id) {
|
||||||
if (!(id in _registeredPanels)) {
|
if (!(id in _registeredPanels)) {
|
||||||
throw "Home.panels: Panel doesn't exist: id = " + id;
|
throw new Error("Home.panels: Panel doesn't exist: id = " + id);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -411,11 +416,11 @@ var HomePanels = (function() {
|
|||||||
register: function(id, optionsCallback) {
|
register: function(id, optionsCallback) {
|
||||||
// Bail if the panel already exists
|
// Bail if the panel already exists
|
||||||
if (id in _registeredPanels) {
|
if (id in _registeredPanels) {
|
||||||
throw "Home.panels: Panel already exists: id = " + id;
|
throw new Error("Home.panels: Panel already exists: id = " + id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!optionsCallback || typeof optionsCallback !== "function") {
|
if (!optionsCallback || typeof optionsCallback !== "function") {
|
||||||
throw "Home.panels: Panel callback must be a function: id = " + id;
|
throw new Error("Home.panels: Panel callback must be a function: id = " + id);
|
||||||
}
|
}
|
||||||
|
|
||||||
_registeredPanels[id] = optionsCallback;
|
_registeredPanels[id] = optionsCallback;
|
||||||
|
@ -333,8 +333,8 @@ HomeStorage.prototype = {
|
|||||||
*/
|
*/
|
||||||
async save(data, options) {
|
async save(data, options) {
|
||||||
if (data && data.length > MAX_SAVE_COUNT) {
|
if (data && data.length > MAX_SAVE_COUNT) {
|
||||||
throw "save failed for dataset = " + this.datasetId +
|
throw new Error(`save failed for dataset = ${this.datasetId}: ` +
|
||||||
": you cannot save more than " + MAX_SAVE_COUNT + " items at once";
|
`you cannot save more than ${MAX_SAVE_COUNT} items at once`);
|
||||||
}
|
}
|
||||||
|
|
||||||
let db = await getDatabaseConnection();
|
let db = await getDatabaseConnection();
|
||||||
|
@ -22,12 +22,12 @@ Notification.prototype = {
|
|||||||
if ("icon" in aOptions && aOptions.icon != null)
|
if ("icon" in aOptions && aOptions.icon != null)
|
||||||
this._icon = aOptions.icon;
|
this._icon = aOptions.icon;
|
||||||
else
|
else
|
||||||
throw "Notification icon is mandatory";
|
throw new Error("Notification icon is mandatory");
|
||||||
|
|
||||||
if ("title" in aOptions && aOptions.title != null)
|
if ("title" in aOptions && aOptions.title != null)
|
||||||
this._title = aOptions.title;
|
this._title = aOptions.title;
|
||||||
else
|
else
|
||||||
throw "Notification title is mandatory";
|
throw new Error("Notification title is mandatory");
|
||||||
|
|
||||||
if ("message" in aOptions && aOptions.message != null)
|
if ("message" in aOptions && aOptions.message != null)
|
||||||
this._message = aOptions.message;
|
this._message = aOptions.message;
|
||||||
@ -39,7 +39,7 @@ Notification.prototype = {
|
|||||||
|
|
||||||
if ("buttons" in aOptions && aOptions.buttons != null) {
|
if ("buttons" in aOptions && aOptions.buttons != null) {
|
||||||
if (aOptions.buttons.length > 3)
|
if (aOptions.buttons.length > 3)
|
||||||
throw "Too many buttons provided. The max number is 3";
|
throw new Error("Too many buttons provided. The max number is 3");
|
||||||
|
|
||||||
this._buttons = {};
|
this._buttons = {};
|
||||||
for (let i = 0; i < aOptions.buttons.length; i++) {
|
for (let i = 0; i < aOptions.buttons.length; i++) {
|
||||||
@ -184,7 +184,7 @@ var Notifications = {
|
|||||||
update: function notif_update(aId, aOptions) {
|
update: function notif_update(aId, aOptions) {
|
||||||
let notification = _notificationsMap[aId];
|
let notification = _notificationsMap[aId];
|
||||||
if (!notification)
|
if (!notification)
|
||||||
throw "Unknown notification id";
|
throw new Error("Unknown notification id");
|
||||||
notification.fillWithOptions(aOptions);
|
notification.fillWithOptions(aOptions);
|
||||||
notification.show();
|
notification.show();
|
||||||
},
|
},
|
||||||
|
@ -18,7 +18,7 @@ var EXPORTED_SYMBOLS = ["PageActions"];
|
|||||||
// TODO: We should move this method to a common importable location
|
// TODO: We should move this method to a common importable location
|
||||||
function resolveGeckoURI(aURI) {
|
function resolveGeckoURI(aURI) {
|
||||||
if (!aURI)
|
if (!aURI)
|
||||||
throw "Can't resolve an empty uri";
|
throw new Error("Can't resolve an empty uri");
|
||||||
|
|
||||||
if (aURI.startsWith("chrome://")) {
|
if (aURI.startsWith("chrome://")) {
|
||||||
let registry = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIChromeRegistry);
|
let registry = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIChromeRegistry);
|
||||||
|
@ -61,7 +61,7 @@ function SharedPreferencesImpl(options = {}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.scope == null || options.scope == undefined) {
|
if (options.scope == null || options.scope == undefined) {
|
||||||
throw "Shared Preferences must specifiy a scope.";
|
throw new Error("Shared Preferences must specifiy a scope.");
|
||||||
}
|
}
|
||||||
|
|
||||||
this._scope = options.scope;
|
this._scope = options.scope;
|
||||||
|
@ -116,7 +116,7 @@ var WebrtcUI = {
|
|||||||
notificationOptions.icon = "drawable:alert_mic";
|
notificationOptions.icon = "drawable:alert_mic";
|
||||||
} else {
|
} else {
|
||||||
// somethings wrong. lets throw
|
// somethings wrong. lets throw
|
||||||
throw "Couldn't find any cameras or microphones being used";
|
throw new Error("Couldn't find any cameras or microphones being used");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._notificationId)
|
if (this._notificationId)
|
||||||
|
@ -24,6 +24,34 @@ debugger-tests:
|
|||||||
files-changed:
|
files-changed:
|
||||||
- 'devtools/client/debugger/new/**'
|
- 'devtools/client/debugger/new/**'
|
||||||
|
|
||||||
|
devtools-tests:
|
||||||
|
description: devtools node-based tests (for instance jest)
|
||||||
|
platform: linux64/opt
|
||||||
|
treeherder:
|
||||||
|
symbol: node(devtools)
|
||||||
|
kind: test
|
||||||
|
tier: 1
|
||||||
|
worker-type: aws-provisioner-v1/gecko-t-linux-xlarge
|
||||||
|
worker:
|
||||||
|
docker-image: {in-tree: "lint"}
|
||||||
|
max-run-time: 1800
|
||||||
|
run:
|
||||||
|
using: run-task
|
||||||
|
cache-dotcache: true
|
||||||
|
command: >
|
||||||
|
cd /builds/worker/checkouts/gecko/ &&
|
||||||
|
npm install &&
|
||||||
|
cd /builds/worker/checkouts/gecko/devtools/client/aboutdebugging-new/test/jest &&
|
||||||
|
yarn &&
|
||||||
|
yarn test &&
|
||||||
|
cd /builds/worker/checkouts/gecko/devtools/client/framework/test/jest &&
|
||||||
|
yarn &&
|
||||||
|
yarn test
|
||||||
|
when:
|
||||||
|
files-changed:
|
||||||
|
- 'devtools/client/aboutdebugging-new/src/components/**'
|
||||||
|
- 'devtools/client/framework/components/**'
|
||||||
|
|
||||||
eslint-plugin-mozilla:
|
eslint-plugin-mozilla:
|
||||||
description: eslint-plugin-mozilla integration tests
|
description: eslint-plugin-mozilla integration tests
|
||||||
platform: linux64/opt
|
platform: linux64/opt
|
||||||
|
1
testing/web-platform/meta/2dcontext/__dir__.ini
Normal file
1
testing/web-platform/meta/2dcontext/__dir__.ini
Normal file
@ -0,0 +1 @@
|
|||||||
|
leak-threshold: [default: 30000]
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user