Update On Wed Jan 12 19:28:29 CET 2022
This commit is contained in:
parent
6692978efa
commit
d4fe6f9463
2833 changed files with 15216 additions and 11071 deletions
|
@ -487,13 +487,13 @@ already_AddRefed<AccAttributes> RemoteAccessibleBase<Derived>::Attributes() {
|
|||
|
||||
GroupPos groupPos = GroupPosition();
|
||||
nsAccUtils::SetAccGroupAttrs(attributes, groupPos.level, groupPos.setSize,
|
||||
groupPos.posInSet);
|
||||
groupPos.posInSet);
|
||||
|
||||
bool hierarchical = false;
|
||||
uint32_t itemCount = AccGroupInfo::TotalItemCount(this, &hierarchical);
|
||||
if (itemCount) {
|
||||
attributes->SetAttribute(nsGkAtoms::child_item_count,
|
||||
static_cast<int32_t>(itemCount));
|
||||
static_cast<int32_t>(itemCount));
|
||||
}
|
||||
|
||||
if (hierarchical) {
|
||||
|
|
|
@ -30,7 +30,6 @@ var DevelopmentHelpers = {
|
|||
let command = document.createXULElement("command");
|
||||
command.setAttribute("id", "cmd_quickRestart");
|
||||
command.addEventListener("command", this.quickRestart, true);
|
||||
command.setAttribute("oncommand", "void 0;"); // Needed - bug 371900
|
||||
document.getElementById("mainCommandSet").prepend(command);
|
||||
|
||||
let key = document.createXULElement("key");
|
||||
|
@ -38,7 +37,6 @@ var DevelopmentHelpers = {
|
|||
key.setAttribute("key", "r");
|
||||
key.setAttribute("modifiers", "accel,alt");
|
||||
key.setAttribute("command", "cmd_quickRestart");
|
||||
key.setAttribute("oncommand", "void 0;"); // Needed - bug 371900
|
||||
document.getElementById("mainKeyset").prepend(key);
|
||||
|
||||
let menuitem = document.createXULElement("menuitem");
|
||||
|
|
|
@ -170,7 +170,8 @@
|
|||
<key id="key_toggleMute" data-l10n-id="mute-toggle-shortcut" command="cmd_toggleMute" modifiers="control"/>
|
||||
<key id="key_undo"
|
||||
data-l10n-id="text-action-undo-shortcut"
|
||||
modifiers="accel"/>
|
||||
modifiers="accel"
|
||||
internal="true"/>
|
||||
<key id="key_redo"
|
||||
#ifdef XP_UNIX
|
||||
data-l10n-id="text-action-undo-shortcut"
|
||||
|
@ -179,18 +180,21 @@
|
|||
data-l10n-id="text-action-redo-shortcut"
|
||||
modifiers="accel"
|
||||
#endif
|
||||
/>
|
||||
internal="true"/>
|
||||
<key id="key_cut"
|
||||
data-l10n-id="text-action-cut-shortcut"
|
||||
modifiers="accel"/>
|
||||
modifiers="accel"
|
||||
internal="true"/>
|
||||
<key id="key_copy"
|
||||
data-l10n-id="text-action-copy-shortcut"
|
||||
modifiers="accel"/>
|
||||
modifiers="accel"
|
||||
internal="true"/>
|
||||
<key id="key_paste"
|
||||
data-l10n-id="text-action-paste-shortcut"
|
||||
modifiers="accel"/>
|
||||
modifiers="accel"
|
||||
internal="true"/>
|
||||
<key id="key_delete" keycode="VK_DELETE" command="cmd_delete" reserved="false"/>
|
||||
<key id="key_selectAll" data-l10n-id="text-action-select-all-shortcut" modifiers="accel"/>
|
||||
<key id="key_selectAll" data-l10n-id="text-action-select-all-shortcut" modifiers="accel" internal="true"/>
|
||||
|
||||
<key keycode="VK_BACK" command="cmd_handleBackspace" reserved="false"/>
|
||||
<key keycode="VK_BACK" command="cmd_handleShiftBackspace" modifiers="shift" reserved="false"/>
|
||||
|
@ -310,7 +314,9 @@
|
|||
# On OS X, dark voodoo magic invokes the quit code for this key.
|
||||
# So we're not adding the attribute on OSX because of backwards/add-on compat.
|
||||
# See bug 1369909 for background on this.
|
||||
#ifndef XP_MACOSX
|
||||
#ifdef XP_MACOSX
|
||||
internal="true"
|
||||
#else
|
||||
command="cmd_quitApplication"
|
||||
#endif
|
||||
reserved="true"/>
|
||||
|
@ -361,20 +367,25 @@
|
|||
<key id="key_minimizeWindow"
|
||||
command="minimizeWindow"
|
||||
data-l10n-id="window-minimize-shortcut"
|
||||
modifiers="accel"/>
|
||||
modifiers="accel"
|
||||
internal="true"/>
|
||||
<key id="key_openHelpMac"
|
||||
oncommand="openHelpLink('firefox-osxkey');"
|
||||
data-l10n-id="help-shortcut"
|
||||
modifiers="accel"/>
|
||||
modifiers="accel"
|
||||
internal="true"/>
|
||||
<!-- These are used to build the Application menu -->
|
||||
<key id="key_preferencesCmdMac"
|
||||
data-l10n-id="preferences-shortcut"
|
||||
modifiers="accel"/>
|
||||
modifiers="accel"
|
||||
internal="true"/>
|
||||
<key id="key_hideThisAppCmdMac"
|
||||
data-l10n-id="hide-app-shortcut"
|
||||
modifiers="accel"/>
|
||||
modifiers="accel"
|
||||
internal="true"/>
|
||||
<key id="key_hideOtherAppsCmdMac"
|
||||
data-l10n-id="hide-other-apps-shortcut"
|
||||
modifiers="accel,alt"/>
|
||||
modifiers="accel,alt"
|
||||
internal="true"/>
|
||||
#endif
|
||||
</keyset>
|
||||
|
|
|
@ -17,12 +17,16 @@ support-files =
|
|||
https_first_disabled = true
|
||||
skip-if =
|
||||
os == 'win' && bits == 64 # Bug 1719856
|
||||
os == 'linux' && socketprocess_networking
|
||||
[browser_contextmenu_inspect.js]
|
||||
skip-if = os == 'linux' && socketprocess_networking
|
||||
[browser_contextmenu_keyword.js]
|
||||
skip-if = toolkit == "gtk" || (os == "win" && processor == "aarch64") # disabled on Linux due to bug 513558, aarch64 due to 1533161
|
||||
[browser_contextmenu_loadblobinnewtab.js]
|
||||
support-files = browser_contextmenu_loadblobinnewtab.html
|
||||
skip-if = os == 'linux' && socketprocess_networking
|
||||
[browser_contextmenu_save_blocked.js]
|
||||
skip-if = os == 'linux' && socketprocess_networking
|
||||
[browser_contextmenu_share_macosx.js]
|
||||
support-files =
|
||||
browser_contextmenu_shareurl.html
|
||||
|
@ -38,13 +42,20 @@ skip-if = toolkit == "gtk" || (os == "win" && processor == "aarch64") # disabled
|
|||
[browser_contextmenu_touch.js]
|
||||
skip-if = true # Bug 1424433, disable due to very high frequency failure rate also on Windows 10
|
||||
[browser_contextmenu_linkopen.js]
|
||||
skip-if = os == 'linux' && socketprocess_networking
|
||||
[browser_contextmenu_iframe.js]
|
||||
support-files =
|
||||
test_contextmenu_iframe.html
|
||||
skip-if = os == 'linux' && socketprocess_networking
|
||||
[browser_contextmenu_childprocess.js]
|
||||
skip-if = os == 'linux' && socketprocess_networking
|
||||
[browser_contextmenu.js]
|
||||
tags = fullscreen
|
||||
skip-if = toolkit == "gtk" || verify || (os == "win" && processor == "aarch64") # disabled on Linux due to bug 513558, aarch64 due to 1531590
|
||||
skip-if =
|
||||
toolkit == "gtk"
|
||||
verify
|
||||
os == "win" && processor == "aarch64" # disabled on Linux due to bug 513558, aarch64 due to 1531590
|
||||
os == 'linux' && socketprocess_networking
|
||||
[browser_contextmenu_input.js]
|
||||
skip-if = toolkit == "gtk" || (os == "win" && processor == "aarch64") # disabled on Linux due to bug 513558, aarch64 due to 1533161
|
||||
[browser_copy_image_link.js]
|
||||
|
@ -52,10 +63,13 @@ support-files =
|
|||
doggy.png
|
||||
firebird.png
|
||||
firebird.png^headers^
|
||||
skip-if = os == 'linux' && socketprocess_networking
|
||||
[browser_utilityOverlay.js]
|
||||
https_first_disabled = true
|
||||
skip-if = os == 'linux' && socketprocess_networking
|
||||
[browser_utilityOverlayPrincipal.js]
|
||||
https_first_disabled = true
|
||||
[browser_view_image.js]
|
||||
support-files =
|
||||
test_view_image_revoked_cached_blob.html
|
||||
skip-if = os == 'linux' && socketprocess_networking
|
||||
|
|
|
@ -224,6 +224,7 @@ skip-if = e10s # Bug 863514 - no gesture support.
|
|||
[browser_homeDrop.js]
|
||||
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
|
||||
[browser_invalid_uri_back_forward_manipulation.js]
|
||||
skip-if = os == 'mac' && socketprocess_networking
|
||||
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
|
||||
[browser_lastAccessedTab.js]
|
||||
skip-if = toolkit == "windows" # Disabled on Windows due to frequent failures (bug 969405)
|
||||
|
|
|
@ -23,13 +23,18 @@ support-files =
|
|||
|
||||
[browser_appmenu.js]
|
||||
skip-if =
|
||||
asan || debug || (os == 'win' && bits == 32) || (os == 'win' && processor == 'aarch64') # Bug 1382809, bug 1369959, Win32 because of intermittent OOM failures, bug 1533141 for aarch64
|
||||
asan
|
||||
debug
|
||||
(os == 'win' && bits == 32)
|
||||
(os == 'win' && processor == 'aarch64')
|
||||
(os == 'linux' && socketprocess_networking) # Bug 1382809, bug 1369959, Win32 because of intermittent OOM failures, bug 1533141 for aarch64
|
||||
[browser_preferences_usage.js]
|
||||
https_first_disabled = true
|
||||
skip-if =
|
||||
!debug
|
||||
apple_catalina # platform migration
|
||||
os == 'win' && fission # Bug 1713890 - new Fission platform triage
|
||||
socketprocess_networking
|
||||
[browser_startup.js]
|
||||
[browser_startup_content.js]
|
||||
skip-if = !e10s
|
||||
|
|
|
@ -473,8 +473,8 @@ const startupPhases = {
|
|||
ignoreIfUnused: true,
|
||||
stat: 4,
|
||||
fsync: 3,
|
||||
read: 48,
|
||||
write: 172,
|
||||
read: 51,
|
||||
write: 178,
|
||||
},
|
||||
{
|
||||
// bug 1391590
|
||||
|
@ -490,7 +490,7 @@ const startupPhases = {
|
|||
fsync: 2,
|
||||
read: 4,
|
||||
stat: 3,
|
||||
write: 1321,
|
||||
write: 1324,
|
||||
},
|
||||
{
|
||||
// bug 1391590
|
||||
|
|
|
@ -25,5 +25,6 @@ environment =
|
|||
skip-if =
|
||||
apple_silicon # bug 1707724
|
||||
os == "win" && bits == 32
|
||||
socketprocess_networking
|
||||
[../browser_startup_content_mainthreadio.js]
|
||||
[../browser_startup_syncIPC.js]
|
||||
|
|
|
@ -42,6 +42,7 @@ tags = openwindow
|
|||
skip-if =
|
||||
(verify && debug && (os == 'linux'))
|
||||
apple_silicon # Disabled due to bleedover with other tests when run in regular suites; passes in "failures" jobs
|
||||
os == 'linux' && socketprocess_networking
|
||||
[browser_imageCache.js]
|
||||
skip-if = (verify && debug && (os == 'win'))
|
||||
[browser_count_and_remove.js]
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
head = head.js
|
||||
|
||||
[browser_cleanFlow.js]
|
||||
skip-if = socketprocess_networking
|
||||
[browser_dirtyEnable.js]
|
||||
[browser_doorhangerUserReject.js]
|
||||
[browser_localStorageMigration.js]
|
||||
|
|
|
@ -15,15 +15,11 @@
|
|||
%editMenuDTD;
|
||||
]>
|
||||
|
||||
<!-- @CSP: We have to whitelist the 'oncommand' handler for all the cmd_* fields within
|
||||
- editMenuOverlay.js until Bug 371900 is fixed using
|
||||
- sha512-4o5Uf4E4EG+90Mb820FH2YFDf4IuX4bfUwQC7reK1ZhgcXWJBKMK2330XIELaFJJ8HiPffS9mP60MPjuXMIrHA==
|
||||
-->
|
||||
<window id="contentAreaDownloadsView"
|
||||
data-l10n-id="downloads-window"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
csp="default-src chrome:; script-src chrome: 'sha512-4o5Uf4E4EG+90Mb820FH2YFDf4IuX4bfUwQC7reK1ZhgcXWJBKMK2330XIELaFJJ8HiPffS9mP60MPjuXMIrHA=='; img-src chrome: moz-icon:; object-src 'none'">
|
||||
csp="default-src chrome:; img-src chrome: moz-icon:; object-src 'none'">
|
||||
|
||||
<linkset>
|
||||
<html:link rel="localization" href="toolkit/global/textActions.ftl"/>
|
||||
|
|
|
@ -60,7 +60,9 @@ disabled = bug 1438663 # same focus issue as Bug 1438663
|
|||
[browser_ext_browserAction_click_types.js]
|
||||
[browser_ext_browserAction_context.js]
|
||||
https_first_disabled = true
|
||||
skip-if = os == 'linux' && debug # Bug 1504096
|
||||
skip-if =
|
||||
os == 'linux' && debug # Bug 1504096
|
||||
os == 'linux' && socketprocess_networking
|
||||
[browser_ext_browserAction_contextMenu.js]
|
||||
skip-if = os == 'linux' # bug 1369197
|
||||
[browser_ext_browserAction_disabled.js]
|
||||
|
|
|
@ -10,6 +10,7 @@ const BOOKMARKS_COUNT = 4;
|
|||
const TEST_PARENT_FOLDER = "testParentFolder";
|
||||
const TEST_SIF_URL = "http://testsif.example.com/";
|
||||
const TEST_SIF_TITLE = "TestSIF";
|
||||
const TEST_NEW_TITLE = "NewTestSIF";
|
||||
|
||||
function assertBookmarks(searchValue) {
|
||||
let found = 0;
|
||||
|
@ -38,7 +39,7 @@ function assertBookmarks(searchValue) {
|
|||
is(found, BOOKMARKS_COUNT, "found expected site");
|
||||
}
|
||||
|
||||
function showInFolder(aSearchStr, aParentFolderGuid) {
|
||||
async function showInFolder(aSearchStr, aParentFolderGuid) {
|
||||
let searchBox = sidebar.contentDocument.getElementById("search-box");
|
||||
|
||||
searchBox.value = aSearchStr;
|
||||
|
@ -70,9 +71,20 @@ function showInFolder(aSearchStr, aParentFolderGuid) {
|
|||
TEST_SIF_URL,
|
||||
"The searched bookmark URL matches selected node"
|
||||
);
|
||||
|
||||
info("Check the title will be applied the item when changing it");
|
||||
await PlacesUtils.bookmarks.update({
|
||||
guid: theNode.bookmarkGuid,
|
||||
title: TEST_NEW_TITLE,
|
||||
});
|
||||
Assert.equal(
|
||||
treeNode.title,
|
||||
TEST_NEW_TITLE,
|
||||
"New title is applied to the node"
|
||||
);
|
||||
}
|
||||
|
||||
add_task(async function test() {
|
||||
add_task(async function testTree() {
|
||||
// Add bookmarks and tags.
|
||||
for (let i = 0; i < BOOKMARKS_COUNT; i++) {
|
||||
let url = Services.io.newURI(TEST_URI + i);
|
||||
|
@ -94,9 +106,10 @@ add_task(async function test() {
|
|||
|
||||
// Cleanup before testing Show in Folder.
|
||||
await PlacesUtils.bookmarks.eraseEverything();
|
||||
});
|
||||
|
||||
add_task(async function testShowInFolder() {
|
||||
// Now test Show in Folder
|
||||
info("Test Show in Folder");
|
||||
let parentFolder = await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
|
@ -109,10 +122,68 @@ add_task(async function test() {
|
|||
url: TEST_SIF_URL,
|
||||
});
|
||||
|
||||
await withSidebarTree("bookmarks", function() {
|
||||
showInFolder(TEST_SIF_TITLE, parentFolder.guid);
|
||||
await withSidebarTree("bookmarks", async function() {
|
||||
await showInFolder(TEST_SIF_TITLE, parentFolder.guid);
|
||||
});
|
||||
|
||||
// Cleanup
|
||||
await PlacesUtils.bookmarks.eraseEverything();
|
||||
});
|
||||
|
||||
add_task(async function testRenameOnQueryResult() {
|
||||
await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
|
||||
title: TEST_SIF_TITLE,
|
||||
url: TEST_SIF_URL,
|
||||
});
|
||||
|
||||
await withSidebarTree("bookmarks", async function() {
|
||||
const searchBox = sidebar.contentDocument.getElementById("search-box");
|
||||
|
||||
searchBox.value = TEST_SIF_TITLE;
|
||||
searchBox.doCommand();
|
||||
|
||||
const tree = sidebar.contentDocument.getElementById("bookmarks-view");
|
||||
const theNode = tree.view._getNodeForRow(0);
|
||||
|
||||
info("Check the found bookmark");
|
||||
Assert.equal(theNode.uri, TEST_SIF_URL, "URI of bookmark found is correct");
|
||||
Assert.equal(
|
||||
theNode.title,
|
||||
TEST_SIF_TITLE,
|
||||
"Title of bookmark found is correct"
|
||||
);
|
||||
|
||||
info("Check the title will be applied the item when changing it");
|
||||
await PlacesUtils.bookmarks.update({
|
||||
guid: theNode.bookmarkGuid,
|
||||
title: TEST_NEW_TITLE,
|
||||
});
|
||||
// As the query result is refreshed once then the node also is regenerated,
|
||||
// need to get the result node from the tree again.
|
||||
const newNode = tree.view._getNodeForRow(0);
|
||||
Assert.equal(
|
||||
newNode.bookmarkGuid,
|
||||
theNode.bookmarkGuid,
|
||||
"GUID of node regenerated is correct"
|
||||
);
|
||||
Assert.equal(
|
||||
newNode.uri,
|
||||
theNode.uri,
|
||||
"URI of node regenerated is correct"
|
||||
);
|
||||
Assert.equal(
|
||||
newNode.parentGuid,
|
||||
theNode.parentGuid,
|
||||
"parentGuid of node regenerated is correct"
|
||||
);
|
||||
Assert.equal(
|
||||
newNode.title,
|
||||
TEST_NEW_TITLE,
|
||||
"New title is applied to the node"
|
||||
);
|
||||
});
|
||||
|
||||
// Cleanup before testing Show in Folder.
|
||||
await PlacesUtils.bookmarks.eraseEverything();
|
||||
});
|
||||
|
|
|
@ -74,8 +74,9 @@ add_task(async function test_create_and_remove_bookmarks() {
|
|||
"places"
|
||||
);
|
||||
|
||||
// Execute the delete command and check bookmark has been removed.
|
||||
PO._places.controller.doCommand("cmd_delete");
|
||||
// Press the delete key and check that the bookmark has been removed.
|
||||
gLibrary.document.getElementById("placesList").focus();
|
||||
EventUtils.synthesizeKey("VK_DELETE", {}, gLibrary);
|
||||
|
||||
await promiseItemRemovedNotification;
|
||||
|
||||
|
|
|
@ -238,6 +238,10 @@ function init_all() {
|
|||
|
||||
window.addEventListener("hashchange", onHashChange);
|
||||
|
||||
document.getElementById("focusSearch1").addEventListener("command", () => {
|
||||
gSearchResultsPane.searchInput.focus();
|
||||
});
|
||||
|
||||
gotoPref().then(() => {
|
||||
let helpButton = document.getElementById("helpButton");
|
||||
let helpUrl =
|
||||
|
|
|
@ -22,11 +22,8 @@
|
|||
id="preferences-root">
|
||||
|
||||
<head>
|
||||
<!-- @CSP: The 'oncommand' handler for 'focusSearch1' can not easily be rewritten (see Bug 371900)
|
||||
hence we are allowing the inline handler in the script-src directive using the hash
|
||||
sha512-X8+p/CqXeMdssOoFOf5RV+RpkvnN9pukQ20acGc7LqMgfYLW+lR0WAYT66OtSTpFHE/Qgx/ZCBs2RMc4QrA8FQ==
|
||||
Additionally we should remove 'unsafe-inline' from style-src, see Bug 1579160 -->
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src chrome:; script-src chrome: 'sha512-X8+p/CqXeMdssOoFOf5RV+RpkvnN9pukQ20acGc7LqMgfYLW+lR0WAYT66OtSTpFHE/Qgx/ZCBs2RMc4QrA8FQ=='; img-src chrome: moz-icon: https: data:; style-src chrome: data: 'unsafe-inline'; object-src 'none'" />
|
||||
<!-- @CSP: We should remove 'unsafe-inline' from style-src, see Bug 1579160 -->
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src chrome:; img-src chrome: moz-icon: https: data:; style-src chrome: data: 'unsafe-inline'; object-src 'none'" />
|
||||
|
||||
<title data-l10n-id="settings-page-title"></title>
|
||||
|
||||
|
@ -182,9 +179,7 @@
|
|||
</vbox>
|
||||
|
||||
<keyset>
|
||||
<!-- If you change the code within the oncommand handler of 'focusSearch1' you have to update the current hash of
|
||||
sha512-X8+p/CqXeMdssOoFOf5RV+RpkvnN9pukQ20acGc7LqMgfYLW+lR0WAYT66OtSTpFHE/Qgx/ZCBs2RMc4QrA8FQ== within the CSP above. -->
|
||||
<key data-l10n-id="focus-search" key="" modifiers="accel" id="focusSearch1" oncommand="gSearchResultsPane.searchInput.focus();"/>
|
||||
<key data-l10n-id="focus-search" key="" modifiers="accel" id="focusSearch1"/>
|
||||
</keyset>
|
||||
|
||||
<vbox class="main-content" flex="1" align="start">
|
||||
|
|
|
@ -67,6 +67,7 @@ skip-if =
|
|||
os == 'win' && bits == 64 && !debug # Bug 1741554
|
||||
[browser_contentblocking_categories.js]
|
||||
[browser_contentblocking.js]
|
||||
skip-if = socketprocess_networking
|
||||
[browser_contentblocking_standard_tcp_toggle.js]
|
||||
[browser_cookies_exceptions.js]
|
||||
[browser_defaultbrowser_alwayscheck.js]
|
||||
|
|
|
@ -35,12 +35,17 @@ https_first_disabled = true
|
|||
[browser_roundedWindow_open_mid_inner.js]
|
||||
[browser_roundedWindow_open_min_inner.js]
|
||||
[browser_roundedWindow_windowSetting_max_inner.js]
|
||||
skip-if = os == 'linux' && socketprocess_networking
|
||||
[browser_roundedWindow_windowSetting_max_outer.js]
|
||||
skip-if = os == 'linux' && socketprocess_networking
|
||||
[browser_roundedWindow_windowSetting_mid_inner.js]
|
||||
skip-if = os == 'linux' && socketprocess_networking
|
||||
[browser_roundedWindow_windowSetting_mid_outer.js]
|
||||
skip-if = os == "linux" && bits == 64 && os_version == "18.04"
|
||||
[browser_roundedWindow_windowSetting_min_inner.js]
|
||||
skip-if = os == 'linux' && socketprocess_networking
|
||||
[browser_roundedWindow_windowSetting_min_outer.js]
|
||||
skip-if = os == 'linux' && socketprocess_networking
|
||||
[browser_spoofing_keyboard_event.js]
|
||||
skip-if = (debug || asan) && os == "linux" && bits == 64 #Bug 1518179
|
||||
[browser_timezone.js]
|
||||
|
|
|
@ -112,7 +112,7 @@ class UrlbarView {
|
|||
}
|
||||
|
||||
get allowEmptySelection() {
|
||||
let { heuristicResult } = this._queryContext;
|
||||
let { heuristicResult } = this._queryContext || {};
|
||||
return !heuristicResult || !this._shouldShowHeuristic(heuristicResult);
|
||||
}
|
||||
|
||||
|
|
|
@ -210,6 +210,7 @@ support-files =
|
|||
support-files =
|
||||
searchSuggestionEngine.xml
|
||||
searchSuggestionEngine.sjs
|
||||
[browser_searchMode_newWindow.js]
|
||||
[browser_searchMode_no_results.js]
|
||||
[browser_searchMode_oneOffButton.js]
|
||||
[browser_searchMode_pickResult.js]
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Tests immediately entering search mode in a new window and then exiting it.
|
||||
// No errors should be thrown and search mode should be exited successfully.
|
||||
|
||||
"use strict";
|
||||
|
||||
add_task(async function escape() {
|
||||
await doTest(win =>
|
||||
EventUtils.synthesizeKey("KEY_Escape", { repeat: 2 }, win)
|
||||
);
|
||||
});
|
||||
|
||||
add_task(async function backspace() {
|
||||
await doTest(win => EventUtils.synthesizeKey("KEY_Backspace", {}, win));
|
||||
});
|
||||
|
||||
async function doTest(exitSearchMode) {
|
||||
let win = await BrowserTestUtils.openNewBrowserWindow();
|
||||
|
||||
// Press accel+K to enter search mode.
|
||||
await UrlbarTestUtils.promisePopupOpen(win, () =>
|
||||
EventUtils.synthesizeKey("k", { accelKey: true }, win)
|
||||
);
|
||||
await UrlbarTestUtils.assertSearchMode(win, {
|
||||
engineName: Services.search.defaultEngine.name,
|
||||
isGeneralPurposeEngine: true,
|
||||
source: UrlbarUtils.RESULT_SOURCE.SEARCH,
|
||||
isPreview: false,
|
||||
entry: "shortcut",
|
||||
});
|
||||
|
||||
// Exit search mode.
|
||||
await exitSearchMode(win);
|
||||
await UrlbarTestUtils.assertSearchMode(win, null);
|
||||
|
||||
await UrlbarTestUtils.promisePopupClose(win);
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
}
|
|
@ -585,6 +585,20 @@ const AVAILABLE_SHIMS = [
|
|||
],
|
||||
onlyIfDFPIActive: true,
|
||||
},
|
||||
{
|
||||
id: "Crave.ca",
|
||||
platform: "all",
|
||||
name: "Crave.ca",
|
||||
bug: "1746439",
|
||||
contentScripts: [
|
||||
{
|
||||
js: "crave-ca.js",
|
||||
matches: ["*://account.bellmedia.ca/login*"],
|
||||
runAt: "document_start",
|
||||
},
|
||||
],
|
||||
onlyIfDFPIActive: true,
|
||||
},
|
||||
];
|
||||
|
||||
module.exports = AVAILABLE_SHIMS;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"manifest_version": 2,
|
||||
"name": "Web Compatibility Interventions",
|
||||
"description": "Urgent post-release fixes for web compatibility.",
|
||||
"version": "29.7.0",
|
||||
"version": "29.8.0",
|
||||
"applications": {
|
||||
"gecko": {
|
||||
"id": "webcompat@mozilla.org",
|
||||
|
@ -98,6 +98,7 @@
|
|||
"shims/apstag.js",
|
||||
"shims/bmauth.js",
|
||||
"shims/chartbeat.js",
|
||||
"shims/crave-ca.js",
|
||||
"shims/criteo.js",
|
||||
"shims/cxense.js",
|
||||
"shims/eluminate.js",
|
||||
|
|
|
@ -96,6 +96,7 @@ FINAL_TARGET_FILES.features["webcompat@mozilla.org"]["shims"] += [
|
|||
"shims/apstag.js",
|
||||
"shims/bmauth.js",
|
||||
"shims/chartbeat.js",
|
||||
"shims/crave-ca.js",
|
||||
"shims/criteo.js",
|
||||
"shims/cxense.js",
|
||||
"shims/eluminate.js",
|
||||
|
|
56
browser/extensions/webcompat/shims/crave-ca.js
Normal file
56
browser/extensions/webcompat/shims/crave-ca.js
Normal file
|
@ -0,0 +1,56 @@
|
|||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
* Bug 1746439 - crave.ca login broken with dFPI enabled
|
||||
*
|
||||
* Crave.ca relies upon a login page that is out-of-origin. That login page
|
||||
* sets a cookie for https://www.crave.ca, which is then used as an proof of
|
||||
* authentication on redirect back to the main site. This shim adds a request
|
||||
* for storage access for https://www.crave.ca when the user tries to log in.
|
||||
*/
|
||||
|
||||
console.warn(
|
||||
`When logging in, Firefox calls the Storage Access API on behalf of the site. See https://bugzilla.mozilla.org/show_bug.cgi?id=1746439 for details.`
|
||||
);
|
||||
|
||||
// Third-party origin we need to request storage access for.
|
||||
const STORAGE_ACCESS_ORIGIN = "https://www.crave.ca";
|
||||
|
||||
document.documentElement.addEventListener(
|
||||
"click",
|
||||
e => {
|
||||
const { target, isTrusted } = e;
|
||||
if (!isTrusted) {
|
||||
return;
|
||||
}
|
||||
const button = target.closest("button");
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
const form = target.closest(".login-form");
|
||||
if (!form) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.warn(
|
||||
"Calling the Storage Access API on behalf of " + STORAGE_ACCESS_ORIGIN
|
||||
);
|
||||
button.disabled = true;
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
document
|
||||
.requestStorageAccessForOrigin(STORAGE_ACCESS_ORIGIN)
|
||||
.then(() => {
|
||||
button.disabled = false;
|
||||
target.click();
|
||||
})
|
||||
.catch(() => {
|
||||
button.disabled = false;
|
||||
});
|
||||
},
|
||||
true
|
||||
);
|
|
@ -6,9 +6,6 @@
|
|||
%include addons/extension-controlled.inc.css
|
||||
|
||||
%filter substitution
|
||||
%define themeTransition background-color 0.1s cubic-bezier(.17,.67,.83,.67)
|
||||
%define urlbarBreakoutExtend 2px
|
||||
|
||||
:root {
|
||||
--toolbar-bgcolor: var(--toolbar-non-lwt-bgcolor);
|
||||
--toolbar-bgimage: var(--toolbar-non-lwt-bgimage);
|
||||
|
@ -68,6 +65,8 @@
|
|||
--lwt-background-alignment: right top;
|
||||
--lwt-background-tiling: no-repeat;
|
||||
--lwt-brighttext-url-color: #00ddff;
|
||||
|
||||
--ext-theme-background-transition: background-color 0.1s cubic-bezier(.17,.67,.83,.67);
|
||||
}
|
||||
|
||||
@media (prefers-contrast) {
|
||||
|
@ -179,7 +178,7 @@ panel .text-link:-moz-lwtheme:not(:hover) {
|
|||
}
|
||||
|
||||
:root[sessionrestored] #nav-bar:-moz-lwtheme {
|
||||
transition: @themeTransition@;
|
||||
transition: var(--ext-theme-background-transition);
|
||||
}
|
||||
|
||||
/* Places tooltips */
|
||||
|
@ -199,7 +198,7 @@ panel .text-link:-moz-lwtheme:not(:hover) {
|
|||
}
|
||||
|
||||
:root[sessionrestored] #PersonalToolbar:not(.instant) {
|
||||
transition: min-height 170ms ease-out, max-height 170ms ease-out, @themeTransition@;
|
||||
transition: min-height 170ms ease-out, max-height 170ms ease-out, var(--ext-theme-background-transition);
|
||||
}
|
||||
|
||||
#PersonalToolbar[collapsed=true] {
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
%define menuStateActive :not([disabled])[_moz-menuactive]:active
|
||||
%define menuStateMenuActive :not([disabled])[_moz-menuactive]
|
||||
%define inAnyPanel :is(:not([cui-areatype="toolbar"]), [overflowedItem=true])
|
||||
%define panelPaletteIconSize 16px
|
||||
|
||||
%define appmenuWarningBackgroundColor #FFEFBF
|
||||
%define appmenuWarningBackgroundColorHover #FFE8A2
|
||||
|
@ -45,6 +44,8 @@
|
|||
--panel-separator-margin-horizontal: 8px;
|
||||
--panel-separator-margin: var(--panel-separator-margin-vertical) var(--panel-separator-margin-horizontal);
|
||||
--panel-subview-body-padding: 8px 0;
|
||||
|
||||
--panel-and-palette-icon-size: 16px;
|
||||
}
|
||||
|
||||
:root:not(:-moz-lwtheme) {
|
||||
|
@ -433,8 +434,8 @@ toolbarpaletteitem[place="palette"] > toolbarbutton[constrain-size="true"] > .to
|
|||
toolbarpaletteitem[place="palette"] > toolbarbutton[constrain-size="true"] > .toolbarbutton-badge-stack > .toolbarbutton-icon,
|
||||
toolbarbutton[constrain-size="true"][cui-areatype="menu-panel"] > .toolbarbutton-icon,
|
||||
toolbarbutton[constrain-size="true"][cui-areatype="menu-panel"] > .toolbarbutton-badge-stack > .toolbarbutton-icon {
|
||||
height: @panelPaletteIconSize@;
|
||||
width: @panelPaletteIconSize@;
|
||||
height: var(--panel-and-palette-icon-size);
|
||||
width: var(--panel-and-palette-icon-size);
|
||||
}
|
||||
|
||||
#customization-palette .toolbarbutton-1 {
|
||||
|
@ -448,10 +449,10 @@ toolbarbutton[constrain-size="true"][cui-areatype="menu-panel"] > .toolbarbutton
|
|||
/* badge itself is positioned correctly. Here we make sure that the icon itself
|
||||
/* has the minimum size we want, but no padding/margin. */
|
||||
.customization-palette .toolbarbutton-1 > .toolbarbutton-badge-stack > .toolbarbutton-icon {
|
||||
width: @panelPaletteIconSize@;
|
||||
height: @panelPaletteIconSize@;
|
||||
min-width: @panelPaletteIconSize@;
|
||||
min-height: @panelPaletteIconSize@;
|
||||
width: var(--panel-and-palette-icon-size);
|
||||
height: var(--panel-and-palette-icon-size);
|
||||
min-width: var(--panel-and-palette-icon-size);
|
||||
min-height: var(--panel-and-palette-icon-size);
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
|
91
build.gradle
91
build.gradle
|
@ -42,6 +42,12 @@ allprojects {
|
|||
" found ${getRustVersionFor("glean")}")
|
||||
}
|
||||
|
||||
artifactSuffix = getArtifactSuffix()
|
||||
versionName = getVersionName()
|
||||
versionCode = computeVersionCode()
|
||||
versionNumber = getVersionNumber()
|
||||
buildId = getBuildId()
|
||||
|
||||
buildToolsVersion = mozconfig.substs.ANDROID_BUILD_TOOLS_VERSION
|
||||
compileSdkVersion = tryInt(mozconfig.substs.ANDROID_TARGET_SDK)
|
||||
targetSdkVersion = tryInt(mozconfig.substs.ANDROID_TARGET_SDK)
|
||||
|
@ -57,6 +63,9 @@ allprojects {
|
|||
gradle.mozconfig.substs.GRADLE_MAVEN_REPOSITORIES.each { repository ->
|
||||
maven {
|
||||
url repository
|
||||
if (gradle.mozconfig.substs.ALLOW_INSECURE_GRADLE_REPOSITORIES) {
|
||||
allowInsecureProtocol = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -94,15 +103,18 @@ buildscript {
|
|||
gradle.mozconfig.substs.GRADLE_MAVEN_REPOSITORIES.each { repository ->
|
||||
maven {
|
||||
url repository
|
||||
if (gradle.mozconfig.substs.ALLOW_INSECURE_GRADLE_REPOSITORIES) {
|
||||
allowInsecureProtocol = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ext.kotlin_version = '1.5.20'
|
||||
ext.kotlin_version = '1.5.31'
|
||||
|
||||
dependencies {
|
||||
classpath 'org.mozilla.apilint:apilint:0.4.4'
|
||||
classpath 'com.android.tools.build:gradle:4.2.0'
|
||||
classpath 'org.mozilla.apilint:apilint:0.5.1'
|
||||
classpath 'com.android.tools.build:gradle:7.0.3'
|
||||
classpath 'com.getkeepsafe.dexcount:dexcount-gradle-plugin:0.8.2'
|
||||
classpath 'org.apache.commons:commons-exec:1.3'
|
||||
classpath 'com.diffplug.spotless:spotless-plugin-gradle:5.16.0'
|
||||
|
@ -159,6 +171,79 @@ ext.geckoBinariesOnlyIf = { task ->
|
|||
return true
|
||||
}
|
||||
|
||||
// Non-official versions are like "61.0a1", where "a1" is the milestone.
|
||||
// This simply strips that off, leaving "61.0" in this example.
|
||||
def getAppVersionWithoutMilestone() {
|
||||
return project.ext.mozconfig.substs.MOZ_APP_VERSION.replaceFirst(/a[0-9]/, "")
|
||||
}
|
||||
|
||||
// This converts MOZ_APP_VERSION into an integer
|
||||
// version code.
|
||||
//
|
||||
// We take something like 58.1.2a1 and come out with 5800102
|
||||
// This gives us 3 digits for the major number, and 2 digits
|
||||
// each for the minor and build number. Beta and Release
|
||||
//
|
||||
// This must be synchronized with _compute_gecko_version(...) in /taskcluster/gecko_taskgraph/transforms/task.py
|
||||
def computeVersionCode() {
|
||||
String appVersion = getAppVersionWithoutMilestone()
|
||||
|
||||
// Split on the dot delimiter, e.g. 58.1.1a1 -> ["58, "1", "1a1"]
|
||||
String[] parts = appVersion.split('\\.')
|
||||
|
||||
assert parts.size() == 2 || parts.size() == 3
|
||||
|
||||
// Major
|
||||
int code = Integer.parseInt(parts[0]) * 100000
|
||||
|
||||
// Minor
|
||||
code += Integer.parseInt(parts[1]) * 100
|
||||
|
||||
// Build
|
||||
if (parts.size() == 3) {
|
||||
code += Integer.parseInt(parts[2])
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
def getVersionName() {
|
||||
return "${mozconfig.substs.MOZ_APP_VERSION}-${mozconfig.substs.MOZ_UPDATE_CHANNEL}"
|
||||
}
|
||||
|
||||
// Mimic Python: open(os.path.join(buildconfig.topobjdir, 'buildid.h')).readline().split()[2]
|
||||
def getBuildId() {
|
||||
return file("${topobjdir}/buildid.h").getText('utf-8').split()[2]
|
||||
}
|
||||
|
||||
def getVersionNumber() {
|
||||
def appVersion = getAppVersionWithoutMilestone()
|
||||
def parts = appVersion.split('\\.')
|
||||
def version = parts[0] + "." + parts[1] + "." + getBuildId()
|
||||
def substs = project.ext.mozconfig.substs
|
||||
if (!substs.MOZILLA_OFFICIAL && !substs.MOZ_ANDROID_FAT_AAR_ARCHITECTURES) {
|
||||
// Use -SNAPSHOT versions locally to enable the local GeckoView substitution flow.
|
||||
version += "-SNAPSHOT"
|
||||
}
|
||||
return version
|
||||
}
|
||||
|
||||
def getArtifactSuffix() {
|
||||
def substs = project.ext.mozconfig.substs
|
||||
|
||||
def suffix = ""
|
||||
// Release artifacts don't specify the channel, for the sake of simplicity.
|
||||
if (substs.MOZ_UPDATE_CHANNEL != 'release') {
|
||||
suffix += "-${mozconfig.substs.MOZ_UPDATE_CHANNEL}"
|
||||
}
|
||||
|
||||
if (!substs.MOZ_ANDROID_GECKOVIEW_LITE) {
|
||||
suffix += "-omni"
|
||||
}
|
||||
|
||||
return suffix
|
||||
}
|
||||
|
||||
class MachExec extends Exec {
|
||||
def MachExec() {
|
||||
// Bug 1543982: When invoking `mach build` recursively, the outer `mach
|
||||
|
|
|
@ -17,6 +17,22 @@
|
|||
# and not quoting it ensures that each of those arguments is passed
|
||||
# as a separate argument to the actual LD.
|
||||
#
|
||||
# * In rare cases, we also need MOZ_CARGO_WRAP_LD_CXX, which is the
|
||||
# equivalent of CXX, when linking C++ code. Usually, this should
|
||||
# simply work by the use of CC and -lstdc++ (added by cc-rs).
|
||||
# However, in the case of sanitizer runtimes, there is a separate
|
||||
# runtime for C and C++ and linking C++ code with the C runtime can
|
||||
# fail if the requested feature is in the C++ runtime only (bug 1747298).
|
||||
#
|
||||
# $@ is doubly quoted for the eval. See bug 1418598.
|
||||
|
||||
eval ${MOZ_CARGO_WRAP_LD} ${MOZ_CARGO_WRAP_LDFLAGS} '"$@"'
|
||||
WRAP_LD=${MOZ_CARGO_WRAP_LD}
|
||||
for opt; do
|
||||
case "$opt" in
|
||||
-lc++|-lstdc++)
|
||||
WRAP_LD=${MOZ_CARGO_WRAP_LD_CXX};
|
||||
break;
|
||||
;;
|
||||
esac
|
||||
done
|
||||
eval ${WRAP_LD} ${MOZ_CARGO_WRAP_LDFLAGS} '"$@"'
|
||||
|
|
|
@ -244,6 +244,21 @@ void FuncSetCallback::run(const MatchFinder::MatchResult &Result) {
|
|||
return;
|
||||
} else {
|
||||
Func = Result.Nodes.getNodeAs<FunctionDecl>("canRunScriptFunction");
|
||||
|
||||
const char *ErrorAttrInDefinition =
|
||||
"MOZ_CAN_RUN_SCRIPT must be put in front "
|
||||
"of the declaration, not the definition";
|
||||
const char *NoteAttrInDefinition = "The first declaration exists here";
|
||||
if (!Func->isFirstDecl() &&
|
||||
!hasCustomAttribute<moz_can_run_script_for_definition>(Func)) {
|
||||
const FunctionDecl *FirstDecl = Func->getFirstDecl();
|
||||
if (!hasCustomAttribute<moz_can_run_script>(FirstDecl)) {
|
||||
Checker.diag(Func->getLocation(), ErrorAttrInDefinition,
|
||||
DiagnosticIDs::Error);
|
||||
Checker.diag(FirstDecl->getLocation(), NoteAttrInDefinition,
|
||||
DiagnosticIDs::Note);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CanRunScriptFuncs.insert(Func);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
ATTR(moz_allow_temporary)
|
||||
ATTR(moz_can_run_script)
|
||||
ATTR(moz_can_run_script_for_definition)
|
||||
ATTR(moz_can_run_script_boundary)
|
||||
ATTR(moz_global_class)
|
||||
ATTR(moz_heap_allocator)
|
||||
|
|
|
@ -652,3 +652,7 @@ struct DisallowMozKnownLiveMemberNotFromKnownLive {
|
|||
foo(mMember->mWhatever); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'mMember->mWhatever' is neither.}}
|
||||
}
|
||||
};
|
||||
|
||||
void IncorrectlyUnmarkedEarlyDeclaration(); // expected-note {{The first declaration exists here}}
|
||||
|
||||
MOZ_CAN_RUN_SCRIPT void IncorrectlyUnmarkedEarlyDeclaration() {}; // expected-error {{MOZ_CAN_RUN_SCRIPT must be put in front of the declaration, not the definition}}
|
||||
|
|
|
@ -58,8 +58,8 @@ def android_sdk_version(geckoview_lite):
|
|||
# If you think you can't handle the whole set of changes, please reach out to the Release
|
||||
# Engineering team.
|
||||
return namespace(
|
||||
build_tools_version="30.0.2",
|
||||
target_sdk_version="30",
|
||||
build_tools_version="31.0.0",
|
||||
target_sdk_version="31",
|
||||
min_sdk_version="16" if geckoview_lite else "21",
|
||||
)
|
||||
|
||||
|
|
|
@ -318,8 +318,10 @@ cargo_linker_env_var := CARGO_TARGET_$(call varize,$(RUST_TARGET))_LINKER
|
|||
|
||||
export MOZ_CARGO_WRAP_LDFLAGS
|
||||
export MOZ_CARGO_WRAP_LD
|
||||
export MOZ_CARGO_WRAP_LD_CXX
|
||||
export MOZ_CARGO_WRAP_HOST_LDFLAGS
|
||||
export MOZ_CARGO_WRAP_HOST_LD
|
||||
export MOZ_CARGO_WRAP_HOST_LD_CXX
|
||||
# Exporting from make always exports a value. Setting a value per-recipe
|
||||
# would export an empty value for the host recipes. When not doing a
|
||||
# cross-compile, the --target for those is the same, and cargo will use
|
||||
|
@ -382,16 +384,22 @@ $(TARGET_RECIPES) $(HOST_RECIPES): MOZ_CARGO_WRAP_HOST_LDFLAGS:=$(HOST_LDFLAGS)
|
|||
|
||||
ifeq (,$(filter clang-cl,$(CC_TYPE)))
|
||||
$(TARGET_RECIPES): MOZ_CARGO_WRAP_LD:=$(CC)
|
||||
$(TARGET_RECIPES): MOZ_CARGO_WRAP_LD_CXX:=$(CXX)
|
||||
else
|
||||
$(TARGET_RECIPES): MOZ_CARGO_WRAP_LD:=$(LINKER)
|
||||
$(TARGET_RECIPES): MOZ_CARGO_WRAP_LD_CXX:=$(LINKER)
|
||||
endif
|
||||
|
||||
ifeq (,$(filter clang-cl,$(HOST_CC_TYPE)))
|
||||
$(HOST_RECIPES): MOZ_CARGO_WRAP_LD:=$(HOST_CC)
|
||||
$(HOST_RECIPES): MOZ_CARGO_WRAP_LD_CXX:=$(HOST_CXX)
|
||||
$(TARGET_RECIPES) $(HOST_RECIPES): MOZ_CARGO_WRAP_HOST_LD:=$(HOST_CC)
|
||||
$(TARGET_RECIPES) $(HOST_RECIPES): MOZ_CARGO_WRAP_HOST_LD_CXX:=$(HOST_CXX)
|
||||
else
|
||||
$(HOST_RECIPES): MOZ_CARGO_WRAP_LD:=$(HOST_LINKER)
|
||||
$(HOST_RECIPES): MOZ_CARGO_WRAP_LD_CXX:=$(HOST_LINKER)
|
||||
$(TARGET_RECIPES) $(HOST_RECIPES): MOZ_CARGO_WRAP_HOST_LD:=$(HOST_LINKER)
|
||||
$(TARGET_RECIPES) $(HOST_RECIPES): MOZ_CARGO_WRAP_HOST_LD_CXX:=$(HOST_LINKER)
|
||||
endif
|
||||
|
||||
ifdef RUST_LIBRARY_FILE
|
||||
|
|
|
@ -2405,7 +2405,7 @@
|
|||
"byName": {},
|
||||
"byBlocks": {},
|
||||
"usedIds": {
|
||||
"0": 0
|
||||
"1": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2426,7 +2426,7 @@
|
|||
"byName": {},
|
||||
"byBlocks": {},
|
||||
"usedIds": {
|
||||
"0": 0
|
||||
"1": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
462
devtools/client/debugger/dist/search-worker.js
vendored
462
devtools/client/debugger/dist/search-worker.js
vendored
|
@ -94,91 +94,6 @@ module.exports = {
|
|||
workerUtils
|
||||
};
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 562:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
var freeGlobal = __webpack_require__(589);
|
||||
|
||||
/** Detect free variable `self`. */
|
||||
var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
|
||||
|
||||
/** Used as a reference to the global object. */
|
||||
var root = freeGlobal || freeSelf || Function('return this')();
|
||||
|
||||
module.exports = root;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 563:
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
/**
|
||||
* Checks if `value` is classified as an `Array` object.
|
||||
*
|
||||
* @static
|
||||
* @memberOf _
|
||||
* @since 0.1.0
|
||||
* @category Lang
|
||||
* @param {*} value The value to check.
|
||||
* @returns {boolean} Returns `true` if `value` is an array, else `false`.
|
||||
* @example
|
||||
*
|
||||
* _.isArray([1, 2, 3]);
|
||||
* // => true
|
||||
*
|
||||
* _.isArray(document.body.children);
|
||||
* // => false
|
||||
*
|
||||
* _.isArray('abc');
|
||||
* // => false
|
||||
*
|
||||
* _.isArray(_.noop);
|
||||
* // => false
|
||||
*/
|
||||
var isArray = Array.isArray;
|
||||
|
||||
module.exports = isArray;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 565:
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
/**
|
||||
* Checks if `value` is object-like. A value is object-like if it's not `null`
|
||||
* and has a `typeof` result of "object".
|
||||
*
|
||||
* @static
|
||||
* @memberOf _
|
||||
* @since 4.0.0
|
||||
* @category Lang
|
||||
* @param {*} value The value to check.
|
||||
* @returns {boolean} Returns `true` if `value` is object-like, else `false`.
|
||||
* @example
|
||||
*
|
||||
* _.isObjectLike({});
|
||||
* // => true
|
||||
*
|
||||
* _.isObjectLike([1, 2, 3]);
|
||||
* // => true
|
||||
*
|
||||
* _.isObjectLike(_.noop);
|
||||
* // => false
|
||||
*
|
||||
* _.isObjectLike(null);
|
||||
* // => false
|
||||
*/
|
||||
function isObjectLike(value) {
|
||||
return value != null && typeof value == 'object';
|
||||
}
|
||||
|
||||
module.exports = isObjectLike;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 567:
|
||||
|
@ -382,165 +297,6 @@ module.exports = {
|
|||
workerHandler
|
||||
};
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 569:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
var Symbol = __webpack_require__(570),
|
||||
getRawTag = __webpack_require__(615),
|
||||
objectToString = __webpack_require__(616);
|
||||
|
||||
/** `Object#toString` result references. */
|
||||
var nullTag = '[object Null]',
|
||||
undefinedTag = '[object Undefined]';
|
||||
|
||||
/** Built-in value references. */
|
||||
var symToStringTag = Symbol ? Symbol.toStringTag : undefined;
|
||||
|
||||
/**
|
||||
* The base implementation of `getTag` without fallbacks for buggy environments.
|
||||
*
|
||||
* @private
|
||||
* @param {*} value The value to query.
|
||||
* @returns {string} Returns the `toStringTag`.
|
||||
*/
|
||||
function baseGetTag(value) {
|
||||
if (value == null) {
|
||||
return value === undefined ? undefinedTag : nullTag;
|
||||
}
|
||||
return (symToStringTag && symToStringTag in Object(value))
|
||||
? getRawTag(value)
|
||||
: objectToString(value);
|
||||
}
|
||||
|
||||
module.exports = baseGetTag;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 570:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
var root = __webpack_require__(562);
|
||||
|
||||
/** Built-in value references. */
|
||||
var Symbol = root.Symbol;
|
||||
|
||||
module.exports = Symbol;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 577:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
var baseGetTag = __webpack_require__(569),
|
||||
isObjectLike = __webpack_require__(565);
|
||||
|
||||
/** `Object#toString` result references. */
|
||||
var symbolTag = '[object Symbol]';
|
||||
|
||||
/**
|
||||
* Checks if `value` is classified as a `Symbol` primitive or object.
|
||||
*
|
||||
* @static
|
||||
* @memberOf _
|
||||
* @since 4.0.0
|
||||
* @category Lang
|
||||
* @param {*} value The value to check.
|
||||
* @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
|
||||
* @example
|
||||
*
|
||||
* _.isSymbol(Symbol.iterator);
|
||||
* // => true
|
||||
*
|
||||
* _.isSymbol('abc');
|
||||
* // => false
|
||||
*/
|
||||
function isSymbol(value) {
|
||||
return typeof value == 'symbol' ||
|
||||
(isObjectLike(value) && baseGetTag(value) == symbolTag);
|
||||
}
|
||||
|
||||
module.exports = isSymbol;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 589:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
/* WEBPACK VAR INJECTION */(function(global) {/** Detect free variable `global` from Node.js. */
|
||||
var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;
|
||||
|
||||
module.exports = freeGlobal;
|
||||
|
||||
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(590)))
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 590:
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
var g;
|
||||
|
||||
// This works in non-strict mode
|
||||
g = (function() {
|
||||
return this;
|
||||
})();
|
||||
|
||||
try {
|
||||
// This works if eval is allowed (see CSP)
|
||||
g = g || Function("return this")() || (1,eval)("this");
|
||||
} catch(e) {
|
||||
// This works if the window reference is available
|
||||
if(typeof window === "object")
|
||||
g = window;
|
||||
}
|
||||
|
||||
// g can still be undefined, but nothing to do about it...
|
||||
// We return undefined, instead of nothing here, so it's
|
||||
// easier to handle this case. if(!global) { ...}
|
||||
|
||||
module.exports = g;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 605:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
var baseToString = __webpack_require__(639);
|
||||
|
||||
/**
|
||||
* Converts `value` to a string. An empty string is returned for `null`
|
||||
* and `undefined` values. The sign of `-0` is preserved.
|
||||
*
|
||||
* @static
|
||||
* @memberOf _
|
||||
* @since 4.0.0
|
||||
* @category Lang
|
||||
* @param {*} value The value to convert.
|
||||
* @returns {string} Returns the converted string.
|
||||
* @example
|
||||
*
|
||||
* _.toString(null);
|
||||
* // => ''
|
||||
*
|
||||
* _.toString(-0);
|
||||
* // => '-0'
|
||||
*
|
||||
* _.toString([1, 2, 3]);
|
||||
* // => '1,2,3'
|
||||
*/
|
||||
function toString(value) {
|
||||
return value == null ? '' : baseToString(value);
|
||||
}
|
||||
|
||||
module.exports = toString;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 607:
|
||||
|
@ -732,160 +488,6 @@ process.chdir = function (dir) {
|
|||
process.umask = function() { return 0; };
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 615:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
var Symbol = __webpack_require__(570);
|
||||
|
||||
/** Used for built-in method references. */
|
||||
var objectProto = Object.prototype;
|
||||
|
||||
/** Used to check objects for own properties. */
|
||||
var hasOwnProperty = objectProto.hasOwnProperty;
|
||||
|
||||
/**
|
||||
* Used to resolve the
|
||||
* [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
|
||||
* of values.
|
||||
*/
|
||||
var nativeObjectToString = objectProto.toString;
|
||||
|
||||
/** Built-in value references. */
|
||||
var symToStringTag = Symbol ? Symbol.toStringTag : undefined;
|
||||
|
||||
/**
|
||||
* A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
|
||||
*
|
||||
* @private
|
||||
* @param {*} value The value to query.
|
||||
* @returns {string} Returns the raw `toStringTag`.
|
||||
*/
|
||||
function getRawTag(value) {
|
||||
var isOwn = hasOwnProperty.call(value, symToStringTag),
|
||||
tag = value[symToStringTag];
|
||||
|
||||
try {
|
||||
value[symToStringTag] = undefined;
|
||||
var unmasked = true;
|
||||
} catch (e) {}
|
||||
|
||||
var result = nativeObjectToString.call(value);
|
||||
if (unmasked) {
|
||||
if (isOwn) {
|
||||
value[symToStringTag] = tag;
|
||||
} else {
|
||||
delete value[symToStringTag];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
module.exports = getRawTag;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 616:
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
/** Used for built-in method references. */
|
||||
var objectProto = Object.prototype;
|
||||
|
||||
/**
|
||||
* Used to resolve the
|
||||
* [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
|
||||
* of values.
|
||||
*/
|
||||
var nativeObjectToString = objectProto.toString;
|
||||
|
||||
/**
|
||||
* Converts `value` to a string using `Object.prototype.toString`.
|
||||
*
|
||||
* @private
|
||||
* @param {*} value The value to convert.
|
||||
* @returns {string} Returns the converted string.
|
||||
*/
|
||||
function objectToString(value) {
|
||||
return nativeObjectToString.call(value);
|
||||
}
|
||||
|
||||
module.exports = objectToString;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 639:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
var Symbol = __webpack_require__(570),
|
||||
arrayMap = __webpack_require__(640),
|
||||
isArray = __webpack_require__(563),
|
||||
isSymbol = __webpack_require__(577);
|
||||
|
||||
/** Used as references for various `Number` constants. */
|
||||
var INFINITY = 1 / 0;
|
||||
|
||||
/** Used to convert symbols to primitives and strings. */
|
||||
var symbolProto = Symbol ? Symbol.prototype : undefined,
|
||||
symbolToString = symbolProto ? symbolProto.toString : undefined;
|
||||
|
||||
/**
|
||||
* The base implementation of `_.toString` which doesn't convert nullish
|
||||
* values to empty strings.
|
||||
*
|
||||
* @private
|
||||
* @param {*} value The value to process.
|
||||
* @returns {string} Returns the string.
|
||||
*/
|
||||
function baseToString(value) {
|
||||
// Exit early for strings to avoid a performance hit in some environments.
|
||||
if (typeof value == 'string') {
|
||||
return value;
|
||||
}
|
||||
if (isArray(value)) {
|
||||
// Recursively convert values (susceptible to call stack limits).
|
||||
return arrayMap(value, baseToString) + '';
|
||||
}
|
||||
if (isSymbol(value)) {
|
||||
return symbolToString ? symbolToString.call(value) : '';
|
||||
}
|
||||
var result = (value + '');
|
||||
return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
|
||||
}
|
||||
|
||||
module.exports = baseToString;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 640:
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
/**
|
||||
* A specialized version of `_.map` for arrays without support for iteratee
|
||||
* shorthands.
|
||||
*
|
||||
* @private
|
||||
* @param {Array} [array] The array to iterate over.
|
||||
* @param {Function} iteratee The function invoked per iteration.
|
||||
* @returns {Array} Returns the new mapped array.
|
||||
*/
|
||||
function arrayMap(array, iteratee) {
|
||||
var index = -1,
|
||||
length = array == null ? 0 : array.length,
|
||||
result = Array(length);
|
||||
|
||||
while (++index < length) {
|
||||
result[index] = iteratee(array[index], index, array);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
module.exports = arrayMap;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 701:
|
||||
|
@ -1018,20 +620,21 @@ Object.defineProperty(exports, "__esModule", {
|
|||
});
|
||||
exports.default = buildQuery;
|
||||
|
||||
var _escapeRegExp = _interopRequireDefault(__webpack_require__(908));
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
/* 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/>. */
|
||||
|
||||
function escapeRegExp(str) {
|
||||
const reRegExpChar = /[\\^$.*+?()[\]{}|]/g;
|
||||
return str.replace(reRegExpChar, "\\$&");
|
||||
}
|
||||
/**
|
||||
* Ignore doing outline matches for less than 3 whitespaces
|
||||
*
|
||||
* @memberof utils/source-search
|
||||
* @static
|
||||
*/
|
||||
|
||||
|
||||
function ignoreWhiteSpace(str) {
|
||||
return /^\s{0,2}$/.test(str) ? "(?!\\s*.*)" : str;
|
||||
}
|
||||
|
@ -1072,16 +675,20 @@ function buildQuery(originalQuery, modifiers, {
|
|||
return new RegExp(originalQuery);
|
||||
}
|
||||
|
||||
let query = originalQuery;
|
||||
let query = originalQuery; // If we don't want to do a regexMatch, we need to escape all regex related characters
|
||||
// so they would actually match.
|
||||
|
||||
if (!regexMatch) {
|
||||
query = escapeRegExp(query);
|
||||
} // ignoreWhiteSpace might return a negative lookbehind, and in such case, we want it
|
||||
// to be consumed as a RegExp part by the callsite, so this needs to be called after
|
||||
// the regexp is escaped.
|
||||
|
||||
|
||||
if (ignoreSpaces) {
|
||||
query = ignoreWhiteSpace(query);
|
||||
}
|
||||
|
||||
if (!regexMatch) {
|
||||
query = (0, _escapeRegExp.default)(query);
|
||||
}
|
||||
|
||||
query = wholeMatch(query, wholeWord);
|
||||
const flags = buildFlags(caseSensitive, isGlobal);
|
||||
|
||||
|
@ -1092,45 +699,6 @@ function buildQuery(originalQuery, modifiers, {
|
|||
return new RegExp(query);
|
||||
}
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 908:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
var toString = __webpack_require__(605);
|
||||
|
||||
/**
|
||||
* Used to match `RegExp`
|
||||
* [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
|
||||
*/
|
||||
var reRegExpChar = /[\\^$.*+?()[\]{}|]/g,
|
||||
reHasRegExpChar = RegExp(reRegExpChar.source);
|
||||
|
||||
/**
|
||||
* Escapes the `RegExp` special characters "^", "$", "\", ".", "*", "+",
|
||||
* "?", "(", ")", "[", "]", "{", "}", and "|" in `string`.
|
||||
*
|
||||
* @static
|
||||
* @memberOf _
|
||||
* @since 3.0.0
|
||||
* @category String
|
||||
* @param {string} [string=''] The string to escape.
|
||||
* @returns {string} Returns the escaped string.
|
||||
* @example
|
||||
*
|
||||
* _.escapeRegExp('[lodash](https://lodash.com/)');
|
||||
* // => '\[lodash\]\(https://lodash\.com/\)'
|
||||
*/
|
||||
function escapeRegExp(string) {
|
||||
string = toString(string);
|
||||
return (string && reHasRegExpChar.test(string))
|
||||
? string.replace(reRegExpChar, '\\$&')
|
||||
: string;
|
||||
}
|
||||
|
||||
module.exports = escapeRegExp;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 909:
|
||||
|
|
|
@ -121,9 +121,14 @@ add_task(async function() {
|
|||
await removeTab(gBrowser.selectedTab);
|
||||
});
|
||||
|
||||
|
||||
// Test setting breakpoints while the service worker is starting up.
|
||||
add_task(async function() {
|
||||
info("Subtest #4");
|
||||
if (Services.appinfo.fissionAutostart) {
|
||||
// Disabled when serviceworker isolation is used due to bug 1749341
|
||||
return;
|
||||
}
|
||||
|
||||
const toolbox = await openNewTabAndToolbox(
|
||||
EXAMPLE_URL + "doc-service-workers.html",
|
||||
|
|
|
@ -73,7 +73,6 @@ class WindowGlobalTargetFront extends TargetMixin(
|
|||
const event = Object.create(null);
|
||||
event.url = packet.url;
|
||||
event.title = packet.title;
|
||||
event.nativeConsoleAPI = packet.nativeConsoleAPI;
|
||||
event.isFrameSwitching = packet.isFrameSwitching;
|
||||
|
||||
// Keep the title unmodified when a developer toolbox switches frame
|
||||
|
|
|
@ -291,23 +291,6 @@ class WebConsoleFront extends FrontClassWithSpec(webconsoleSpec) {
|
|||
return this._client.request(packet, onResponse);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the given Web Console listeners.
|
||||
* TODO: remove once the front is retrieved via getFront, and we use form()
|
||||
*
|
||||
* @see this.LISTENERS
|
||||
* @param array listeners
|
||||
* Array of listeners you want to start. See this.LISTENERS for
|
||||
* known listeners.
|
||||
* @return request
|
||||
* Request object that implements both Promise and EventEmitter interfaces
|
||||
*/
|
||||
async startListeners(listeners) {
|
||||
const response = await super.startListeners(listeners);
|
||||
this.hasNativeConsoleAPI = response.nativeConsoleAPI;
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the WebConsoleFront.
|
||||
*
|
||||
|
|
|
@ -283,7 +283,6 @@ skip-if = win10_2004 # Bug 1723573
|
|||
[browser_net_ws-clear.js]
|
||||
[browser_net_ws-connection-closed.js]
|
||||
[browser_net_ws-early-connection.js]
|
||||
skip-if = socketprocess_networking
|
||||
[browser_net_ws-filter-dropdown.js]
|
||||
[browser_net_ws-filter-regex.js]
|
||||
[browser_net_ws-json-action-cable-payload.js]
|
||||
|
@ -296,5 +295,4 @@ skip-if = socketprocess_networking
|
|||
[browser_net_ws-sse-persist-columns.js]
|
||||
[browser_net_ws-stomp-payload.js]
|
||||
[browser_net-ws-filter-freetext.js]
|
||||
skip-if = socketprocess_networking
|
||||
[browser_net_image_cache.js]
|
||||
|
|
|
@ -23,7 +23,7 @@ const TEST_IMAGE =
|
|||
"test/test-image.png";
|
||||
|
||||
add_task(async function() {
|
||||
// Needed for the execute() function below
|
||||
// Needed for the execute() call in `testMessages`.
|
||||
await pushPref("security.allow_parent_unrestricted_js_loads", true);
|
||||
await pushPref("devtools.browserconsole.contentMessages", true);
|
||||
const tab = await addTab(TEST_URI);
|
||||
|
@ -48,12 +48,31 @@ async function testMessages() {
|
|||
const opened = waitForBrowserConsole();
|
||||
let hud = BrowserConsoleManager.getBrowserConsole();
|
||||
ok(!hud, "browser console is not open");
|
||||
|
||||
// The test harness does override the global's console property to replace it with
|
||||
// a Console.jsm instance (https://searchfox.org/mozilla-central/rev/618f9970972adc5a21194d39d690ec0865f26024/testing/mochitest/api.js#75-80)
|
||||
// So here we reset the console property with the native console (which is luckily
|
||||
// stored in `nativeConsole`).
|
||||
const overriddenConsole = globalThis.console;
|
||||
globalThis.console = globalThis.nativeConsole;
|
||||
|
||||
info("wait for the browser console to open with ctrl-shift-j");
|
||||
EventUtils.synthesizeKey("j", { accelKey: true, shiftKey: true }, window);
|
||||
|
||||
hud = await opened;
|
||||
ok(hud, "browser console opened");
|
||||
|
||||
info("Check that we don't display the non-native console API warning");
|
||||
// Wait a bit to let room for the message to be displayed
|
||||
await wait(1000);
|
||||
is(
|
||||
findMessage(hud, "The Web Console logging API", ".warn"),
|
||||
undefined,
|
||||
"The message about disabled console API is not displayed"
|
||||
);
|
||||
// Set the overidden console back.
|
||||
globalThis.console = overriddenConsole;
|
||||
|
||||
await clearOutput(hud);
|
||||
|
||||
await setFilterState(hud, {
|
||||
|
|
|
@ -132,7 +132,7 @@ const App = React.createClass({
|
|||
|
||||
If you are using something like Redux to manage state this is handled
|
||||
automatically for you with the library you use to bind Redux with
|
||||
React. See more in [Redux](redux.html).
|
||||
React. See more in [Redux](redux.md).
|
||||
|
||||
## DOM Diffing
|
||||
|
||||
|
@ -154,4 +154,4 @@ just make sure the virtual DOM has what it should.
|
|||
## Next
|
||||
|
||||
Read the [React Guidelines](react-guidelines.md) next to learn how to
|
||||
write React code specifically for the devtools.
|
||||
write React code specifically for the devtools.
|
||||
|
|
|
@ -5,7 +5,7 @@ concepts, so go read them.
|
|||
|
||||
# Quick Intro
|
||||
|
||||
Just like the [React introduction](react.html), this is a quick
|
||||
Just like the [React introduction](react.md), this is a quick
|
||||
introduction to redux, focusing on how it fits into React and why we
|
||||
chose it.
|
||||
|
||||
|
@ -157,4 +157,4 @@ rendered with react.
|
|||
## Next
|
||||
|
||||
Read the [Redux Guidelines](redux-guidelines.md) next to learn how to
|
||||
write React code specifically for the devtools.
|
||||
write React code specifically for the devtools.
|
||||
|
|
|
@ -304,7 +304,7 @@ Notes:
|
|||
|
||||
The code for the tabs uses their ids to automatically report telemetry when you switch between panels, so you don't need to explicitly call `toolOpened` and `toolClosed` on top level panels.
|
||||
|
||||
You will still need to call those functions on subpanels, or tools such as about:debugging which are not opened as tabs.
|
||||
You will still need to call those functions on subpanels, or tools such as `about:debugging` which are not opened as tabs.
|
||||
|
||||
#### Testing
|
||||
|
||||
|
@ -426,7 +426,7 @@ Click [here](https://wiki.mozilla.org/Firefox/Data_Collection#Requesting_Data_Co
|
|||
|
||||
### Local data
|
||||
|
||||
Go to [about:telemetry](about:telemetry) to see stats relating to your local instance.
|
||||
Go to `about:telemetry` to see stats relating to your local instance.
|
||||
|
||||
### Global data
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ Create a new profile, and name it `development`. Then start Firefox by clicking
|
|||
|
||||
Next time you start Firefox with `./mach run -P development`, the new profile will be automatically used, and settings will persist between browser launches.
|
||||
|
||||
It's now time to [start contributing](../contributing.html)! 😃
|
||||
It's now time to [start contributing](../contributing.md)! 😃
|
||||
|
||||
---
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Writing new DAMP performance tests
|
||||
|
||||
See [DAMP Performance tests](performance-tests.md) for an overall description of our performance tests.
|
||||
See [DAMP Performance tests](performance-tests-damp.md) for an overall description of our performance tests.
|
||||
Here, we will describe how to write a new test and register it to run in DAMP.
|
||||
|
||||
```note::
|
||||
|
@ -16,8 +16,8 @@ Here, we will describe how to write a new test and register it to run in DAMP.
|
|||
```
|
||||
|
||||
This page contains the general documentation for writing DAMP tests. See also:
|
||||
- [Performance test writing example](./writing-perf-tests-example.html) for a practical example of creating a new test
|
||||
- [Performance test writing tips](./writing-perf-tests-tips.html) for detailed tips on how to write a good and efficient test
|
||||
- [Performance test writing example](writing-perf-tests-example.md) for a practical example of creating a new test
|
||||
- [Performance test writing tips](writing-perf-tests-tips.md) for detailed tips on how to write a good and efficient test
|
||||
|
||||
## Test location
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ But there can be a wide variety of highlighters. In particular, highlighters are
|
|||
|
||||
## Using highlighters
|
||||
|
||||
Highlighters run on the debuggee side, not on the toolbox side. This is so that it's possible to highlight elements on a remote device for instance. This means you need to go through the [Remote Debugging Protocol](protocol.md) to use a highlighter.
|
||||
Highlighters run on the debuggee side, not on the toolbox side. This is so that it's possible to highlight elements on a remote device for instance. This means you need to go through the [Remote Debugging Protocol](../backend/protocol.md) to use a highlighter.
|
||||
|
||||
The InspectorFront provides the following method:
|
||||
|
||||
|
|
|
@ -22,14 +22,16 @@ The memory tool is built of three main elements:
|
|||
|
||||
Unlike other tools (such as the JavaScript debugger), the memory tool makes very
|
||||
little use of the Remote DevTools Server and the actors that reside in it. Use
|
||||
of the [`MemoryActor`](devtools/server/actors/memory.js) is limited to toggling
|
||||
allocation stack recording on and off, and transferring heap snapshots from the
|
||||
debuggee (which is on the server) to the `HeapAnalysesWorker` (which is on the
|
||||
client). A nice benefit that naturally emerges, is that supporting "legacy"
|
||||
servers (eg, using Firefox Developer Edition as a client to remote debug a
|
||||
release Firefox for Android server) is a no-op. As we add new analyses, we can
|
||||
run them on snapshots taken on old servers no problem. The only requirement is
|
||||
that changes to the snapshot format itself remain backwards compatible.
|
||||
of the
|
||||
[`MemoryActor`](https://searchfox.org/mozilla-central/source/devtools/server/actors/memory.js)
|
||||
is limited to toggling allocation stack recording on and off, and transferring
|
||||
heap snapshots from the debuggee (which is on the server) to the
|
||||
`HeapAnalysesWorker` (which is on the client). A nice benefit that naturally
|
||||
emerges, is that supporting "legacy" servers (eg, using Firefox Developer
|
||||
Edition as a client to remote debug a release Firefox for Android server) is a
|
||||
no-op. As we add new analyses, we can run them on snapshots taken on old servers
|
||||
no problem. The only requirement is that changes to the snapshot format itself
|
||||
remain backwards compatible.
|
||||
|
||||
## `JS::ubi::Node`
|
||||
|
||||
|
@ -103,9 +105,9 @@ The `DeserializedNode` and `DeserializedEdge` classes implement the
|
|||
than the live heap graph operate on these classes (unknowingly, of course).
|
||||
|
||||
For more details, see the
|
||||
[`mozilla::devtools::HeapSnapshot`](devtools/shared/heapsnapshot/HeapSnapshot.cpp)
|
||||
[`mozilla::devtools::HeapSnapshot`](https://searchfox.org/mozilla-central/source/devtools/shared/heapsnapshot/HeapSnapshot.cpp)
|
||||
and
|
||||
[`mozilla::devtools::Deserialized{Node,Edge}`](devtools/shared/heapsnapshot/DeserializedNode.h)
|
||||
[`mozilla::devtools::Deserialized{Node,Edge}`](https://searchfox.org/mozilla-central/source/devtools/shared/heapsnapshot/DeserializedNode.h)
|
||||
classes.
|
||||
|
||||
### Heap Analyses
|
||||
|
@ -114,14 +116,15 @@ Heap analyses operate on `JS::ubi::Node` graphs without knowledge of whether
|
|||
that graph is backed by the live heap graph or an offline heap snapshot. They
|
||||
must make sure never to allocate GC things or modify the live heap graph.
|
||||
|
||||
In general, analyses are implemented in their own `js/public/Ubi{AnalysisName}.h`
|
||||
header (eg `js/public/UbiCensus.h`), and are exposed to chrome JavaScript code
|
||||
via a method on the [`HeapSnapshot`](dom/webidl/HeapSnapshot.webidl) webidl
|
||||
interface.
|
||||
In general, analyses are implemented in their own
|
||||
`js/public/Ubi{AnalysisName}.h` header (eg `js/public/UbiCensus.h`), and are
|
||||
exposed to chrome JavaScript code via a method on the
|
||||
[`HeapSnapshot`](https://searchfox.org/mozilla-central/source/dom/webidl/HeapSnapshot.webidl)
|
||||
webidl interface.
|
||||
|
||||
For each analysis we expose to chrome JavaScript on the `HeapSnapshot` webidl
|
||||
interface, there is a small amount of glue code in Gecko. The
|
||||
[`mozilla::devtools::HeapSnapshot`](devtools/shared/heapsnapshot/HeapSnapshot.h)
|
||||
[`mozilla::devtools::HeapSnapshot`](https://searchfox.org/mozilla-central/source/devtools/shared/heapsnapshot/HeapSnapshot.h)
|
||||
C++ class implements the webidl interface. The analyses methods (eg
|
||||
`ComputeDominatorTree`) take the deserialized nodes and edges from the heap
|
||||
snapshot, create `JS::ubi::Node`s from them, call the analyses from
|
||||
|
@ -129,7 +132,8 @@ snapshot, create `JS::ubi::Node`s from them, call the analyses from
|
|||
JavaScript.
|
||||
|
||||
For API documentation on running specific analyses, see the
|
||||
[`HeapSnapshot`](dom/webidl/HeapSnapshot.webidl) webidl interface.
|
||||
[`HeapSnapshot`](https://searchfox.org/mozilla-central/source/dom/webidl/HeapSnapshot.webidl)
|
||||
webidl interface.
|
||||
|
||||
### Testing `JS::ubi::Node`, Snapshots, and Analyses
|
||||
|
||||
|
|
|
@ -107,12 +107,11 @@ The reply is:
|
|||
"NetworkActivity",
|
||||
"FileActivity"
|
||||
],
|
||||
"nativeConsoleAPI": true,
|
||||
"from": "conn0.console9"
|
||||
}
|
||||
|
||||
|
||||
The reply tells which listeners were started and it includes a flag ``nativeConsoleAPI`` which tells if the ``window.console`` object was overridden by the scripts in the page or not.
|
||||
The reply tells which listeners were started.
|
||||
|
||||
|
||||
Tab navigation
|
||||
|
@ -133,11 +132,10 @@ When page navigation starts the following packet is sent from the tab actor:
|
|||
"type": "tabNavigated",
|
||||
"state": "start",
|
||||
"url": newURL,
|
||||
"nativeConsoleAPI": true
|
||||
}
|
||||
|
||||
|
||||
The ``nativeConsoleAPI`` property tells if the ``window.console`` object is native or not for the top level window object for the given tab - this is always ``true`` when navigation starts. When navigation stops the following packet is sent:
|
||||
When navigation stops the following packet is sent:
|
||||
|
||||
.. code-block::
|
||||
|
||||
|
@ -147,7 +145,6 @@ The ``nativeConsoleAPI`` property tells if the ``window.console`` object is nati
|
|||
"state": "stop",
|
||||
"url": newURL,
|
||||
"title": newTitle,
|
||||
"nativeConsoleAPI": true|false
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
/* global XPCNativeWrapper */
|
||||
|
||||
// protocol.js uses objects as exceptions in order to define
|
||||
// error packets.
|
||||
/* eslint-disable no-throw-literal */
|
||||
|
@ -159,9 +157,6 @@ const windowGlobalTargetPrototype = {
|
|||
* This event contains the following attributes:
|
||||
* * url (string)
|
||||
* The new URI being loaded.
|
||||
* * nativeConsoleAPI (boolean)
|
||||
* `false` if the console API of the page has been overridden (e.g. by Firebug)
|
||||
* `true` if the Gecko implementation is used
|
||||
* * state (string)
|
||||
* `start` if we just start requesting the new URL
|
||||
* `stop` if the new URL is done loading
|
||||
|
@ -1535,7 +1530,6 @@ const windowGlobalTargetPrototype = {
|
|||
if (!this.followWindowGlobalLifeCycle) {
|
||||
this.emit("tabNavigated", {
|
||||
url: newURI,
|
||||
nativeConsoleAPI: true,
|
||||
state: "start",
|
||||
isFrameSwitching,
|
||||
});
|
||||
|
@ -1586,34 +1580,11 @@ const windowGlobalTargetPrototype = {
|
|||
this.emit("tabNavigated", {
|
||||
url: this.url,
|
||||
title: this.title,
|
||||
nativeConsoleAPI: this.hasNativeConsoleAPI(this.window),
|
||||
state: "stop",
|
||||
isFrameSwitching: isFrameSwitching,
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Tells if the window.console object is native or overwritten by script in
|
||||
* the page.
|
||||
*
|
||||
* @param nsIDOMWindow window
|
||||
* The window object you want to check.
|
||||
* @return boolean
|
||||
* True if the window.console object is native, or false otherwise.
|
||||
*/
|
||||
hasNativeConsoleAPI(window) {
|
||||
let isNative = false;
|
||||
try {
|
||||
// We are very explicitly examining the "console" property of
|
||||
// the non-Xrayed object here.
|
||||
const console = window.wrappedJSObject.console;
|
||||
isNative = new XPCNativeWrapper(console).IS_NATIVE_CONSOLE;
|
||||
} catch (ex) {
|
||||
// ignore
|
||||
}
|
||||
return isNative;
|
||||
},
|
||||
|
||||
/**
|
||||
* Create or return the StyleSheetActor for a style sheet. This method
|
||||
* is here because the Style Editor and Inspector share style sheet actors.
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
/* global XPCNativeWrapper */
|
||||
const { ActorClassWithSpec, Actor } = require("devtools/shared/protocol");
|
||||
const { webconsoleSpec } = require("devtools/shared/specs/webconsole");
|
||||
|
||||
|
@ -377,28 +376,6 @@ const WebConsoleActor = ActorClassWithSpec(webconsoleSpec, {
|
|||
return { actor: this.actorID };
|
||||
},
|
||||
|
||||
hasNativeConsoleAPI: function(window) {
|
||||
if (isWorker || !(window instanceof Ci.nsIDOMWindow)) {
|
||||
// We can only use XPCNativeWrapper on non-worker nsIDOMWindow.
|
||||
return true;
|
||||
}
|
||||
|
||||
let isNative = false;
|
||||
try {
|
||||
// We are very explicitly examining the "console" property of
|
||||
// the non-Xrayed object here.
|
||||
const console = window.wrappedJSObject.console;
|
||||
// In xpcshell tests, console ends up being undefined and XPCNativeWrapper
|
||||
// crashes in debug builds.
|
||||
if (console) {
|
||||
isNative = new XPCNativeWrapper(console).IS_NATIVE_CONSOLE;
|
||||
}
|
||||
} catch (ex) {
|
||||
// ignored
|
||||
}
|
||||
return isNative;
|
||||
},
|
||||
|
||||
_findProtoChain: ThreadActor.prototype._findProtoChain,
|
||||
_removeFromProtoChain: ThreadActor.prototype._removeFromProtoChain,
|
||||
|
||||
|
@ -789,8 +766,7 @@ const WebConsoleActor = ActorClassWithSpec(webconsoleSpec, {
|
|||
startedListeners.forEach(this._listeners.add, this._listeners);
|
||||
|
||||
return {
|
||||
startedListeners: startedListeners,
|
||||
nativeConsoleAPI: this.hasNativeConsoleAPI(this.global),
|
||||
startedListeners,
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -1818,8 +1794,11 @@ const WebConsoleActor = ActorClassWithSpec(webconsoleSpec, {
|
|||
* - dom-complete
|
||||
* @param {Number} time
|
||||
* The time that the event is fired.
|
||||
* @param {Boolean} hasNativeConsoleAPI
|
||||
* Tells if the window.console object is native or overwritten by script in the page.
|
||||
* Only passed when `name` is "dom-complete" (see devtools/server/actors/webconsole/listeners/document-events.js).
|
||||
*/
|
||||
onDocumentEvent: function(name, { time }) {
|
||||
onDocumentEvent: function(name, { time, hasNativeConsoleAPI }) {
|
||||
// will-navigate event has been added in Fx91 and is only expected to be used
|
||||
// by DOCUMENT_EVENT watcher. For toolbox still not using watcher actor and DOCUMENT_EVENT watcher
|
||||
// will-navigate will be emitted based on target actor's will-navigate events.
|
||||
|
@ -1829,6 +1808,7 @@ const WebConsoleActor = ActorClassWithSpec(webconsoleSpec, {
|
|||
this.emit("documentEvent", {
|
||||
name,
|
||||
time,
|
||||
hasNativeConsoleAPI,
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
@ -242,14 +242,27 @@ class DevToolsFrameChild extends JSWindowActorChild {
|
|||
// This will destroy the content process one
|
||||
this._destroyTargetActor(watcherActorID);
|
||||
// And this will destroy the parent process one
|
||||
this.sendAsyncMessage("DevToolsFrameChild:destroy", {
|
||||
actors: [
|
||||
{
|
||||
watcherActorID,
|
||||
form,
|
||||
},
|
||||
],
|
||||
});
|
||||
try {
|
||||
this.sendAsyncMessage("DevToolsFrameChild:destroy", {
|
||||
actors: [
|
||||
{
|
||||
watcherActorID,
|
||||
form,
|
||||
},
|
||||
],
|
||||
});
|
||||
} catch (e) {
|
||||
// Ignore exception when the JSWindowActorChild has already been destroyed.
|
||||
// We often try to emit this message while the WindowGlobal is in the process of being
|
||||
// destroyed. We eagerly destroy the target actor during reloads,
|
||||
// just before the WindowGlobal starts destroying, but sendAsyncMessage
|
||||
// doesn't have time to complete and throws.
|
||||
if (
|
||||
!e.message.includes("JSWindowActorChild cannot send at the moment")
|
||||
) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
});
|
||||
this._connections.set(watcherActorID, {
|
||||
connection,
|
||||
|
|
|
@ -51,7 +51,6 @@ function assertEvent(event, data) {
|
|||
);
|
||||
is(data.state, "start", "state is start");
|
||||
is(data.url, URL2, "url property is correct");
|
||||
is(data.nativeConsoleAPI, true, "nativeConsoleAPI is correct");
|
||||
break;
|
||||
case isE10s ? 5 : 4:
|
||||
is(
|
||||
|
@ -80,7 +79,6 @@ function assertEvent(event, data) {
|
|||
is(event, "tabNavigated", "Finally, the receive the client event");
|
||||
is(data.state, "stop", "state is stop");
|
||||
is(data.url, URL2, "url property is correct");
|
||||
is(data.nativeConsoleAPI, true, "nativeConsoleAPI is correct");
|
||||
|
||||
signalAllEventsReceived();
|
||||
break;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[DEFAULT]
|
||||
tags = devtools
|
||||
head = head_dbg.js
|
||||
skip-if = toolkit == 'android' || socketprocess_networking
|
||||
skip-if = toolkit == 'android'
|
||||
firefox-appdir = browser
|
||||
|
||||
support-files=
|
||||
|
|
|
@ -138,7 +138,6 @@ const windowGlobalTargetSpecPrototype = {
|
|||
type: "tabNavigated",
|
||||
url: Option(0, "string"),
|
||||
title: Option(0, "string"),
|
||||
nativeConsoleAPI: Option(0, "boolean"),
|
||||
state: Option(0, "string"),
|
||||
isFrameSwitching: Option(0, "boolean"),
|
||||
},
|
||||
|
|
|
@ -14,7 +14,6 @@ const {
|
|||
|
||||
types.addDictType("console.startlisteners", {
|
||||
startedListeners: "array:string",
|
||||
nativeConsoleAPI: "nullable:boolean",
|
||||
});
|
||||
|
||||
types.addDictType("console.stoplisteners", {
|
||||
|
@ -96,6 +95,7 @@ const webconsoleSpecPrototype = {
|
|||
documentEvent: {
|
||||
name: Option(0, "string"),
|
||||
time: Option(0, "string"),
|
||||
hasNativeConsoleAPI: Option(0, "boolean"),
|
||||
},
|
||||
},
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@ async function startTest()
|
|||
let {state, response} = await attachConsoleToTab(["PageError"]);
|
||||
is(response.startedListeners.length, 1, "startedListeners.length");
|
||||
is(response.startedListeners[0], "PageError", "startedListeners: PageError");
|
||||
ok(response.nativeConsoleAPI, "nativeConsoleAPI");
|
||||
|
||||
await closeDebugger(state);
|
||||
top.console_ = top.console;
|
||||
|
@ -36,7 +35,6 @@ async function startTest()
|
|||
isnot(startedListeners.indexOf("ConsoleAPI"), -1,
|
||||
"startedListeners: ConsoleAPI");
|
||||
is(startedListeners.indexOf("foo"), -1, "startedListeners: no foo");
|
||||
ok(!response.nativeConsoleAPI, "!nativeConsoleAPI");
|
||||
|
||||
top.console = top.console_;
|
||||
response = await state.webConsoleFront.stopListeners(["ConsoleAPI", "foo"]);
|
||||
|
@ -48,7 +46,6 @@ async function startTest()
|
|||
|
||||
is(response.startedListeners.length, 1, "startedListeners.length");
|
||||
is(response.startedListeners[0], "ConsoleAPI", "startedListeners: ConsoleAPI");
|
||||
ok(response.nativeConsoleAPI, "nativeConsoleAPI");
|
||||
|
||||
top.console = top.console_;
|
||||
delete top.console_;
|
||||
|
|
|
@ -908,8 +908,6 @@ DevToolsStartup.prototype = {
|
|||
k.setAttribute("modifiers", mod);
|
||||
}
|
||||
|
||||
// Bug 371900: command event is fired only if "oncommand" attribute is set.
|
||||
k.setAttribute("oncommand", ";");
|
||||
k.addEventListener("command", oncommand);
|
||||
|
||||
return k;
|
||||
|
|
|
@ -93,3 +93,5 @@ redirects:
|
|||
tools/static-analysis/index.html: code-quality/static-analysis.html
|
||||
xpcom/xpcom: xpcom
|
||||
|
||||
fatal warnings:
|
||||
- "WARNING: '([^']*)' reference target not found:"
|
||||
|
|
|
@ -5,9 +5,8 @@ asynchronous and massively parallel architecture.
|
|||
|
||||
## Tools
|
||||
|
||||
PIX - Can do timing of Direct3D calls. Works reasonably well with
|
||||
Firefox. See also [Debugging With
|
||||
PIX](/en/Debugging_With_PIX "en/Debugging With PIX").
|
||||
[PIX](https://devblogs.microsoft.com/pix/introduction/) - Can do
|
||||
timing of Direct3D calls. Works reasonably well with Firefox.
|
||||
|
||||
NVIDIA PerfHUD - Last I checked required a special build to be used.
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ degree):
|
|||
- [Talos](https://wiki.mozilla.org/TestEngineering/Performance/Talos): The main
|
||||
performance system, run on virtually every check-in to an
|
||||
integration branch
|
||||
- [build_metrics](/setup/configuring_build_options.html):
|
||||
- [build_metrics](/setup/configuring_build_options.rst):
|
||||
A grab bag of performance metrics generated by the build system
|
||||
- [AreWeFastYet](https://arewefastyet.com/): A generic JavaScript and
|
||||
Web benchmarking system
|
||||
|
|
|
@ -5,8 +5,7 @@ be used to profile wakeups. This article provides a light introduction
|
|||
to it.
|
||||
|
||||
:::
|
||||
**Note**: The [power profiling
|
||||
overview](/en-US/docs/Mozilla/Performance/Power_profiling_overview) is
|
||||
**Note**: The [power profiling overview](power_profiling_overview.md) is
|
||||
worth reading at this point if you haven't already. It may make parts
|
||||
of this document easier to understand.
|
||||
:::
|
||||
|
@ -16,7 +15,7 @@ of this document easier to understand.
|
|||
`dtrace` must be invoked as the super-user. A good starting command for
|
||||
profiling wakeups is the following.
|
||||
|
||||
```
|
||||
```
|
||||
sudo dtrace -n 'mach_kernel::wakeup { @[ustack()] = count(); }' -p $FIREFOX_PID > $OUTPUT_FILE
|
||||
```
|
||||
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
|
||||
This page explains how optimize the performance the Firefox code base
|
||||
|
||||
The [test documentation](../../testing/perfdocs/)
|
||||
explains how to test for performance in Firefox.
|
||||
The [profiler documentation](../../tools/profiler/)
|
||||
explains how to use the Gecko profiler.
|
||||
The [test documentation](/testing/perfdocs/index.rst)
|
||||
explains how to test for performance in Firefox.
|
||||
The [profiler documentation](/tools/profiler/index.rst)
|
||||
explains how to use the Gecko profiler.
|
||||
|
||||
## General Performance references
|
||||
* Tips on generating valid performance metrics by [benchmarking](benchmarking.md)
|
||||
* Tips on generating valid performance metrics by [benchmarking](Benchmarking.md)
|
||||
* [GPU Performance](GPU_performance.md) Tips for reducing impacts on browser performance in front-end code.
|
||||
* [Automated Performance testing and Sheriffing](automated_performance_testing_and_sheriffing.md) Information on automated performance testing and sheriffing at Mozilla.
|
||||
* [Performance best practices for Firefox front-end engineers](bestpractices.md) Tips for reducing impacts on browser performance in front-end code.
|
||||
|
|
|
@ -12,7 +12,7 @@ of this document easier to understand.
|
|||
|
||||
## Invocation
|
||||
|
||||
First, do a [standard build of Firefox](../setup/index.html).
|
||||
First, do a [standard build of Firefox](/setup/index.rst).
|
||||
|
||||
### Mac
|
||||
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
This page explains how to test and debug Rust code in Firefox.
|
||||
|
||||
The [build documentation](../build/buildsystem/rust.html) explains how to add
|
||||
new Rust code to Firefox. The [code documentation](../writing-rust-code)
|
||||
The [build documentation](/build/buildsystem/rust.rst) explains how to add
|
||||
new Rust code to Firefox. The [code documentation](/writing-rust-code/index.md)
|
||||
explains how to write and work with Rust code in Firefox.
|
||||
|
||||
## Testing Mozilla crates
|
||||
|
@ -31,7 +31,7 @@ It's also possible to use `RUST_TESTS` in a different `moz.build` file. See
|
|||
`testing/geckodriver/moz.build` and the [geckodriver testing docs] for an
|
||||
example.
|
||||
|
||||
[geckodriver testing docs]: ../testing/geckodriver/Testing.html
|
||||
[geckodriver testing docs]: /testing/geckodriver/Testing.md
|
||||
|
||||
### GTests
|
||||
|
||||
|
@ -102,7 +102,7 @@ To restrict logging to child processes, use `RUST_LOG_CHILD` instead of
|
|||
Rust logging can also be forwarded to the [Gecko logger] for capture via
|
||||
`MOZ_LOG` and `MOZ_LOG_FILE`.
|
||||
|
||||
[Gecko logger]: /xpcom/logging.html
|
||||
[Gecko logger]: /xpcom/logging.rst
|
||||
|
||||
- When parsing modules from `MOZ_LOG`, modules containing `::` are considered
|
||||
to be Rust modules. To log everything in a top-level module like
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
This page explains how to write and work with Rust code in Firefox, with an
|
||||
emphasis on interoperation with C++ code.
|
||||
|
||||
The [build documentation](../build/buildsystem/rust.html) explains how to add
|
||||
new Rust code to Firefox. The [test documentation](../testing-rust-code)
|
||||
The [build documentation](/build/buildsystem/rust.rst) explains how to add
|
||||
new Rust code to Firefox. The [test documentation](/testing-rust-code/index.md)
|
||||
explains how to test and debug Rust code in Firefox.
|
||||
|
||||
```{toctree}
|
||||
|
|
|
@ -21,7 +21,7 @@ xpcom = { path = "../../../xpcom/rust/xpcom" }
|
|||
file hierarchy.)
|
||||
|
||||
Next hook it into the build system according to the [build
|
||||
documentation](../build/buildsystem/rust.html).
|
||||
documentation](/build/buildsystem/rust.rst).
|
||||
|
||||
The Rust code will need to import some basic types. `xpcom::interfaces`
|
||||
contains all the usual `nsI` interfaces.
|
||||
|
@ -33,7 +33,7 @@ use std::sync::atomic::{AtomicBool, Ordering};
|
|||
use xpcom::{interfaces::nsISupports, RefPtr};
|
||||
```
|
||||
|
||||
The next part declares the implementation.
|
||||
The next part declares the implementation.
|
||||
|
||||
```rust
|
||||
#[derive(xpcom)]
|
||||
|
@ -110,11 +110,11 @@ The following XPCOM components are written in Rust.
|
|||
- [bookmark_sync](https://searchfox.org/mozilla-central/source/toolkit/components/places/bookmark_sync),
|
||||
which [merges](https://mozilla.github.io/dogear) bookmarks from Firefox Sync
|
||||
with bookmarks in the Places database.
|
||||
[There's also some docs on how Rust interacts with Sync](../services/sync/rust-engines.html)
|
||||
[There's also some docs on how Rust interacts with Sync](/services/sync/rust-engines.rst)
|
||||
- [webext_storage_bridge](https://searchfox.org/mozilla-central/source/toolkit/components/extensions/storage/webext_storage_bridge),
|
||||
which powers the WebExtension storage.sync API. It's a self-contained example
|
||||
that pulls in a crate from application-services for the heavy lifting, wraps
|
||||
that up in a Rust XPCOM component, and then wraps the component in a JS
|
||||
interface. There's also some boilerplate there around adding a
|
||||
`components.conf` file, and a dummy C++ header that declares the component
|
||||
constructor. [It has some in-depth documentation on how it hangs together](../toolkit/components/extensions/webextensions/webext-storage.html).
|
||||
constructor. [It has some in-depth documentation on how it hangs together](../toolkit/components/extensions/webextensions/webext-storage.rst).
|
||||
|
|
|
@ -287,7 +287,8 @@ class CanonicalBrowsingContext final : public BrowsingContext {
|
|||
|
||||
void SetRestoreData(SessionStoreRestoreData* aData, ErrorResult& aError);
|
||||
void ClearRestoreState();
|
||||
void RequestRestoreTabContent(WindowGlobalParent* aWindow);
|
||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY void RequestRestoreTabContent(
|
||||
WindowGlobalParent* aWindow);
|
||||
already_AddRefed<Promise> GetRestorePromise();
|
||||
|
||||
nsresult WriteSessionStorageToSessionStore(
|
||||
|
|
|
@ -315,7 +315,10 @@ bool CCGCScheduler::GCRunnerFiredDoGC(TimeStamp aDeadline,
|
|||
if (!aDeadline.IsNull()) {
|
||||
if (aDeadline < now) {
|
||||
// This slice overflowed the idle period.
|
||||
idleDuration = aDeadline - startTimeStamp;
|
||||
if (aDeadline > startTimeStamp) {
|
||||
idleDuration = aDeadline - startTimeStamp;
|
||||
}
|
||||
// Otherwise the whole slice was done outside the idle period.
|
||||
} else {
|
||||
// Note, we don't want to use duration here, since it may contain
|
||||
// data also from JS engine triggered GC slices.
|
||||
|
|
|
@ -2051,6 +2051,7 @@ already_AddRefed<EventSource> EventSource::Constructor(
|
|||
}
|
||||
eventSource->mReadyState = EventSourceImpl::CONNECTING;
|
||||
|
||||
guardESImpl.release();
|
||||
return eventSource.forget();
|
||||
}
|
||||
|
||||
|
|
|
@ -80,7 +80,10 @@ support-files =
|
|||
file_bug1700871.html
|
||||
[browser_inputStream_structuredClone.js]
|
||||
[browser_multiple_popups.js]
|
||||
skip-if = (os == 'win' && !debug) || (os == "mac" && !debug) # Bug 1505235, Bug 1661132 (osx)
|
||||
skip-if =
|
||||
(os == 'win' && !debug)
|
||||
(os == "mac" && !debug) # Bug 1505235, Bug 1661132 (osx)
|
||||
socketprocess_networking
|
||||
support-files = browser_multiple_popups.html
|
||||
[browser_bug1554070.js]
|
||||
support-files =
|
||||
|
|
|
@ -93,8 +93,7 @@ static std::string ChooseDeviceReplacement(const std::string& str) {
|
|||
static const std::string GEFORCE_480 = "GeForce GTX 480";
|
||||
static const std::string GEFORCE_980 = "GeForce GTX 980";
|
||||
|
||||
if (Contains(str, "NVIDIA") ||
|
||||
Contains(str, "GeForce") ||
|
||||
if (Contains(str, "NVIDIA") || Contains(str, "GeForce") ||
|
||||
Contains(str, "Quadro")) {
|
||||
auto ret = std::invoke([&]() {
|
||||
static const std::regex kGeForce("GeForce.*?([0-9][0-9][0-9]+)");
|
||||
|
@ -276,7 +275,8 @@ static std::string ChooseDeviceReplacement(const std::string& str) {
|
|||
std::string SanitizeRenderer(const std::string& str) {
|
||||
std::smatch m;
|
||||
|
||||
// e.g. "ANGLE (AMD, AMD Radeon(TM) Graphics Direct3D11 vs_5_0 ps_5_0, D3D11-27.20.1020.2002)"
|
||||
// e.g. "ANGLE (AMD, AMD Radeon(TM) Graphics Direct3D11 vs_5_0 ps_5_0,
|
||||
// D3D11-27.20.1020.2002)"
|
||||
static const std::regex kReAngle(
|
||||
"ANGLE [(]([^,]*), ([^,]*)( Direct3D[^,]*), .*[)]");
|
||||
if (std::regex_match(str, m, kReAngle)) {
|
||||
|
|
|
@ -266,9 +266,7 @@ class UniqueBuffer final {
|
|||
|
||||
UniqueBuffer() = default;
|
||||
|
||||
~UniqueBuffer() {
|
||||
reset();
|
||||
}
|
||||
~UniqueBuffer() { reset(); }
|
||||
|
||||
UniqueBuffer(UniqueBuffer&& rhs) { *this = std::move(rhs); }
|
||||
|
||||
|
|
|
@ -202,41 +202,49 @@ TEST(SanitizeRenderer, TestAdreno512)
|
|||
}
|
||||
|
||||
// -
|
||||
// Keep gtests for our known CI RENDERER strings (see test_renderer_strings.html)
|
||||
// otherwise the first time we know we messed up is in CI results after an hour,
|
||||
// instead of after running gtests locally.
|
||||
// Keep gtests for our known CI RENDERER strings (see
|
||||
// test_renderer_strings.html) otherwise the first time we know we messed up is
|
||||
// in CI results after an hour, instead of after running gtests locally.
|
||||
|
||||
TEST(SanitizeRenderer, TestCiAndroid) {
|
||||
TEST(SanitizeRenderer, TestCiAndroid)
|
||||
{
|
||||
const std::string renderer("Adreno (TM) 540");
|
||||
const std::string expectation("Adreno (TM) 540");
|
||||
const auto sanitized = mozilla::webgl::SanitizeRenderer(renderer);
|
||||
EXPECT_EQ(sanitized, expectation);
|
||||
}
|
||||
|
||||
TEST(SanitizeRenderer, TestCiLinux) {
|
||||
TEST(SanitizeRenderer, TestCiLinux)
|
||||
{
|
||||
const std::string renderer("llvmpipe (LLVM 10.0.0, 256 bits)");
|
||||
const std::string expectation("llvmpipe");
|
||||
const auto sanitized = mozilla::webgl::SanitizeRenderer(renderer);
|
||||
EXPECT_EQ(sanitized, expectation);
|
||||
}
|
||||
|
||||
TEST(SanitizeRenderer, TestCiMac) {
|
||||
TEST(SanitizeRenderer, TestCiMac)
|
||||
{
|
||||
const std::string renderer("Intel(R) UHD Graphics 630");
|
||||
const std::string expectation("Intel(R) HD Graphics 400");
|
||||
const auto sanitized = mozilla::webgl::SanitizeRenderer(renderer);
|
||||
EXPECT_EQ(sanitized, expectation);
|
||||
}
|
||||
|
||||
TEST(SanitizeRenderer, TestCiMac2) {
|
||||
TEST(SanitizeRenderer, TestCiMac2)
|
||||
{
|
||||
const std::string renderer("Apple M1");
|
||||
const std::string expectation("Apple M1");
|
||||
const auto sanitized = mozilla::webgl::SanitizeRenderer(renderer);
|
||||
EXPECT_EQ(sanitized, expectation);
|
||||
}
|
||||
|
||||
TEST(SanitizeRenderer, TestCiWindows) {
|
||||
const std::string renderer("ANGLE (NVIDIA, NVIDIA Tesla M60 Direct3D11 vs_5_0 ps_5_0, D3D11-23.21.13.9181)");
|
||||
const std::string expectation("ANGLE (NVIDIA, NVIDIA GeForce 8800 GTX Direct3D11 vs_5_0 ps_5_0)");
|
||||
TEST(SanitizeRenderer, TestCiWindows)
|
||||
{
|
||||
const std::string renderer(
|
||||
"ANGLE (NVIDIA, NVIDIA Tesla M60 Direct3D11 vs_5_0 ps_5_0, "
|
||||
"D3D11-23.21.13.9181)");
|
||||
const std::string expectation(
|
||||
"ANGLE (NVIDIA, NVIDIA GeForce 8800 GTX Direct3D11 vs_5_0 ps_5_0)");
|
||||
const auto sanitized = mozilla::webgl::SanitizeRenderer(renderer);
|
||||
EXPECT_EQ(sanitized, expectation);
|
||||
}
|
||||
|
|
|
@ -1361,7 +1361,7 @@ Multiple `[Alias]` extended attribute can be used on the one method.
|
|||
global interface (such as `Window`).
|
||||
|
||||
Aside from regular property names, the name of an alias can be
|
||||
[Symbol.iterator](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol#Well-known_symbols).
|
||||
[Symbol.iterator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/iterator).
|
||||
This is specified by writing `[Alias="@@iterator"]`.
|
||||
|
||||
### `[BindingAlias=propName]`
|
||||
|
@ -1757,7 +1757,7 @@ the cached value.
|
|||
### `[Frozen]`
|
||||
|
||||
Used to flag attributes that, when their getter is called, will call
|
||||
[`Object.freeze`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze)
|
||||
[`Object.freeze`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze)
|
||||
on the return value before returning it. This extended attribute is only
|
||||
allowed on attributes that return sequences, dictionaries and
|
||||
`MozMap`, and corresponds to returning a frozen `Array` (for the
|
||||
|
@ -2184,15 +2184,13 @@ interface MyNumber {
|
|||
};
|
||||
```
|
||||
|
||||
Next, create an XPCOM component that implements this interface. [Basic
|
||||
directions](/en-US/docs/How_to_Build_an_XPCOM_Component_in_Javascript)
|
||||
for how to do this can be found elsewhere on MDN. Use the same contract
|
||||
ID as you specified in the Web IDL file. The class ID doesn't matter,
|
||||
except that it should be a newly generated one. For `QueryInterface`,
|
||||
you only need to implement `nsISupports`, not anything corresponding
|
||||
to the Web IDL interface. The name you use for the XPCOM component should
|
||||
be distinct from the name of the interface, to avoid confusing error
|
||||
messages.
|
||||
Next, create an XPCOM component that implements this interface. Use
|
||||
the same contract ID as you specified in the Web IDL file. The class
|
||||
ID doesn't matter, except that it should be a newly generated one. For
|
||||
`QueryInterface`, you only need to implement `nsISupports`, not
|
||||
anything corresponding to the Web IDL interface. The name you use for
|
||||
the XPCOM component should be distinct from the name of the interface,
|
||||
to avoid confusing error messages.
|
||||
|
||||
Web IDL attributes are implemented as properties on the JS object or its
|
||||
prototype chain, whereas Web IDL methods are implemented as methods on
|
||||
|
|
|
@ -584,8 +584,13 @@ bool XULKeySetGlobalKeyListener::IsExecutableElement(
|
|||
return false;
|
||||
}
|
||||
|
||||
aElement->GetAttr(nsGkAtoms::oncommand, value);
|
||||
return !value.IsEmpty();
|
||||
// Internal keys are defined as <key> elements so that the menu label
|
||||
// and disabled state can be updated properly, but the command is executed
|
||||
// by some other means. This will typically be because the key is defined
|
||||
// as a shortcut defined in ShortcutKeyDefinitions.cpp instead, or on Mac,
|
||||
// some special system defined keys.
|
||||
return !aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::internal,
|
||||
nsGkAtoms::_true, eCaseMatters);
|
||||
}
|
||||
|
||||
already_AddRefed<dom::EventTarget> XULKeySetGlobalKeyListener::GetHandlerTarget(
|
||||
|
|
|
@ -466,7 +466,6 @@ nsresult HTMLCanvasElement::DispatchPrintCallback(nsITimerCallback* aCallback) {
|
|||
return OwnerDoc()->Dispatch(TaskCategory::Other, renderEvent.forget());
|
||||
}
|
||||
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
void HTMLCanvasElement::CallPrintCallback() {
|
||||
if (!mPrintState) {
|
||||
// `mPrintState` might have been destroyed by cancelling the previous
|
||||
|
|
|
@ -334,7 +334,7 @@ class HTMLCanvasElement final : public nsGenericHTMLElement,
|
|||
const JS::Value& aEncoderOptions, nsAString& aDataURL);
|
||||
nsresult MozGetAsFileImpl(const nsAString& aName, const nsAString& aType,
|
||||
nsIPrincipal& aSubjectPrincipal, File** aResult);
|
||||
void CallPrintCallback();
|
||||
MOZ_CAN_RUN_SCRIPT void CallPrintCallback();
|
||||
|
||||
virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
|
||||
const nsAttrValue* aValue,
|
||||
|
|
|
@ -1561,7 +1561,7 @@ Decimal HTMLInputElement::StringToDecimal(const nsAString& aValue) {
|
|||
return Decimal::nan();
|
||||
}
|
||||
NS_LossyConvertUTF16toASCII asciiString(aValue);
|
||||
std::string stdString = asciiString.get();
|
||||
std::string stdString(asciiString.get(), asciiString.Length());
|
||||
return Decimal::fromString(stdString);
|
||||
}
|
||||
|
||||
|
|
|
@ -95,12 +95,7 @@ nsresult NumericInputTypeBase::GetRangeUnderflowMessage(nsAString& aMessage) {
|
|||
|
||||
bool NumericInputTypeBase::ConvertStringToNumber(nsAString& aValue,
|
||||
Decimal& aResultValue) const {
|
||||
ICUUtils::LanguageTagIterForContent langTagIter(mInputElement);
|
||||
aResultValue =
|
||||
Decimal::fromDouble(ICUUtils::ParseNumber(aValue, langTagIter));
|
||||
if (!aResultValue.isFinite()) {
|
||||
aResultValue = HTMLInputElement::StringToDecimal(aValue);
|
||||
}
|
||||
aResultValue = HTMLInputElement::StringToDecimal(aValue);
|
||||
return aResultValue.isFinite();
|
||||
}
|
||||
|
||||
|
@ -138,6 +133,17 @@ bool NumberInputType::HasBadInput() const {
|
|||
return !value.IsEmpty() && mInputElement->GetValueAsDecimal().isNaN();
|
||||
}
|
||||
|
||||
bool NumberInputType::ConvertStringToNumber(nsAString& aValue,
|
||||
Decimal& aResultValue) const {
|
||||
ICUUtils::LanguageTagIterForContent langTagIter(mInputElement);
|
||||
aResultValue =
|
||||
Decimal::fromDouble(ICUUtils::ParseNumber(aValue, langTagIter));
|
||||
if (aResultValue.isFinite()) {
|
||||
return true;
|
||||
}
|
||||
return NumericInputTypeBase::ConvertStringToNumber(aValue, aResultValue);
|
||||
}
|
||||
|
||||
bool NumberInputType::ConvertNumberToString(Decimal aValue,
|
||||
nsAString& aResultString) const {
|
||||
MOZ_ASSERT(aValue.isFinite(), "aValue must be a valid non-Infinite number.");
|
||||
|
|
|
@ -46,6 +46,8 @@ class NumberInputType final : public NumericInputTypeBase {
|
|||
nsresult GetValueMissingMessage(nsAString& aMessage) override;
|
||||
nsresult GetBadInputMessage(nsAString& aMessage) override;
|
||||
|
||||
bool ConvertStringToNumber(nsAString& aValue,
|
||||
Decimal& aResultValue) const override;
|
||||
bool ConvertNumberToString(Decimal aValue,
|
||||
nsAString& aResultString) const override;
|
||||
|
||||
|
|
|
@ -311,7 +311,7 @@ bool ClonedErrorHolder::ToErrorValue(JSContext* aCx,
|
|||
if (mTokenOffset >= sourceLine.Length()) {
|
||||
// Corrupt data, leave linebuf unset.
|
||||
} else if (JS::UniqueTwoByteChars buffer =
|
||||
ToNullTerminatedJSStringBuffer(aCx, sourceLine)) {
|
||||
ToNullTerminatedJSStringBuffer(aCx, sourceLine)) {
|
||||
err->initOwnedLinebuf(buffer.release(), sourceLine.Length(),
|
||||
mTokenOffset);
|
||||
} else {
|
||||
|
|
|
@ -187,7 +187,8 @@ class WindowGlobalChild final : public WindowGlobalActor,
|
|||
const dom::sessionstore::DocShellRestoreState& aState,
|
||||
RestoreDocShellStateResolver&& aResolve);
|
||||
|
||||
mozilla::ipc::IPCResult RecvRestoreTabContent(
|
||||
// TODO: Use MOZ_CAN_RUN_SCRIPT when it gains IPDL support (bug 1539864)
|
||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY mozilla::ipc::IPCResult RecvRestoreTabContent(
|
||||
dom::SessionStoreRestoreData* aData,
|
||||
RestoreTabContentResolver&& aResolve);
|
||||
|
||||
|
|
|
@ -266,9 +266,8 @@ class AudioInputTrack : public ProcessedMediaTrack {
|
|||
}
|
||||
// Get the data in [aFrom, aTo) from aPort->GetSource() to aOutput. aOutput
|
||||
// needs to be empty.
|
||||
void GetInputSourceData(AudioSegment& aOutput,
|
||||
const MediaInputPort* aPort, GraphTime aFrom,
|
||||
GraphTime aTo) const;
|
||||
void GetInputSourceData(AudioSegment& aOutput, const MediaInputPort* aPort,
|
||||
GraphTime aFrom, GraphTime aTo) const;
|
||||
|
||||
// Any thread
|
||||
AudioInputTrack* AsAudioInputTrack() override { return this; }
|
||||
|
|
|
@ -71,9 +71,12 @@ void MIDIOutput::Send(const Sequence<uint8_t>& aData,
|
|||
}
|
||||
|
||||
nsTArray<MIDIMessage> msgArray;
|
||||
MIDIUtils::ParseMessages(aData, timestamp, msgArray);
|
||||
// Our translation of the spec is that invalid messages in a multi-message
|
||||
// sequence will be thrown out, but that valid messages will still be used.
|
||||
bool ret = MIDIUtils::ParseMessages(aData, timestamp, msgArray);
|
||||
if (!ret) {
|
||||
aRv.ThrowTypeError("Invalid MIDI message");
|
||||
return;
|
||||
}
|
||||
|
||||
if (msgArray.IsEmpty()) {
|
||||
aRv.ThrowTypeError("Empty message array");
|
||||
return;
|
||||
|
|
|
@ -21,33 +21,65 @@ static const uint8_t kCommandLengths[] = {3, 3, 3, 3, 2, 2, 3};
|
|||
// messages is variable, so we just put zero since it won't be checked anyways.
|
||||
// Taken from MIDI Spec v1.0, Pg. 105, Table 5
|
||||
static const uint8_t kSystemLengths[] = {0, 2, 3, 2, 1, 1, 1, 1};
|
||||
static const uint8_t kReservedStatuses[] = {0xf4, 0xf5, 0xf9, 0xfd};
|
||||
|
||||
namespace mozilla::dom::MIDIUtils {
|
||||
|
||||
static bool IsSystemRealtimeMessage(uint8_t aByte) {
|
||||
return (aByte & kSystemRealtimeMessage) == kSystemRealtimeMessage;
|
||||
}
|
||||
|
||||
static bool IsCommandByte(uint8_t aByte) {
|
||||
return (aByte & kCommandByte) == kCommandByte;
|
||||
}
|
||||
|
||||
static bool IsReservedStatus(uint8_t aByte) {
|
||||
for (const auto& msg : kReservedStatuses) {
|
||||
if (aByte == msg) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Checks validity of MIDIMessage passed to it. Throws debug warnings and
|
||||
// returns false if message is not valid.
|
||||
bool IsValidMessage(const MIDIMessage* aMsg) {
|
||||
if (NS_WARN_IF(!aMsg)) {
|
||||
if (aMsg->data().Length() == 0) {
|
||||
return false;
|
||||
}
|
||||
// Assert on parser problems
|
||||
MOZ_ASSERT(aMsg->data().Length() > 0,
|
||||
"Created a MIDI Message of Length 0. This should never happen!");
|
||||
|
||||
uint8_t cmd = aMsg->data()[0];
|
||||
// If first byte isn't a command, something is definitely wrong.
|
||||
MOZ_ASSERT((cmd & kCommandByte) == kCommandByte,
|
||||
"Constructed a MIDI packet where first byte is not command!");
|
||||
if (!IsCommandByte(cmd)) {
|
||||
NS_WARNING("Constructed a MIDI packet where first byte is not command!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsReservedStatus(cmd)) {
|
||||
NS_WARNING("Using a reserved message");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cmd == kSysexMessageStart) {
|
||||
// All we can do with sysex is make sure it starts and ends with the
|
||||
// correct command bytes.
|
||||
// All we can do with sysex is make sure it starts and ends with the
|
||||
// correct command bytes and that it does not contain other command bytes.
|
||||
if (aMsg->data()[aMsg->data().Length() - 1] != kSysexMessageEnd) {
|
||||
NS_WARNING("Last byte of Sysex Message not 0xF7!");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 1; i < aMsg->data().Length() - 2; i++) {
|
||||
if (IsCommandByte(aMsg->data()[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
// For system realtime messages, the length should always be 1.
|
||||
if ((cmd & kSystemRealtimeMessage) == kSystemRealtimeMessage) {
|
||||
if (IsSystemRealtimeMessage(cmd)) {
|
||||
return aMsg->data().Length() == 1;
|
||||
}
|
||||
// Otherwise, just use the correct array for testing lengths. We can't tell
|
||||
|
@ -72,44 +104,66 @@ bool IsValidMessage(const MIDIMessage* aMsg) {
|
|||
return aMsg->data().Length() == kCommandLengths[cmdIndex];
|
||||
}
|
||||
|
||||
uint32_t ParseMessages(const nsTArray<uint8_t>& aByteBuffer,
|
||||
const TimeStamp& aTimestamp,
|
||||
nsTArray<MIDIMessage>& aMsgArray) {
|
||||
bool ParseMessages(const nsTArray<uint8_t>& aByteBuffer,
|
||||
const TimeStamp& aTimestamp,
|
||||
nsTArray<MIDIMessage>& aMsgArray) {
|
||||
uint32_t bytesRead = 0;
|
||||
bool inSysexMessage = false;
|
||||
UniquePtr<MIDIMessage> currentMsg;
|
||||
UniquePtr<MIDIMessage> currentMsg = nullptr;
|
||||
for (const auto& byte : aByteBuffer) {
|
||||
bytesRead++;
|
||||
if ((byte & kSystemRealtimeMessage) == kSystemRealtimeMessage) {
|
||||
|
||||
if (IsSystemRealtimeMessage(byte)) {
|
||||
MIDIMessage rt_msg;
|
||||
rt_msg.data().AppendElement(byte);
|
||||
rt_msg.timestamp() = aTimestamp;
|
||||
if (!IsValidMessage(&rt_msg)) {
|
||||
return false;
|
||||
}
|
||||
aMsgArray.AppendElement(rt_msg);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (byte == kSysexMessageEnd) {
|
||||
if (!inSysexMessage) {
|
||||
MOZ_ASSERT(inSysexMessage);
|
||||
NS_WARNING(
|
||||
"Got sysex message end with no sysex message being processed!");
|
||||
return false;
|
||||
}
|
||||
inSysexMessage = false;
|
||||
} else if (byte & kCommandByte) {
|
||||
if (currentMsg && IsValidMessage(currentMsg.get())) {
|
||||
} else if (IsCommandByte(byte)) {
|
||||
if (currentMsg) {
|
||||
if (!IsValidMessage(currentMsg.get())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aMsgArray.AppendElement(*currentMsg);
|
||||
}
|
||||
|
||||
currentMsg = MakeUnique<MIDIMessage>();
|
||||
currentMsg->timestamp() = aTimestamp;
|
||||
}
|
||||
|
||||
if (!currentMsg) {
|
||||
NS_WARNING("No command byte has been encountered yet!");
|
||||
return false;
|
||||
}
|
||||
|
||||
currentMsg->data().AppendElement(byte);
|
||||
|
||||
if (byte == kSysexMessageStart) {
|
||||
inSysexMessage = true;
|
||||
}
|
||||
}
|
||||
if (currentMsg && IsValidMessage(currentMsg.get())) {
|
||||
|
||||
if (currentMsg) {
|
||||
if (!IsValidMessage(currentMsg.get())) {
|
||||
return false;
|
||||
}
|
||||
aMsgArray.AppendElement(*currentMsg);
|
||||
}
|
||||
return bytesRead;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsSysexMessage(const MIDIMessage& aMsg) {
|
||||
|
|
|
@ -17,10 +17,10 @@ class MIDIMessage;
|
|||
namespace MIDIUtils {
|
||||
|
||||
// Takes a nsTArray of bytes and parses it into zero or more MIDI messages.
|
||||
// Returns number of bytes parsed.
|
||||
uint32_t ParseMessages(const nsTArray<uint8_t>& aByteBuffer,
|
||||
const TimeStamp& aTimestamp,
|
||||
nsTArray<MIDIMessage>& aMsgArray);
|
||||
// Returns true if no errors were encountered, false otherwise.
|
||||
bool ParseMessages(const nsTArray<uint8_t>& aByteBuffer,
|
||||
const TimeStamp& aTimestamp,
|
||||
nsTArray<MIDIMessage>& aMsgArray);
|
||||
// Returns true if a message is a sysex message.
|
||||
bool IsSysexMessage(const MIDIMessage& a);
|
||||
} // namespace MIDIUtils
|
||||
|
|
|
@ -107,6 +107,7 @@ void TestMIDIPlatformService::Init() {
|
|||
MIDIPlatformService::Get()->AddPortInfo(mControlInputPort);
|
||||
MIDIPlatformService::Get()->AddPortInfo(mControlOutputPort);
|
||||
MIDIPlatformService::Get()->AddPortInfo(mAlwaysClosedTestOutputPort);
|
||||
MIDIPlatformService::Get()->AddPortInfo(mStateTestOutputPort);
|
||||
nsCOMPtr<nsIRunnable> r(new SendPortListRunnable());
|
||||
|
||||
// Start the IO Thread.
|
||||
|
@ -220,8 +221,8 @@ void TestMIDIPlatformService::ProcessMessages(const nsAString& aPortId) {
|
|||
// messages.
|
||||
case 0x01: {
|
||||
nsTArray<uint8_t> msgs;
|
||||
const uint8_t msg[] = {0xF0, 0x01, 0xF8, 0x02, 0x03,
|
||||
0x04, 0xF9, 0x05, 0xF7};
|
||||
const uint8_t msg[] = {0xF0, 0x01, 0xFA, 0x02, 0x03,
|
||||
0x04, 0xF8, 0x05, 0xF7};
|
||||
// Can't use AppendElements on an array here, so just do range
|
||||
// based loading.
|
||||
for (const auto& s : msg) {
|
||||
|
|
|
@ -19,3 +19,4 @@ skip-if = os == 'android' || os == 'linux' || os == 'mac' #Bug 1747637
|
|||
disabled = Bug 1437204
|
||||
[test_midi_device_pending.html]
|
||||
disabled = Bug 1437204
|
||||
[test_midi_send_messages.html]
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
var inputs = access.inputs;
|
||||
var outputs = access.outputs;
|
||||
is(inputs.size, 1, "Should have one input");
|
||||
is(outputs.size, 2, "Should have two outputs");
|
||||
is(outputs.size, 3, "Should have three outputs");
|
||||
ok(inputs.has(input_id), "input list should contain input id");
|
||||
ok(outputs.has(output_id), "output list should contain output id");
|
||||
var input = access.inputs.get(input_id);
|
||||
|
|
|
@ -18,9 +18,9 @@
|
|||
function checkReturn(msg) {
|
||||
checkCount++;
|
||||
if (checkCount == 1) {
|
||||
MIDITestUtils.checkPacket(msg.data, [0xF8]);
|
||||
MIDITestUtils.checkPacket(msg.data, [0xFA]);
|
||||
} else if (checkCount == 2) {
|
||||
MIDITestUtils.checkPacket(msg.data, [0xF9]);
|
||||
MIDITestUtils.checkPacket(msg.data, [0xF8]);
|
||||
} else if (checkCount == 3) {
|
||||
MIDITestUtils.checkPacket(msg.data, [0xF0, 0x01, 0x02, 0x03, 0x04, 0x05, 0xF7]);
|
||||
SimpleTest.finish();
|
||||
|
|
114
dom/midi/tests/test_midi_send_messages.html
Normal file
114
dom/midi/tests/test_midi_send_messages.html
Normal file
|
@ -0,0 +1,114 @@
|
|||
<html>
|
||||
|
||||
<head>
|
||||
<title>WebMIDI Send Test</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
<script type="application/javascript" src="MIDITestUtils.js"></script>
|
||||
</head>
|
||||
|
||||
<body onload="runTests()">
|
||||
<script class="testbody" type="application/javascript">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
async function runTests() {
|
||||
await MIDITestUtils.permissionSetup(true);
|
||||
const access = await navigator.requestMIDIAccess({ sysex: true });
|
||||
const output = access.outputs.get(MIDITestUtils.stateTestOutputInfo.id);
|
||||
|
||||
dump("output = " + JSON.stringify(output, null, " ") + "\n");
|
||||
|
||||
// Note on(off).
|
||||
output.send([0xff, 0x90, 0x00, 0x00, 0x90, 0x07, 0x00]);
|
||||
|
||||
try {
|
||||
output.send([0x00, 0x01])
|
||||
} catch (ex) {
|
||||
dump("Caught exception");
|
||||
ok(true, "Caught exception");
|
||||
}
|
||||
|
||||
// Running status is not allowed in Web MIDI API.
|
||||
SimpleTest.doesThrow(() => output.send([0x00, 0x01]), "Running status is not allowed in Web MIDI API.");
|
||||
|
||||
// Unexpected End of Sysex.
|
||||
SimpleTest.doesThrow(() => output.send([0xf7]), "Unexpected End of Sysex.");
|
||||
|
||||
// Unexpected reserved status bytes.
|
||||
SimpleTest.doesThrow(() => output.send([0xf4]), "Unexpected reserved status byte 0xf4.");
|
||||
SimpleTest.doesThrow(() => output.send([0xf5]), "Unexpected reserved status byte 0xf5.");
|
||||
SimpleTest.doesThrow(() => output.send([0xf9]), "Unexpected reserved status byte 0xf9.");
|
||||
SimpleTest.doesThrow(() => output.send([0xfd]), "Unexpected reserved status byte 0xfd.");
|
||||
|
||||
// Incomplete channel messages.
|
||||
SimpleTest.doesThrow(() => output.send([0x80]), "Incomplete channel message.");
|
||||
SimpleTest.doesThrow(() => output.send([0x80, 0x00]), "Incomplete channel message.");
|
||||
SimpleTest.doesThrow(() => output.send([0x90]), "Incomplete channel message.");
|
||||
SimpleTest.doesThrow(() => output.send([0x90, 0x00]), "Incomplete channel message.");
|
||||
SimpleTest.doesThrow(() => output.send([0xa0]), "Incomplete channel message.");
|
||||
SimpleTest.doesThrow(() => output.send([0xa0, 0x00]), "Incomplete channel message.");
|
||||
SimpleTest.doesThrow(() => output.send([0xb0]), "Incomplete channel message.");
|
||||
SimpleTest.doesThrow(() => output.send([0xb0, 0x00]), "Incomplete channel message.");
|
||||
SimpleTest.doesThrow(() => output.send([0xc0]), "Incomplete channel message.");
|
||||
SimpleTest.doesThrow(() => output.send([0xd0]), "Incomplete channel message.");
|
||||
SimpleTest.doesThrow(() => output.send([0xe0]), "Incomplete channel message.");
|
||||
SimpleTest.doesThrow(() => output.send([0xe0, 0x00]), "Incomplete channel message.");
|
||||
|
||||
// Incomplete system messages.
|
||||
SimpleTest.doesThrow(() => output.send([0xf1]), "Incomplete system message.");
|
||||
SimpleTest.doesThrow(() => output.send([0xf2]), "Incomplete system message.");
|
||||
SimpleTest.doesThrow(() => output.send([0xf2, 0x00]), "Incomplete system message.");
|
||||
SimpleTest.doesThrow(() => output.send([0xf3]), "Incomplete system message.");
|
||||
|
||||
// Invalid data bytes.
|
||||
SimpleTest.doesThrow(() => output.send([0x80, 0x80, 0x00]), "Incomplete system message.");
|
||||
SimpleTest.doesThrow(() => output.send([0x80, 0x00, 0x80]), "Incomplete system message.");
|
||||
|
||||
// Complete messages.
|
||||
output.send([0x80, 0x00, 0x00]);
|
||||
output.send([0x90, 0x00, 0x00]);
|
||||
output.send([0xa0, 0x00, 0x00]);
|
||||
output.send([0xb0, 0x00, 0x00]);
|
||||
output.send([0xc0, 0x00]);
|
||||
output.send([0xd0, 0x00]);
|
||||
output.send([0xe0, 0x00, 0x00]);
|
||||
|
||||
// Real-Time messages.
|
||||
output.send([0xf8]);
|
||||
output.send([0xfa]);
|
||||
output.send([0xfb]);
|
||||
output.send([0xfc]);
|
||||
output.send([0xfe]);
|
||||
output.send([0xff]);
|
||||
|
||||
// Valid messages with Real-Time messages.
|
||||
output.send([0x90, 0xff, 0xff, 0x00, 0xff, 0x01, 0xff, 0x80, 0xff, 0x00,
|
||||
0xff, 0xff, 0x00, 0xff, 0xff]);
|
||||
|
||||
// Sysex messages.
|
||||
output.send([0xf0, 0x00, 0x01, 0x02, 0x03, 0xf7]);
|
||||
output.send([0xf0, 0xf8, 0xf7, 0xff]);
|
||||
SimpleTest.doesThrow(() => output.send([0xf0, 0x80, 0xf7]), "Invalid sysex message.");
|
||||
SimpleTest.doesThrow(() => output.send([0xf0, 0xf0, 0xf7]), "Double begin sysex message.");
|
||||
SimpleTest.doesThrow(() => output.send([0xf0, 0xff, 0xf7, 0xf7]), "Double end sysex message.");
|
||||
|
||||
// Reserved status bytes.
|
||||
SimpleTest.doesThrow(() => output.send([0xf4, 0x80, 0x00, 0x00]), "Reserved status byte.");
|
||||
SimpleTest.doesThrow(() => output.send([0x80, 0xf4, 0x00, 0x00]), "Reserved status byte.");
|
||||
SimpleTest.doesThrow(() => output.send([0x80, 0x00, 0xf4, 0x00]), "Reserved status byte.");
|
||||
SimpleTest.doesThrow(() => output.send([0x80, 0x00, 0x00, 0xf4]), "Reserved status byte.");
|
||||
SimpleTest.doesThrow(() => output.send([0xf0, 0xff, 0xf4, 0xf7]), "Reserved status byte.");
|
||||
|
||||
// Invalid timestamps.
|
||||
SimpleTest.doesThrow(() => output.send([], NaN), "NaN timestamp.");
|
||||
SimpleTest.doesThrow(() => output.send([], Infinity), "Infinity timestamp.");
|
||||
SimpleTest.doesThrow(() => output.send(new Uint8Array(), NaN), "NaN timestamp.");
|
||||
SimpleTest.doesThrow(() => output.send(new Uint8Array(), Infinity), "Infinity timestamp.");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1383,16 +1383,6 @@ bool nsContentSecurityUtils::ValidateScriptFilename(JSContext* cx,
|
|||
}
|
||||
#endif
|
||||
|
||||
// If we got here we are going to return false, so set the error context
|
||||
const char* utf8Filename;
|
||||
if (mozilla::IsUtf8(mozilla::MakeStringSpan(aFilename))) {
|
||||
utf8Filename = aFilename;
|
||||
} else {
|
||||
utf8Filename = "(invalid UTF-8 filename)";
|
||||
}
|
||||
JS_ReportErrorNumberUTF8(cx, js::GetErrorMessage, nullptr,
|
||||
JSMSG_UNSAFE_FILENAME, utf8Filename);
|
||||
|
||||
// Presently we are only enforcing restrictions for the script filename
|
||||
// on Nightly. On all channels we are reporting Telemetry. In the future we
|
||||
// will assert in debug builds and return false to prevent execution in
|
||||
|
|
|
@ -27,7 +27,16 @@ struct ValueWithSize : LinkedListElement<ValueWithSize> {
|
|||
double mSize = 0.0f;
|
||||
};
|
||||
|
||||
using QueueWithSizes = LinkedList<ValueWithSize>;
|
||||
// This type is a little tricky lifetime wise: Despite the fact that we're
|
||||
// talking about linked list of VaueWithSize, what is actually stored in the
|
||||
// list are dynamically allocated ValueWithSize*. As a result, these have to be
|
||||
// deleted. There are two ways this lifetime is managed:
|
||||
//
|
||||
// 1. In DequeueValue we pop the first element into a UniquePtr, so that it is
|
||||
// correctly cleaned up at destruction time.
|
||||
// 2. We use an AutoCleanLinkedList which will delete elements when destroyed
|
||||
// or `clear`ed.
|
||||
using QueueWithSizes = AutoCleanLinkedList<ValueWithSize>;
|
||||
|
||||
// https://streams.spec.whatwg.org/#is-non-negative-number
|
||||
inline bool IsNonNegativeNumber(double v) {
|
||||
|
@ -59,7 +68,8 @@ inline void EnqueueValueWithSize(QueueContainingClass aContainer,
|
|||
return;
|
||||
}
|
||||
|
||||
// Step 4.
|
||||
// Step 4. See the comment on QueueWithSizes for the lifetime reasoning
|
||||
// around this allocation.
|
||||
ValueWithSize* valueWithSize = new ValueWithSize(aValue, aSize);
|
||||
aContainer->Queue().insertBack(valueWithSize);
|
||||
// Step 5.
|
||||
|
|
|
@ -485,7 +485,7 @@ var interfaceNamesInGlobalScope = [
|
|||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{ name: "HTMLDetailsElement", insecureContext: true },
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{ name: "HTMLDialogElement", insecureContext: true, nightly: true },
|
||||
{ name: "HTMLDialogElement", insecureContext: true },
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{ name: "HTMLDirectoryElement", insecureContext: true },
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
|
|
|
@ -65,7 +65,6 @@
|
|||
#include "nsXPCOMPrivate.h"
|
||||
#include "OSFileConstants.h"
|
||||
#include "xpcpublic.h"
|
||||
#include "XPCPrefableContextOptions.h"
|
||||
#include "XPCSelfHostedShmem.h"
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
|
@ -132,9 +131,8 @@ static_assert(MAX_WORKERS_PER_DOMAIN >= 1,
|
|||
|
||||
// Prefixes for observing preference changes.
|
||||
#define PREF_JS_OPTIONS_PREFIX "javascript.options."
|
||||
#define PREF_WORKERS_OPTIONS_PREFIX PREF_WORKERS_PREFIX "options."
|
||||
#define PREF_MEM_OPTIONS_PREFIX "mem."
|
||||
#define PREF_GCZEAL "gcZeal"
|
||||
#define PREF_GCZEAL "gczeal"
|
||||
|
||||
static NS_DEFINE_CID(kStreamTransportServiceCID, NS_STREAMTRANSPORTSERVICE_CID);
|
||||
|
||||
|
@ -165,8 +163,6 @@ template <>
|
|||
struct PrefTraits<bool> {
|
||||
using PrefValueType = bool;
|
||||
|
||||
static const PrefValueType kDefaultValue = false;
|
||||
|
||||
static inline PrefValueType Get(const char* aPref) {
|
||||
AssertIsOnMainThread();
|
||||
return Preferences::GetBool(aPref);
|
||||
|
@ -194,9 +190,7 @@ struct PrefTraits<int32_t> {
|
|||
};
|
||||
|
||||
template <typename T>
|
||||
T GetWorkerPref(const nsACString& aPref,
|
||||
const T aDefault = PrefTraits<T>::kDefaultValue,
|
||||
bool* aPresent = nullptr) {
|
||||
T GetPref(const char* aFullPref, const T aDefault, bool* aPresent = nullptr) {
|
||||
AssertIsOnMainThread();
|
||||
|
||||
using PrefHelper = PrefTraits<T>;
|
||||
|
@ -204,22 +198,11 @@ T GetWorkerPref(const nsACString& aPref,
|
|||
T result;
|
||||
bool present = true;
|
||||
|
||||
nsAutoCString prefName;
|
||||
prefName.AssignLiteral(PREF_WORKERS_OPTIONS_PREFIX);
|
||||
prefName.Append(aPref);
|
||||
|
||||
if (PrefHelper::Exists(prefName.get())) {
|
||||
result = PrefHelper::Get(prefName.get());
|
||||
if (PrefHelper::Exists(aFullPref)) {
|
||||
result = PrefHelper::Get(aFullPref);
|
||||
} else {
|
||||
prefName.AssignLiteral(PREF_JS_OPTIONS_PREFIX);
|
||||
prefName.Append(aPref);
|
||||
|
||||
if (PrefHelper::Exists(prefName.get())) {
|
||||
result = PrefHelper::Get(prefName.get());
|
||||
} else {
|
||||
result = aDefault;
|
||||
present = false;
|
||||
}
|
||||
result = aDefault;
|
||||
present = false;
|
||||
}
|
||||
|
||||
if (aPresent) {
|
||||
|
@ -228,23 +211,6 @@ T GetWorkerPref(const nsACString& aPref,
|
|||
return result;
|
||||
}
|
||||
|
||||
// Optimized version for bool that receives already-concatenated pref names.
|
||||
//
|
||||
// Used by xpc::SetPrefableContextOptions.
|
||||
bool GetWorkerBoolPref(const char* jsPref, const char* workerPref) {
|
||||
using PrefHelper = PrefTraits<bool>;
|
||||
|
||||
if (PrefHelper::Exists(workerPref)) {
|
||||
return PrefHelper::Get(workerPref);
|
||||
}
|
||||
|
||||
if (PrefHelper::Exists(jsPref)) {
|
||||
return PrefHelper::Get(jsPref);
|
||||
}
|
||||
|
||||
return PrefHelper::kDefaultValue;
|
||||
}
|
||||
|
||||
void LoadContextOptions(const char* aPrefName, void* /* aClosure */) {
|
||||
AssertIsOnMainThread();
|
||||
|
||||
|
@ -260,22 +226,18 @@ void LoadContextOptions(const char* aPrefName, void* /* aClosure */) {
|
|||
// another callback that will handle this change.
|
||||
if (StringBeginsWith(
|
||||
prefName,
|
||||
nsLiteralCString(PREF_JS_OPTIONS_PREFIX PREF_MEM_OPTIONS_PREFIX)) ||
|
||||
StringBeginsWith(
|
||||
prefName, nsLiteralCString(
|
||||
PREF_WORKERS_OPTIONS_PREFIX PREF_MEM_OPTIONS_PREFIX))) {
|
||||
nsLiteralCString(PREF_JS_OPTIONS_PREFIX PREF_MEM_OPTIONS_PREFIX))) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
if (prefName.EqualsLiteral(PREF_JS_OPTIONS_PREFIX PREF_GCZEAL) ||
|
||||
prefName.EqualsLiteral(PREF_WORKERS_OPTIONS_PREFIX PREF_GCZEAL)) {
|
||||
if (prefName.EqualsLiteral(PREF_JS_OPTIONS_PREFIX PREF_GCZEAL)) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
JS::ContextOptions contextOptions;
|
||||
xpc::SetPrefableContextOptions(contextOptions, GetWorkerBoolPref);
|
||||
xpc::SetPrefableContextOptions(contextOptions);
|
||||
|
||||
nsCOMPtr<nsIXULRuntime> xr = do_GetService("@mozilla.org/xre/runtime;1");
|
||||
if (xr) {
|
||||
|
@ -303,12 +265,13 @@ void LoadGCZealOptions(const char* /* aPrefName */, void* /* aClosure */) {
|
|||
return;
|
||||
}
|
||||
|
||||
int32_t gczeal = GetWorkerPref<int32_t>(nsLiteralCString(PREF_GCZEAL), -1);
|
||||
int32_t gczeal = GetPref<int32_t>(PREF_JS_OPTIONS_PREFIX PREF_GCZEAL, -1);
|
||||
if (gczeal < 0) {
|
||||
gczeal = 0;
|
||||
}
|
||||
|
||||
int32_t frequency = GetWorkerPref<int32_t>("gcZeal.frequency"_ns, -1);
|
||||
int32_t frequency =
|
||||
GetPref<int32_t>(PREF_JS_OPTIONS_PREFIX PREF_GCZEAL ".frequency", -1);
|
||||
if (frequency < 0) {
|
||||
frequency = JS_DEFAULT_ZEAL_FREQ;
|
||||
}
|
||||
|
@ -322,12 +285,11 @@ void LoadGCZealOptions(const char* /* aPrefName */, void* /* aClosure */) {
|
|||
#endif
|
||||
|
||||
void UpdateCommonJSGCMemoryOption(RuntimeService* aRuntimeService,
|
||||
const nsACString& aPrefName,
|
||||
JSGCParamKey aKey) {
|
||||
const char* aPrefName, JSGCParamKey aKey) {
|
||||
AssertIsOnMainThread();
|
||||
NS_ASSERTION(!aPrefName.IsEmpty(), "Empty pref name!");
|
||||
NS_ASSERTION(aPrefName, "Null pref name!");
|
||||
|
||||
int32_t prefValue = GetWorkerPref(aPrefName, -1);
|
||||
int32_t prefValue = GetPref(aPrefName, -1);
|
||||
Maybe<uint32_t> value = (prefValue < 0 || prefValue >= 10000)
|
||||
? Nothing()
|
||||
: Some(uint32_t(prefValue));
|
||||
|
@ -360,30 +322,31 @@ void LoadJSGCMemoryOptions(const char* aPrefName, void* /* aClosure */) {
|
|||
return;
|
||||
}
|
||||
|
||||
constexpr auto jsPrefix = nsLiteralCString{PREF_JS_OPTIONS_PREFIX};
|
||||
constexpr auto workersPrefix = nsLiteralCString{PREF_WORKERS_OPTIONS_PREFIX};
|
||||
|
||||
constexpr auto memPrefix =
|
||||
nsLiteralCString{PREF_JS_OPTIONS_PREFIX PREF_MEM_OPTIONS_PREFIX};
|
||||
const nsDependentCString fullPrefName(aPrefName);
|
||||
|
||||
// Pull out the string that actually distinguishes the parameter we need to
|
||||
// change.
|
||||
nsDependentCSubstring memPrefName;
|
||||
if (StringBeginsWith(fullPrefName, jsPrefix)) {
|
||||
memPrefName.Rebind(fullPrefName, jsPrefix.Length());
|
||||
} else if (StringBeginsWith(fullPrefName, workersPrefix)) {
|
||||
memPrefName.Rebind(fullPrefName, workersPrefix.Length());
|
||||
if (StringBeginsWith(fullPrefName, memPrefix)) {
|
||||
memPrefName.Rebind(fullPrefName, memPrefix.Length());
|
||||
} else {
|
||||
NS_ERROR("Unknown pref name!");
|
||||
return;
|
||||
}
|
||||
|
||||
struct WorkerGCPref {
|
||||
nsLiteralCString name;
|
||||
nsLiteralCString memName;
|
||||
const char* fullName;
|
||||
JSGCParamKey key;
|
||||
};
|
||||
|
||||
#define PREF(suffix_, key_) \
|
||||
{ nsLiteralCString(PREF_MEM_OPTIONS_PREFIX suffix_), key_ }
|
||||
#define PREF(suffix_, key_) \
|
||||
{ \
|
||||
nsLiteralCString(PREF_MEM_OPTIONS_PREFIX suffix_), \
|
||||
PREF_JS_OPTIONS_PREFIX PREF_MEM_OPTIONS_PREFIX suffix_, key_ \
|
||||
}
|
||||
constexpr WorkerGCPref kWorkerPrefs[] = {
|
||||
PREF("max", JSGC_MAX_BYTES),
|
||||
PREF("gc_high_frequency_time_limit_ms", JSGC_HIGH_FREQUENCY_TIME_LIMIT),
|
||||
|
@ -413,12 +376,12 @@ void LoadJSGCMemoryOptions(const char* aPrefName, void* /* aClosure */) {
|
|||
|
||||
if (gRuntimeServiceDuringInit) {
|
||||
// During init, we want to update every pref in kWorkerPrefs.
|
||||
MOZ_ASSERT(memPrefName.EqualsLiteral(PREF_MEM_OPTIONS_PREFIX),
|
||||
MOZ_ASSERT(memPrefName.IsEmpty(),
|
||||
"Pref branch prefix only expected during init");
|
||||
} else {
|
||||
// Otherwise, find the single pref that changed.
|
||||
while (pref != end) {
|
||||
if (pref->name == memPrefName) {
|
||||
if (pref->memName == memPrefName) {
|
||||
end = pref + 1;
|
||||
break;
|
||||
}
|
||||
|
@ -437,7 +400,7 @@ void LoadJSGCMemoryOptions(const char* aPrefName, void* /* aClosure */) {
|
|||
while (pref != end) {
|
||||
switch (pref->key) {
|
||||
case JSGC_MAX_BYTES: {
|
||||
int32_t prefValue = GetWorkerPref(pref->name, -1);
|
||||
int32_t prefValue = GetPref(pref->fullName, -1);
|
||||
Maybe<uint32_t> value = (prefValue <= 0 || prefValue >= 0x1000)
|
||||
? Nothing()
|
||||
: Some(uint32_t(prefValue) * 1024 * 1024);
|
||||
|
@ -445,7 +408,7 @@ void LoadJSGCMemoryOptions(const char* aPrefName, void* /* aClosure */) {
|
|||
break;
|
||||
}
|
||||
case JSGC_SLICE_TIME_BUDGET_MS: {
|
||||
int32_t prefValue = GetWorkerPref(pref->name, -1);
|
||||
int32_t prefValue = GetPref(pref->fullName, -1);
|
||||
Maybe<uint32_t> value = (prefValue <= 0 || prefValue >= 100000)
|
||||
? Nothing()
|
||||
: Some(uint32_t(prefValue));
|
||||
|
@ -454,7 +417,7 @@ void LoadJSGCMemoryOptions(const char* aPrefName, void* /* aClosure */) {
|
|||
}
|
||||
case JSGC_COMPACTING_ENABLED: {
|
||||
bool present;
|
||||
bool prefValue = GetWorkerPref(pref->name, false, &present);
|
||||
bool prefValue = GetPref(pref->fullName, false, &present);
|
||||
Maybe<uint32_t> value = present ? Some(prefValue ? 1 : 0) : Nothing();
|
||||
UpdateOtherJSGCMemoryOption(rts, pref->key, value);
|
||||
break;
|
||||
|
@ -472,7 +435,7 @@ void LoadJSGCMemoryOptions(const char* aPrefName, void* /* aClosure */) {
|
|||
case JSGC_URGENT_THRESHOLD_MB:
|
||||
case JSGC_MIN_EMPTY_CHUNK_COUNT:
|
||||
case JSGC_MAX_EMPTY_CHUNK_COUNT:
|
||||
UpdateCommonJSGCMemoryOption(rts, pref->name, pref->key);
|
||||
UpdateCommonJSGCMemoryOption(rts, pref->fullName, pref->key);
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Unknown JSGCParamKey value");
|
||||
|
@ -1485,12 +1448,9 @@ nsresult RuntimeService::Init() {
|
|||
#define WORKER_PREF(name, callback) \
|
||||
NS_FAILED(Preferences::RegisterCallbackAndCall(callback, name))
|
||||
|
||||
if (NS_FAILED(Preferences::RegisterPrefixCallback(
|
||||
if (NS_FAILED(Preferences::RegisterPrefixCallbackAndCall(
|
||||
LoadJSGCMemoryOptions,
|
||||
PREF_JS_OPTIONS_PREFIX PREF_MEM_OPTIONS_PREFIX)) ||
|
||||
NS_FAILED(Preferences::RegisterPrefixCallbackAndCall(
|
||||
LoadJSGCMemoryOptions,
|
||||
PREF_WORKERS_OPTIONS_PREFIX PREF_MEM_OPTIONS_PREFIX)) ||
|
||||
#ifdef JS_GC_ZEAL
|
||||
NS_FAILED(Preferences::RegisterCallback(
|
||||
LoadGCZealOptions, PREF_JS_OPTIONS_PREFIX PREF_GCZEAL)) ||
|
||||
|
@ -1499,13 +1459,8 @@ nsresult RuntimeService::Init() {
|
|||
WORKER_PREF("general.appname.override", AppNameOverrideChanged) ||
|
||||
WORKER_PREF("general.appversion.override", AppVersionOverrideChanged) ||
|
||||
WORKER_PREF("general.platform.override", PlatformOverrideChanged) ||
|
||||
#ifdef JS_GC_ZEAL
|
||||
WORKER_PREF("dom.workers.options.gcZeal", LoadGCZealOptions) ||
|
||||
#endif
|
||||
NS_FAILED(Preferences::RegisterPrefixCallbackAndCall(
|
||||
LoadContextOptions, PREF_WORKERS_OPTIONS_PREFIX)) ||
|
||||
NS_FAILED(Preferences::RegisterPrefixCallback(LoadContextOptions,
|
||||
PREF_JS_OPTIONS_PREFIX))) {
|
||||
LoadContextOptions, PREF_JS_OPTIONS_PREFIX))) {
|
||||
NS_WARNING("Failed to register pref callbacks!");
|
||||
}
|
||||
|
||||
|
@ -1767,23 +1722,17 @@ void RuntimeService::Cleanup() {
|
|||
if (mObserved) {
|
||||
if (NS_FAILED(Preferences::UnregisterPrefixCallback(
|
||||
LoadContextOptions, PREF_JS_OPTIONS_PREFIX)) ||
|
||||
NS_FAILED(Preferences::UnregisterPrefixCallback(
|
||||
LoadContextOptions, PREF_WORKERS_OPTIONS_PREFIX)) ||
|
||||
WORKER_PREF("intl.accept_languages", PrefLanguagesChanged) ||
|
||||
WORKER_PREF("general.appname.override", AppNameOverrideChanged) ||
|
||||
WORKER_PREF("general.appversion.override", AppVersionOverrideChanged) ||
|
||||
WORKER_PREF("general.platform.override", PlatformOverrideChanged) ||
|
||||
#ifdef JS_GC_ZEAL
|
||||
WORKER_PREF("dom.workers.options.gcZeal", LoadGCZealOptions) ||
|
||||
NS_FAILED(Preferences::UnregisterCallback(
|
||||
LoadGCZealOptions, PREF_JS_OPTIONS_PREFIX PREF_GCZEAL)) ||
|
||||
#endif
|
||||
NS_FAILED(Preferences::UnregisterPrefixCallback(
|
||||
LoadJSGCMemoryOptions,
|
||||
PREF_JS_OPTIONS_PREFIX PREF_MEM_OPTIONS_PREFIX)) ||
|
||||
NS_FAILED(Preferences::UnregisterPrefixCallback(
|
||||
LoadJSGCMemoryOptions,
|
||||
PREF_WORKERS_OPTIONS_PREFIX PREF_MEM_OPTIONS_PREFIX))) {
|
||||
PREF_JS_OPTIONS_PREFIX PREF_MEM_OPTIONS_PREFIX))) {
|
||||
NS_WARNING("Failed to unregister pref callbacks!");
|
||||
}
|
||||
|
||||
|
|
|
@ -322,28 +322,9 @@ add_task(async function test() {
|
|||
|
||||
// ## Fission Isolation
|
||||
if (Services.appinfo.fissionAutostart) {
|
||||
const fissionUrl = "example.com";
|
||||
const fissionRemoteType = `webIsolated=https://example.com`;
|
||||
|
||||
await do_test_sw(fissionUrl, fissionRemoteType, "synthetic", null);
|
||||
await do_test_sw(fissionUrl, fissionRemoteType, "synthetic", fileBlob);
|
||||
|
||||
// ## ServiceWorker isolation via allow-list
|
||||
// ## ServiceWorker isolation
|
||||
const isolateUrl = "example.com";
|
||||
const isolateRemoteType = `webServiceWorker=https://` + isolateUrl;
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
[
|
||||
"browser.tabs.remote.serviceWorkerIsolationList",
|
||||
"https://" + isolateUrl,
|
||||
],
|
||||
[
|
||||
"browser.tabs.remote.separatePrivilegedMozillaWebContentProcess",
|
||||
false,
|
||||
],
|
||||
["browser.tabs.remote.separatedMozillaDomains", ""],
|
||||
],
|
||||
});
|
||||
await do_test_sw(isolateUrl, isolateRemoteType, "synthetic", null);
|
||||
await do_test_sw(isolateUrl, isolateRemoteType, "synthetic", fileBlob);
|
||||
}
|
||||
|
|
|
@ -319,6 +319,10 @@ class GetNextTokenCompleteEvent final : public nsIRunnable,
|
|||
nsCOMPtr<nsISupports> mContinuationState;
|
||||
};
|
||||
|
||||
inline nsISupports* ToSupports(GetNextTokenCompleteEvent* aEvent) {
|
||||
return static_cast<nsIRunnable*>(aEvent);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(GetNextTokenCompleteEvent, nsIRunnable, nsICancelable)
|
||||
|
||||
//
|
||||
|
@ -336,7 +340,7 @@ class GetNextTokenRunnable final : public mozilla::Runnable {
|
|||
const nsACString& challenge, bool isProxyAuth, const nsAString& domain,
|
||||
const nsAString& username, const nsAString& password,
|
||||
nsISupports* sessionState, nsISupports* continuationState,
|
||||
GetNextTokenCompleteEvent* aCompleteEvent)
|
||||
nsMainThreadPtrHandle<GetNextTokenCompleteEvent>& aCompleteEvent)
|
||||
: mozilla::Runnable("GetNextTokenRunnable"),
|
||||
mAuthChannel(authChannel),
|
||||
mChallenge(challenge),
|
||||
|
@ -413,7 +417,7 @@ class GetNextTokenRunnable final : public mozilla::Runnable {
|
|||
nsString mPassword;
|
||||
nsCOMPtr<nsISupports> mSessionState;
|
||||
nsCOMPtr<nsISupports> mContinuationState;
|
||||
RefPtr<GetNextTokenCompleteEvent> mCompleteEvent;
|
||||
nsMainThreadPtrHandle<GetNextTokenCompleteEvent> mCompleteEvent;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
@ -428,12 +432,13 @@ nsHttpNegotiateAuth::GenerateCredentialsAsync(
|
|||
NS_ENSURE_ARG(aCallback);
|
||||
NS_ENSURE_ARG_POINTER(aCancelable);
|
||||
|
||||
RefPtr<GetNextTokenCompleteEvent> cancelEvent =
|
||||
new GetNextTokenCompleteEvent(aCallback);
|
||||
|
||||
nsMainThreadPtrHandle<nsIHttpAuthenticableChannel> handle(
|
||||
new nsMainThreadPtrHolder<nsIHttpAuthenticableChannel>(
|
||||
"nsIHttpAuthenticableChannel", authChannel, false));
|
||||
nsMainThreadPtrHandle<GetNextTokenCompleteEvent> cancelEvent(
|
||||
new nsMainThreadPtrHolder<GetNextTokenCompleteEvent>(
|
||||
"GetNextTokenCompleteEvent", new GetNextTokenCompleteEvent(aCallback),
|
||||
false));
|
||||
nsCOMPtr<nsIRunnable> getNextTokenRunnable = new GetNextTokenRunnable(
|
||||
handle, challenge, isProxyAuth, domain, username, password, sessionState,
|
||||
continuationState, cancelEvent);
|
||||
|
@ -442,7 +447,8 @@ nsHttpNegotiateAuth::GenerateCredentialsAsync(
|
|||
getNextTokenRunnable, nsIEventTarget::DISPATCH_EVENT_MAY_BLOCK);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
cancelEvent.forget(aCancelable);
|
||||
RefPtr<GetNextTokenCompleteEvent> cancelable(cancelEvent.get());
|
||||
cancelable.forget(aCancelable);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,28 @@
|
|||
#include <ostream>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
std::ostream& operator<<(std::ostream& aOut, const Side& aSide) {
|
||||
#define Emit(x) \
|
||||
case x: \
|
||||
aOut << #x; \
|
||||
break
|
||||
|
||||
switch (aSide) {
|
||||
Emit(eSideTop);
|
||||
Emit(eSideBottom);
|
||||
Emit(eSideLeft);
|
||||
Emit(eSideRight);
|
||||
default:
|
||||
NS_ERROR("unknown side");
|
||||
aOut << int(aSide);
|
||||
break;
|
||||
}
|
||||
|
||||
#undef Emit
|
||||
return aOut;
|
||||
}
|
||||
|
||||
namespace gfx {
|
||||
|
||||
std::ostream& operator<<(std::ostream& aOut, const SurfaceFormat& aFormat) {
|
||||
|
|
|
@ -858,6 +858,8 @@ namespace mozilla {
|
|||
// Side constants for use in various places.
|
||||
enum Side : uint8_t { eSideTop, eSideRight, eSideBottom, eSideLeft };
|
||||
|
||||
std::ostream& operator<<(std::ostream&, const mozilla::Side&);
|
||||
|
||||
constexpr auto AllPhysicalSides() {
|
||||
return mozilla::MakeInclusiveEnumeratedRange(eSideTop, eSideLeft);
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue