Merge autoland to mozilla-central. a=merge

This commit is contained in:
Bogdan Tara 2019-08-28 12:39:23 +03:00
Родитель 3c01a01df9 451bc0629c
Коммит 786d0c66bc
117 изменённых файлов: 1976 добавлений и 551 удалений

6
Cargo.lock сгенерированный
Просмотреть файл

@ -385,7 +385,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cstr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "cstr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"dogear 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "dogear 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"moz_task 0.1.0", "moz_task 0.1.0",
@ -956,7 +956,7 @@ dependencies = [
[[package]] [[package]]
name = "dogear" name = "dogear"
version = "0.3.1" version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3947,7 +3947,7 @@ dependencies = [
"checksum devd-rs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d009f166c0d9e9f9909dc751630b3a6411ab7f85a153d32d01deb364ffe52a7" "checksum devd-rs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d009f166c0d9e9f9909dc751630b3a6411ab7f85a153d32d01deb364ffe52a7"
"checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" "checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c"
"checksum dirs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "88972de891f6118092b643d85a0b28e0678e0f948d7f879aa32f2d5aafe97d2a" "checksum dirs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "88972de891f6118092b643d85a0b28e0678e0f948d7f879aa32f2d5aafe97d2a"
"checksum dogear 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "251a15c9a597d70eb53cbb0c5473d8d8c6241aef615c092030ebab27fb5b26ef" "checksum dogear 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "57cd6ee785daa898686f3e2fb4a2b1ce490fcd6d69665c857d16fb61b48f4aae"
"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
"checksum dtoa-short 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "068d4026697c1a18f0b0bb8cfcad1b0c151b90d8edb9bf4c235ad68128920d1d" "checksum dtoa-short 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "068d4026697c1a18f0b0bb8cfcad1b0c151b90d8edb9bf4c235ad68128920d1d"
"checksum dwrote 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0bd1369e02db5e9b842a9b67bce8a2fcc043beafb2ae8a799dd482d46ea1ff0d" "checksum dwrote 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0bd1369e02db5e9b842a9b67bce8a2fcc043beafb2ae8a799dd482d46ea1ff0d"

Просмотреть файл

@ -112,6 +112,7 @@ support-files =
test_no_mcb_on_http_site_font2.html test_no_mcb_on_http_site_font2.html
test_no_mcb_on_http_site_font2.css test_no_mcb_on_http_site_font2.css
[browser_no_mcb_for_loopback.js] [browser_no_mcb_for_loopback.js]
skip-if = fission # Timeouts
tags = mcb tags = mcb
support-files = support-files =
../general/moz.png ../general/moz.png

Просмотреть файл

@ -3,8 +3,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
body { body {
--sidebar-width: 320px;
display: grid; display: grid;
grid-template-columns: 320px 1fr; grid-template-columns: var(--sidebar-width) 1fr;
grid-template-rows: 75px 1fr; grid-template-rows: 75px 1fr;
grid-template-areas: "header header" grid-template-areas: "header header"
"logins login"; "logins login";
@ -17,12 +18,13 @@ header {
align-items: center; align-items: center;
background-color: var(--in-content-box-background); background-color: var(--in-content-box-background);
border-bottom: 1px solid var(--in-content-box-border-color); border-bottom: 1px solid var(--in-content-box-border-color);
padding-inline: 60px 23px; padding-inline-end: 23px;
} }
login-filter { login-filter {
max-width: 30%; min-width: 320px;
margin: auto; max-width: 400px;
margin-inline: 40px auto;
flex-grow: 1; flex-grow: 1;
align-self: center; align-self: center;
} }
@ -52,8 +54,9 @@ login-item {
} }
#branding-logo { #branding-logo {
flex-basis: var(--sidebar-width);
flex-shrink: 0;
height: 32px; height: 32px;
margin-inline-end: 18px;
-moz-context-properties: fill; -moz-context-properties: fill;
fill: #20123a; fill: #20123a;
} }

Просмотреть файл

@ -22,6 +22,9 @@
.fxaccounts-avatar-button { .fxaccounts-avatar-button {
cursor: pointer; cursor: pointer;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
} }
.fxaccount-email { .fxaccount-email {

Просмотреть файл

@ -978,6 +978,12 @@ var Policies = {
}, },
}, },
OfferToSaveLoginsDefault: {
onBeforeUIStartup(manager, param) {
setDefaultPref("signon.rememberSignons", param);
},
},
OverrideFirstRunPage: { OverrideFirstRunPage: {
onProfileAfterChange(manager, param) { onProfileAfterChange(manager, param) {
let url = param ? param.href : ""; let url = param ? param.href : "";

Просмотреть файл

@ -497,6 +497,10 @@
"type": "boolean" "type": "boolean"
}, },
"OfferToSaveLoginsDefault": {
"type": "boolean"
},
"OverrideFirstRunPage": { "OverrideFirstRunPage": {
"type": "URLorEmpty" "type": "URLorEmpty"
}, },

Просмотреть файл

@ -456,6 +456,16 @@ const POLICIES_TESTS = [
"browser.newtabpage.activity-stream.feeds.section.topstories": false, "browser.newtabpage.activity-stream.feeds.section.topstories": false,
}, },
}, },
// POLICY: OfferToSaveLoginsDefault
{
policies: {
OfferToSaveLoginsDefault: false,
},
unlockedPrefs: {
"signon.rememberSignons": false,
},
},
]; ];
add_task(async function test_policy_simple_prefs() { add_task(async function test_policy_simple_prefs() {

Просмотреть файл

@ -205,7 +205,9 @@ class TabsUpdateFilterEventManager extends EventManager {
let register = (fire, filterProps) => { let register = (fire, filterProps) => {
let filter = { ...filterProps }; let filter = { ...filterProps };
if (filter.urls) { if (filter.urls) {
filter.urls = new MatchPatternSet(filter.urls); filter.urls = new MatchPatternSet(filter.urls, {
restrictSchemes: false,
});
} }
let needsModified = true; let needsModified = true;
if (filter.properties) { if (filter.properties) {
@ -944,7 +946,9 @@ this.tabs = class extends ExtensionAPI {
queryInfo = Object.assign({}, queryInfo); queryInfo = Object.assign({}, queryInfo);
if (queryInfo.url !== null) { if (queryInfo.url !== null) {
queryInfo.url = new MatchPatternSet([].concat(queryInfo.url)); queryInfo.url = new MatchPatternSet([].concat(queryInfo.url), {
restrictSchemes: false,
});
} }
if (queryInfo.title !== null) { if (queryInfo.title !== null) {
queryInfo.title = new MatchGlob(queryInfo.title); queryInfo.title = new MatchGlob(queryInfo.title);

Просмотреть файл

@ -164,6 +164,7 @@ skip-if = (verify && debug && (os == 'mac'))
[browser_ext_pageAction_simple.js] [browser_ext_pageAction_simple.js]
[browser_ext_pageAction_telemetry.js] [browser_ext_pageAction_telemetry.js]
[browser_ext_pageAction_title.js] [browser_ext_pageAction_title.js]
skip-if = fission # Timeouts Bug 1574926
[browser_ext_popup_api_injection.js] [browser_ext_popup_api_injection.js]
[browser_ext_popup_background.js] [browser_ext_popup_background.js]
[browser_ext_popup_corners.js] [browser_ext_popup_corners.js]

Просмотреть файл

@ -21,56 +21,38 @@ add_task(async function() {
permissions: ["tabs"], permissions: ["tabs"],
}, },
background: function() { async background() {
browser.tabs.query( let tabs = await browser.tabs.query({ lastFocusedWindow: true });
{ browser.test.assertEq(tabs.length, 3, "should have three tabs");
lastFocusedWindow: true,
},
function(tabs) {
browser.test.assertEq(tabs.length, 3, "should have three tabs");
tabs.sort((tab1, tab2) => tab1.index - tab2.index); tabs.sort((tab1, tab2) => tab1.index - tab2.index);
browser.test.assertEq(tabs[0].url, "about:blank", "first tab blank"); browser.test.assertEq(tabs[0].url, "about:blank", "first tab blank");
tabs.shift(); tabs.shift();
browser.test.assertTrue(tabs[0].active, "tab 0 active"); browser.test.assertTrue(tabs[0].active, "tab 0 active");
browser.test.assertFalse(tabs[1].active, "tab 1 inactive"); browser.test.assertFalse(tabs[1].active, "tab 1 inactive");
browser.test.assertFalse(tabs[0].pinned, "tab 0 unpinned"); browser.test.assertFalse(tabs[0].pinned, "tab 0 unpinned");
browser.test.assertFalse(tabs[1].pinned, "tab 1 unpinned"); browser.test.assertFalse(tabs[1].pinned, "tab 1 unpinned");
browser.test.assertEq( browser.test.assertEq(tabs[0].url, "about:robots", "tab 0 url correct");
tabs[0].url, browser.test.assertEq(tabs[1].url, "about:config", "tab 1 url correct");
"about:robots",
"tab 0 url correct"
);
browser.test.assertEq(
tabs[1].url,
"about:config",
"tab 1 url correct"
);
browser.test.assertEq( browser.test.assertEq(tabs[0].status, "complete", "tab 0 status correct");
tabs[0].status, browser.test.assertEq(tabs[1].status, "complete", "tab 1 status correct");
"complete",
"tab 0 status correct"
);
browser.test.assertEq(
tabs[1].status,
"complete",
"tab 1 status correct"
);
browser.test.assertEq( browser.test.assertEq(
tabs[0].title, tabs[0].title,
"Gort! Klaatu barada nikto!", "Gort! Klaatu barada nikto!",
"tab 0 title correct" "tab 0 title correct"
);
browser.test.notifyPass("tabs.query");
}
); );
tabs = await browser.tabs.query({ url: "about:blank" });
browser.test.assertEq(tabs.length, 1, "about:blank query finds one tab");
browser.test.assertEq(tabs[0].url, "about:blank", "with the correct url");
browser.test.notifyPass("tabs.query");
}, },
}); });

Просмотреть файл

@ -13,6 +13,7 @@ support-files =
[browser_block_mozAddonManager.js] [browser_block_mozAddonManager.js]
[browser_dynamical_window_rounding.js] [browser_dynamical_window_rounding.js]
[browser_navigator.js] [browser_navigator.js]
skip-if = fission # Timeouts
[browser_netInfo.js] [browser_netInfo.js]
[browser_performanceAPI.js] [browser_performanceAPI.js]
[browser_roundedWindow_dialogWindow.js] [browser_roundedWindow_dialogWindow.js]

Просмотреть файл

@ -72,6 +72,7 @@ support-files =
skip-if = (os == 'mac' && os_version == '10.14') # bug 1554807 skip-if = (os == 'mac' && os_version == '10.14') # bug 1554807
[browser_locationBarExternalLoad.js] [browser_locationBarExternalLoad.js]
[browser_moz_action_link.js] [browser_moz_action_link.js]
skip-if = fission # Timeouts
[browser_new_tab_urlbar_reset.js] [browser_new_tab_urlbar_reset.js]
[browser_openViewOnFocus.js] [browser_openViewOnFocus.js]
[browser_pasteAndGo.js] [browser_pasteAndGo.js]

Просмотреть файл

@ -41,7 +41,6 @@ ac_add_options --disable-jemalloc
ac_add_options --enable-proxy-bypass-protection ac_add_options --enable-proxy-bypass-protection
# These aren't supported on mingw at this time # These aren't supported on mingw at this time
ac_add_options --disable-maintenance-service
ac_add_options --disable-webrtc # Bug 1393901 ac_add_options --disable-webrtc # Bug 1393901
ac_add_options --disable-geckodriver # Bug 1489320 ac_add_options --disable-geckodriver # Bug 1489320

Просмотреть файл

@ -41,7 +41,6 @@ ac_add_options --disable-jemalloc
ac_add_options --enable-proxy-bypass-protection ac_add_options --enable-proxy-bypass-protection
# These aren't supported on mingw at this time # These aren't supported on mingw at this time
ac_add_options --disable-maintenance-service
ac_add_options --disable-webrtc # Bug 1393901 ac_add_options --disable-webrtc # Bug 1393901
ac_add_options --disable-geckodriver # Bug 1489320 ac_add_options --disable-geckodriver # Bug 1489320

Просмотреть файл

@ -115,6 +115,8 @@ policy-NoDefaultBookmarks = Disable creation of the default bookmarks bundled wi
policy-OfferToSaveLogins = Enforce the setting to allow { -brand-short-name } to offer to remember saved logins and passwords. Both true and false values are accepted. policy-OfferToSaveLogins = Enforce the setting to allow { -brand-short-name } to offer to remember saved logins and passwords. Both true and false values are accepted.
policy-OfferToSaveLoginsDefault = Set the default value for allowing { -brand-short-name } to offer to remember saved logins and passwords. Both true and false values are accepted.
policy-OverrideFirstRunPage = Override the first run page. Set this policy to blank if you want to disable the first run page. policy-OverrideFirstRunPage = Override the first run page. Set this policy to blank if you want to disable the first run page.
policy-OverridePostUpdatePage = Override the post-update “Whats New” page. Set this policy to blank if you want to disable the post-update page. policy-OverridePostUpdatePage = Override the post-update “Whats New” page. Set this policy to blank if you want to disable the post-update page.

Просмотреть файл

@ -274,10 +274,6 @@
%include ../shared/identity-block/identity-block.inc.css %include ../shared/identity-block/identity-block.inc.css
#wrapper-urlbar-container[place="palette"] {
max-width: 20em;
}
#pageAction-urlbar-shareURL, #pageAction-urlbar-shareURL,
#pageAction-panel-shareURL { #pageAction-panel-shareURL {
list-style-image: url("chrome://browser/skin/share.svg"); list-style-image: url("chrome://browser/skin/share.svg");

Просмотреть файл

@ -1699,14 +1699,13 @@ toolbarpaletteitem[place="menu-panel"] > .subviewbutton-nav::after {
border-bottom: 1px solid var(--panel-separator-color); border-bottom: 1px solid var(--panel-separator-color);
display: flex; display: flex;
flex: 1 auto; flex: 1 auto;
height: 40px; /* fixed item height to prevent flex sizing; height + 2*4px padding */
padding: 4px; padding: 4px;
} }
.panel-header > label { .panel-header > label {
flex: auto; flex: auto;
font-weight: 600; font-weight: 600;
margin: 0; margin: 4px 0;
text-align: center; text-align: center;
} }

Просмотреть файл

@ -574,10 +574,6 @@ menuitem.bookmark-item {
%include ../shared/autocomplete.inc.css %include ../shared/autocomplete.inc.css
%include ../shared/urlbar-autocomplete.inc.css %include ../shared/urlbar-autocomplete.inc.css
.urlbarView {
font-size: 1.15em;
}
#PopupAutoComplete > richlistbox > richlistitem[originaltype~="datalist-first"] { #PopupAutoComplete > richlistbox > richlistitem[originaltype~="datalist-first"] {
border-top: 1px solid ThreeDShadow; border-top: 1px solid ThreeDShadow;
} }

Просмотреть файл

@ -32,6 +32,7 @@ Important Concepts
sparse sparse
Support for projects building with GN <gn> Support for projects building with GN <gn>
telemetry telemetry
sccache-dist
test_certificates test_certificates
integrated development environment (IDE) integrated development environment (IDE)

117
build/docs/sccache-dist.rst Normal file
Просмотреть файл

@ -0,0 +1,117 @@
.. _sccache_dist:
==================================
Distributed sccache (sccache-dist)
==================================
`sccache <https://github.com/mozilla/sccache>`_ is a ccache-like tool written in
rust.
Distributed sccache (also referred to as sccache-dist) is being rolled out to
Mozilla offices as a replacement for icecc. The steps for setting up your
machine as an sccache-dist server as well as distributing your build to servers
in your office are detailed below.
In addition to improved security properties, distributed sccache offers
distribution and caching of rust compilation, so it should be an improvement
above and beyond what we see with icecc. Build servers run on linux and
distributing builds is currently supported from macOS and linux machines.
Distribution from Windows is supported in principle but hasn't seen sufficient
testing.
Steps for distributing a build as an sccache-dist client
========================================================
Start by following the instructions at https://github.com/mozilla/sccache/blob/master/docs/DistributedQuickstart.md#configure-a-client
to configure your sccache distributed client. Ignore the note about custom
toolchains if you're distributing compilation from linux.
sccache 0.2.10 or above is recommended, and the auth section of your config
must read::
[dist.auth]
type = "mozilla"
* The scheduler url to use is: ``https://sccache1.corpdmz.<OFFICE>.mozilla.com``,
where <OFFICE> is, for instance, sfo1. A complete list of office short names
to be used can be found `here <https://docs.google.com/spreadsheets/d/1alscUTcfFyu3L0vs_S_cGi9JxF4uPrfsmwJko9annWE/edit#gid=0>`_
* If you're compiling from a macOS client, there are a handful of additional
considerations detailed here:
https://github.com/mozilla/sccache/blob/master/docs/DistributedQuickstart.md#considerations-when-distributing-from-macos.
In particular, custom toolchains will need to be specified.
Run ``./mach bootstrap`` to download prebuilt toolchains and place them in
``~/.mozbuild/clang-dist-toolchain.tar.xz`` and
``~/.mozbuild/rustc-dist-toolchain.tar.xz``.
* Add the following to your mozconfig::
ac_add_options CCACHE=/path/to/sccache
* When attempting to get your client running, the output of ``sccache -s`` should
be consulted to confirm compilations are being distributed. To receive helpful
logging from the local daemon in case they aren't, run
``SCCACHE_NO_DAEMON=1 RUST_LOG=sccache=trace path/to/sccache --start-server``
in a terminal window separate from your build prior to building.
* Run ``./mach build -j<value>`` with an appropriately large ``<value>``.
``sccache --dist-status`` should provide the number of cores available to you
(or a message if you're not connected). In the future this will be integrated
with the build system to automatically select an appropriate value.
This should be enough to distribute your build and replace your use of icecc.
Bear in mind there may be a few speedbumps, and please ensure your version of
sccache is current before investigating further. Please see the common questions
section below and ask for help if anything is preventing you from using it over
email (dev-builds), on slack in #sccache, or in #build on irc.
Steps for setting up a server
=============================
Build servers must run linux and use bubblewrap 3.0+ for sandboxing of compile
processes. This requires a kernel 4.6 or greater, so Ubuntu 18+, RHEL 8, or
similar.
* Acquire a recent build of sccache. ``./mach bootstrap`` or
``./mach artifact toolchain --from-build linux64-sccache`` will provide this.
``cargo install`` may also be used, but ensure the version for the ``sccache``
and ``sccache-dist`` binaries you end up using is 0.2.10 or above.
Alternatively, the source is available at https://github.com/mozilla/sccache
and should be built with the ``dist-server`` feature selected if building from
there.
* Collect the IP of your builder and request assignment of a static IP in a bug
filed in
`NetOps :: Other <https://bugzilla.mozilla.org/enter_bug.cgi?product=Infrastructure%20%26%20Operations&component=NetOps%3A%20Office%20Other>`_
cc sccache-admins@mozilla.com on this bug.
* File a bug in
`Infrastructure :: Other <https://bugzilla.mozilla.org/enter_bug.cgi?product=Infrastructure+%26+Operations&component=Infrastructure%3A+Other>`_
asking for an sccache builder auth token to be generated for your builder.
The bug should include your name, office, where in the office the builder is
located (desk, closet, etc - so IT can physically find it if needed), the IP
address, and a secure method to reach you (gpg, keybase.io, etc). An auth
token will be generated and delivered to you.
* The instructions at https://github.com/mozilla/sccache/blob/master/docs/DistributedQuickstart.md#configure-a-build-server
should contain everything else required to configure and run the server.
Common questions/considerations
===============================
* My build is still slow: scache-dist can only do so much with parts of the
build that aren't able to be parallelized. To start debugging a slow build,
ensure the "Successful distributed compilations" line in the output of
``sccache -s`` dominates other counts. For a full build, at least a 2-3x
improvement should be observed.
* My build output is incomprehensible due to a flood of warnings: clang will
treat some warnings differently when its fed preprocessed code in a separate
invocation (preprocessing occurs locally with sccache-dist). See the
following note about disabling problematic warnings:
https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Using_Icecream#I_get_build_failures_due_to_-Werror_when_building_remotely_but_not_when_building_locally
* My build fails with a message about incompatible versions of rustc between
dependent crates: if you're using a custom toolchain check that the version
of rustc in your ``rustc-dist-toolchain.tar.xz`` is the same as the version
you're running locally.

Просмотреть файл

@ -26,7 +26,7 @@ export { breakOnNext } from "./breakOnNext";
export { mapFrames } from "./mapFrames"; export { mapFrames } from "./mapFrames";
export { pauseOnExceptions } from "./pauseOnExceptions"; export { pauseOnExceptions } from "./pauseOnExceptions";
export { selectFrame } from "./selectFrame"; export { selectFrame } from "./selectFrame";
export { toggleSkipPausing } from "./skipPausing"; export { toggleSkipPausing, setSkipPausing } from "./skipPausing";
export { toggleMapScopes } from "./mapScopes"; export { toggleMapScopes } from "./mapScopes";
export { setExpandedScope } from "./expandScopes"; export { setExpandedScope } from "./expandScopes";
export { generateInlinePreview } from "./inlinePreview"; export { generateInlinePreview } from "./inlinePreview";

Просмотреть файл

@ -18,3 +18,19 @@ export function toggleSkipPausing() {
dispatch({ type: "TOGGLE_SKIP_PAUSING", skipPausing }); dispatch({ type: "TOGGLE_SKIP_PAUSING", skipPausing });
}; };
} }
/**
* @memberof actions/pause
* @static
*/
export function setSkipPausing(skipPausing: boolean) {
return async ({ dispatch, client, getState, sourceMaps }: ThunkArgs) => {
const currentlySkipping = getSkipPausing(getState());
if (currentlySkipping === skipPausing) {
return;
}
await client.setSkipPausing(skipPausing);
dispatch({ type: "TOGGLE_SKIP_PAUSING", skipPausing });
};
}

Просмотреть файл

@ -30,6 +30,9 @@ jest.mock("../../utils/prefs", () => ({
pendingBreakpoints: {}, pendingBreakpoints: {},
}, },
clear: jest.fn(), clear: jest.fn(),
features: {
inlinePreview: true,
},
})); }));
import { import {

Просмотреть файл

@ -30,6 +30,10 @@ export type UIAction =
+type: "TOGGLE_FRAMEWORK_GROUPING", +type: "TOGGLE_FRAMEWORK_GROUPING",
+value: boolean, +value: boolean,
|} |}
| {|
+type: "TOGGLE_INLINE_PREVIEW",
+value: boolean,
|}
| {| | {|
+type: "SHOW_SOURCE", +type: "SHOW_SOURCE",
+source: Source, +source: Source,

Просмотреть файл

@ -77,6 +77,15 @@ export function toggleFrameworkGrouping(toggleValue: boolean) {
}; };
} }
export function toggleInlinePreview(toggleValue: boolean) {
return ({ dispatch, getState }: ThunkArgs) => {
dispatch({
type: "TOGGLE_INLINE_PREVIEW",
value: toggleValue,
});
};
}
export function showSource(cx: Context, sourceId: string) { export function showSource(cx: Context, sourceId: string) {
return ({ dispatch, getState }: ThunkArgs) => { return ({ dispatch, getState }: ThunkArgs) => {
const source = getSource(getState(), sourceId); const source = getSource(getState(), sourceId);

Просмотреть файл

@ -54,6 +54,7 @@ class InlinePreviews extends Component<Props> {
return ( return (
<InlinePreviewRow <InlinePreviewRow
editor={editor} editor={editor}
key={line}
line={lineNum} line={lineNum}
previews={previews[line]} previews={previews[line]}
numColumnBreakpoints={numColumnBreakpoints} numColumnBreakpoints={numColumnBreakpoints}

Просмотреть файл

@ -37,6 +37,7 @@ import {
getCurrentThread, getCurrentThread,
getThreadContext, getThreadContext,
getSkipPausing, getSkipPausing,
getInlinePreview,
} from "../../selectors"; } from "../../selectors";
// Redux actions // Redux actions
@ -103,6 +104,7 @@ export type Props = {
symbols: SymbolDeclarations, symbols: SymbolDeclarations,
isPaused: boolean, isPaused: boolean,
skipPausing: boolean, skipPausing: boolean,
inlinePreviewEnabled: boolean,
// Actions // Actions
openConditionalPanel: typeof actions.openConditionalPanel, openConditionalPanel: typeof actions.openConditionalPanel,
@ -584,6 +586,7 @@ class Editor extends PureComponent<Props, State> {
selectedSource, selectedSource,
conditionalPanelLocation, conditionalPanelLocation,
isPaused, isPaused,
inlinePreviewEnabled,
} = this.props; } = this.props;
const { editor, contextMenu } = this.state; const { editor, contextMenu } = this.state;
@ -611,7 +614,7 @@ class Editor extends PureComponent<Props, State> {
{features.columnBreakpoints ? ( {features.columnBreakpoints ? (
<ColumnBreakpoints editor={editor} /> <ColumnBreakpoints editor={editor} />
) : null} ) : null}
{isPaused && features.inlinePreview ? ( {isPaused && inlinePreviewEnabled ? (
<InlinePreviews editor={editor} selectedSource={selectedSource} /> <InlinePreviews editor={editor} selectedSource={selectedSource} />
) : null} ) : null}
</div> </div>
@ -665,6 +668,7 @@ const mapStateToProps = state => {
symbols: getSymbols(state, selectedSource), symbols: getSymbols(state, selectedSource),
isPaused: getIsPaused(state, getCurrentThread(state)), isPaused: getIsPaused(state, getCurrentThread(state)),
skipPausing: getSkipPausing(state), skipPausing: getSkipPausing(state),
inlinePreviewEnabled: getInlinePreview(state),
}; };
}; };

Просмотреть файл

@ -15,6 +15,7 @@ import {
} from "../../../utils/source"; } from "../../../utils/source";
import { downloadFile } from "../../../utils/utils"; import { downloadFile } from "../../../utils/utils";
import { features } from "../../../utils/prefs";
import { isFulfilled } from "../../../utils/async-value"; import { isFulfilled } from "../../../utils/async-value";
import actions from "../../../actions"; import actions from "../../../actions";
@ -159,6 +160,14 @@ const downloadFileItem = (
click: () => downloadFile(selectedContent, getFilename(selectedSource)), click: () => downloadFile(selectedContent, getFilename(selectedSource)),
}); });
const inlinePreviewItem = (editorActions: EditorItemActions) => ({
id: "node-menu-inline-preview",
label: features.inlinePreview
? L10N.getStr("inlinePreview.disable.label")
: L10N.getStr("inlinePreview.enable.label"),
click: () => editorActions.toggleInlinePreview(!features.inlinePreview),
});
export function editorMenuItems({ export function editorMenuItems({
cx, cx,
editorActions, editorActions,
@ -218,6 +227,8 @@ export function editorMenuItems({
); );
} }
items.push({ type: "separator" }, inlinePreviewItem(editorActions));
return items; return items;
} }
@ -229,6 +240,7 @@ export type EditorItemActions = {
jumpToMappedLocation: typeof actions.jumpToMappedLocation, jumpToMappedLocation: typeof actions.jumpToMappedLocation,
showSource: typeof actions.showSource, showSource: typeof actions.showSource,
toggleBlackBox: typeof actions.toggleBlackBox, toggleBlackBox: typeof actions.toggleBlackBox,
toggleInlinePreview: typeof actions.toggleInlinePreview,
}; };
export function editorItemActions(dispatch: Function) { export function editorItemActions(dispatch: Function) {
@ -241,6 +253,7 @@ export function editorItemActions(dispatch: Function) {
jumpToMappedLocation: actions.jumpToMappedLocation, jumpToMappedLocation: actions.jumpToMappedLocation,
showSource: actions.showSource, showSource: actions.showSource,
toggleBlackBox: actions.toggleBlackBox, toggleBlackBox: actions.toggleBlackBox,
toggleInlinePreview: actions.toggleInlinePreview,
}, },
dispatch dispatch
); );

Просмотреть файл

@ -31,6 +31,7 @@ type Props = {
unHighlightDomElement: typeof actions.unHighlightDomElement, unHighlightDomElement: typeof actions.unHighlightDomElement,
deleteBreakpoint: typeof deleteDOMMutationBreakpoint, deleteBreakpoint: typeof deleteDOMMutationBreakpoint,
toggleBreakpoint: typeof toggleDOMMutationBreakpointState, toggleBreakpoint: typeof toggleDOMMutationBreakpointState,
setSkipPausing: typeof actions.setSkipPausing,
}; };
const localizationTerms = { const localizationTerms = {
@ -40,12 +41,22 @@ const localizationTerms = {
}; };
class DOMMutationBreakpointsContents extends Component<Props> { class DOMMutationBreakpointsContents extends Component<Props> {
handleBreakpoint(breakpointId, shouldEnable) {
const { toggleBreakpoint, setSkipPausing } = this.props;
// The user has enabled a mutation breakpoint so we should no
// longer skip pausing
if (shouldEnable) {
setSkipPausing(false);
}
toggleBreakpoint(breakpointId, shouldEnable);
}
renderItem(breakpoint: DOMMutationBreakpoint) { renderItem(breakpoint: DOMMutationBreakpoint) {
const { const {
openElementInInspector, openElementInInspector,
highlightDomElement, highlightDomElement,
unHighlightDomElement, unHighlightDomElement,
toggleBreakpoint,
deleteBreakpoint, deleteBreakpoint,
} = this.props; } = this.props;
const { enabled, id: breakpointId, nodeFront, mutationType } = breakpoint; const { enabled, id: breakpointId, nodeFront, mutationType } = breakpoint;
@ -55,7 +66,7 @@ class DOMMutationBreakpointsContents extends Component<Props> {
<input <input
type="checkbox" type="checkbox"
checked={enabled} checked={enabled}
onChange={() => toggleBreakpoint(breakpointId, !enabled)} onChange={() => this.handleBreakpoint(breakpointId, !enabled)}
/> />
<div className="dom-mutation-info"> <div className="dom-mutation-info">
<div className="dom-mutation-label"> <div className="dom-mutation-label">
@ -123,6 +134,7 @@ class DomMutationBreakpoints extends Component<Props> {
openElementInInspector={this.props.openElementInInspector} openElementInInspector={this.props.openElementInInspector}
highlightDomElement={this.props.highlightDomElement} highlightDomElement={this.props.highlightDomElement}
unHighlightDomElement={this.props.unHighlightDomElement} unHighlightDomElement={this.props.unHighlightDomElement}
setSkipPausing={this.props.setSkipPausing}
/> />
); );
} }
@ -136,5 +148,6 @@ export default connect(
openElementInInspector: actions.openElementInInspectorCommand, openElementInInspector: actions.openElementInInspectorCommand,
highlightDomElement: actions.highlightDomElement, highlightDomElement: actions.highlightDomElement,
unHighlightDomElement: actions.unHighlightDomElement, unHighlightDomElement: actions.unHighlightDomElement,
setSkipPausing: actions.setSkipPausing,
} }
)(DomMutationBreakpoints); )(DomMutationBreakpoints);

Просмотреть файл

@ -343,6 +343,20 @@ function update(
}; };
} }
// Disable skipPausing if a breakpoint is enabled or added
case "SET_BREAKPOINT": {
return action.breakpoint.disabled
? state
: { ...state, skipPausing: false };
}
case "UPDATE_EVENT_LISTENERS":
case "REMOVE_BREAKPOINT":
case "SET_XHR_BREAKPOINT":
case "ENABLE_XHR_BREAKPOINT": {
return { ...state, skipPausing: false };
}
case "TOGGLE_SKIP_PAUSING": { case "TOGGLE_SKIP_PAUSING": {
const { skipPausing } = action; const { skipPausing } = action;
prefs.skipPausing = skipPausing; prefs.skipPausing = skipPausing;

Просмотреть файл

@ -9,7 +9,7 @@
* @module reducers/ui * @module reducers/ui
*/ */
import { prefs } from "../utils/prefs"; import { prefs, features } from "../utils/prefs";
import type { Source, Range, SourceLocation } from "../types"; import type { Source, Range, SourceLocation } from "../types";
@ -37,6 +37,7 @@ export type UIState = {
}, },
conditionalPanelLocation: null | SourceLocation, conditionalPanelLocation: null | SourceLocation,
isLogPoint: boolean, isLogPoint: boolean,
inlinePreviewEnabled: boolean,
}; };
export const createUIState = (): UIState => ({ export const createUIState = (): UIState => ({
@ -51,6 +52,7 @@ export const createUIState = (): UIState => ({
isLogPoint: false, isLogPoint: false,
orientation: "horizontal", orientation: "horizontal",
viewport: null, viewport: null,
inlinePreviewEnabled: features.inlinePreview,
}); });
function update(state: UIState = createUIState(), action: Action): UIState { function update(state: UIState = createUIState(), action: Action): UIState {
@ -64,6 +66,11 @@ function update(state: UIState = createUIState(), action: Action): UIState {
return { ...state, frameworkGroupingOn: action.value }; return { ...state, frameworkGroupingOn: action.value };
} }
case "TOGGLE_INLINE_PREVIEW": {
features.inlinePreview = action.value;
return { ...state, inlinePreviewEnabled: action.value };
}
case "SET_ORIENTATION": { case "SET_ORIENTATION": {
return { ...state, orientation: action.orientation }; return { ...state, orientation: action.orientation };
} }
@ -185,4 +192,8 @@ export function getViewport(state: OuterState) {
return state.ui.viewport; return state.ui.viewport;
} }
export function getInlinePreview(state: OuterState) {
return state.ui.inlinePreviewEnabled;
}
export default update; export default update;

Просмотреть файл

@ -7,6 +7,19 @@ function skipPausing(dbg) {
return waitForState(dbg, state => dbg.selectors.getSkipPausing()); return waitForState(dbg, state => dbg.selectors.getSkipPausing());
} }
function toggleBreakpoint(dbg, index) {
const breakpoints = findAllElements(dbg, "breakpointItems");
const bp = breakpoints[index];
const input = bp.querySelector("input");
input.click();
}
async function disableBreakpoint(dbg, index) {
const disabled = waitForDispatch(dbg, "SET_BREAKPOINT");
toggleBreakpoint(dbg, index);
await disabled;
}
/* /*
* Tests toggling the skip pausing button and * Tests toggling the skip pausing button and
* invoking functions without pausing. * invoking functions without pausing.
@ -25,4 +38,14 @@ add_task(async function() {
await reload(dbg, "simple3"); await reload(dbg, "simple3");
res = await invokeInTab("simple"); res = await invokeInTab("simple");
is(res, 3, "simple() successfully completed"); is(res, 3, "simple() successfully completed");
info("Adding a breakpoint disables skipPausing");
await addBreakpoint(dbg, "simple3", 3);
await waitForState(dbg, state => !state.skipPausing);
info("Enabling a breakpoint disables skipPausing");
await skipPausing(dbg);
await disableBreakpoint(dbg, 0);
await toggleBreakpoint(dbg, 0);
await waitForState(dbg, state => !state.skipPausing);
}); });

Просмотреть файл

@ -192,7 +192,7 @@ skip-if = fission && debug # Leaks windows.
[browser_inspector_search-04.js] [browser_inspector_search-04.js]
fail-if = fission fail-if = fission
[browser_inspector_search-05.js] [browser_inspector_search-05.js]
fail-if = fission skip-if = fission # Timeouts
[browser_inspector_search-06.js] [browser_inspector_search-06.js]
[browser_inspector_search-07.js] [browser_inspector_search-07.js]
[browser_inspector_search-08.js] [browser_inspector_search-08.js]

Просмотреть файл

@ -430,6 +430,14 @@ editor.jumpToMappedLocation1.accesskey=m
downloadFile.label=Download file downloadFile.label=Download file
downloadFile.accesskey=d downloadFile.accesskey=d
# LOCALIZATION NOTE (inlinePreview.enable.label): Context menu item
# for enabling the inline preview feature
inlinePreview.enable.label=Enable inline preview
# LOCALIZATION NOTE (inlinePreview.disable.label): Context menu item
# for disabling the inline preview feature
inlinePreview.disable.label=Disable inline preview
# LOCALIZATION NOTE (framework.disableGrouping): This is the text that appears in the # LOCALIZATION NOTE (framework.disableGrouping): This is the text that appears in the
# context menu to disable framework grouping. # context menu to disable framework grouping.
framework.disableGrouping=Disable framework grouping framework.disableGrouping=Disable framework grouping

Просмотреть файл

@ -83,4 +83,4 @@ pref("devtools.debugger.features.event-listeners-breakpoints", true);
pref("devtools.debugger.features.dom-mutation-breakpoints", true); pref("devtools.debugger.features.dom-mutation-breakpoints", true);
pref("devtools.debugger.features.log-points", true); pref("devtools.debugger.features.log-points", true);
pref("devtools.debugger.features.overlay-step-buttons", false); pref("devtools.debugger.features.overlay-step-buttons", false);
pref("devtools.debugger.features.inline-preview", false); pref("devtools.debugger.features.inline-preview", true);

Просмотреть файл

@ -79,7 +79,7 @@ support-files =
[browser_styleeditor_autocomplete-disabled.js] [browser_styleeditor_autocomplete-disabled.js]
[browser_styleeditor_bom.js] [browser_styleeditor_bom.js]
[browser_styleeditor_bug_740541_iframes.js] [browser_styleeditor_bug_740541_iframes.js]
fail-if = fission skip-if = fission # Timeouts
[browser_styleeditor_bug_851132_middle_click.js] [browser_styleeditor_bug_851132_middle_click.js]
[browser_styleeditor_bug_870339.js] [browser_styleeditor_bug_870339.js]
[browser_styleeditor_bug_1405342_serviceworker_iframes.js] [browser_styleeditor_bug_1405342_serviceworker_iframes.js]

Просмотреть файл

@ -18,6 +18,12 @@ loader.lazyRequireGetter(
"BrowserConsole", "BrowserConsole",
"devtools/client/webconsole/browser-console" "devtools/client/webconsole/browser-console"
); );
loader.lazyRequireGetter(
this,
"PREFS",
"devtools/client/webconsole/constants",
true
);
const BC_WINDOW_FEATURES = const BC_WINDOW_FEATURES =
"chrome,titlebar,toolbar,centerscreen,resizable,dialog=no"; "chrome,titlebar,toolbar,centerscreen,resizable,dialog=no";
@ -46,12 +52,11 @@ class BrowserConsoleManager {
* The target that the browser console will connect to. * The target that the browser console will connect to.
* @param nsIDOMWindow iframeWindow * @param nsIDOMWindow iframeWindow
* The window where the browser console UI is already loaded. * The window where the browser console UI is already loaded.
* @param Boolean fissionSupport
* @return object * @return object
* A promise object for the opening of the new BrowserConsole instance. * A promise object for the opening of the new BrowserConsole instance.
*/ */
async openBrowserConsole(target, win, fissionSupport = false) { async openBrowserConsole(target, win) {
const hud = new BrowserConsole(target, win, win, fissionSupport); const hud = new BrowserConsole(target, win, win);
this._browserConsole = hud; this._browserConsole = hud;
hud.once("destroyed", () => { hud.once("destroyed", () => {
this._browserConsole = null; this._browserConsole = null;
@ -73,11 +78,6 @@ class BrowserConsoleManager {
return this._browserConsoleInitializing; return this._browserConsoleInitializing;
} }
const fissionSupport = Services.prefs.getBoolPref(
"devtools.browsertoolbox.fission",
false
);
async function connect() { async function connect() {
// The Browser console ends up using the debugger in autocomplete. // The Browser console ends up using the debugger in autocomplete.
// Because the debugger can't be running in the same compartment than its debuggee, // Because the debugger can't be running in the same compartment than its debuggee,
@ -124,6 +124,9 @@ class BrowserConsoleManager {
win.addEventListener("DOMContentLoaded", resolve, { once: true }); win.addEventListener("DOMContentLoaded", resolve, { once: true });
}); });
const fissionSupport = Services.prefs.getBoolPref(
PREFS.FEATURES.BROWSER_TOOLBOX_FISSION
);
const title = fissionSupport const title = fissionSupport
? `💥 Fission Browser Console 💥` ? `💥 Fission Browser Console 💥`
: l10n.getStr("browserConsole.title"); : l10n.getStr("browserConsole.title");
@ -137,11 +140,7 @@ class BrowserConsoleManager {
const target = await connect(); const target = await connect();
await target.attach(); await target.attach();
const win = await openWindow(target); const win = await openWindow(target);
const browserConsole = await this.openBrowserConsole( const browserConsole = await this.openBrowserConsole(target, win);
target,
win,
fissionSupport
);
return browserConsole; return browserConsole;
})(); })();

Просмотреть файл

@ -35,10 +35,9 @@ class BrowserConsole extends WebConsole {
* The window where the browser console UI is already loaded. * The window where the browser console UI is already loaded.
* @param nsIDOMWindow chromeWindow * @param nsIDOMWindow chromeWindow
* The window of the browser console owner. * The window of the browser console owner.
* @param Boolean fissionSupport
*/ */
constructor(target, iframeWindow, chromeWindow, fissionSupport = false) { constructor(target, iframeWindow, chromeWindow) {
super(null, iframeWindow, chromeWindow, true, fissionSupport); super(null, iframeWindow, chromeWindow, true);
this._browserConsoleTarget = target; this._browserConsoleTarget = target;
this._telemetry = new Telemetry(); this._telemetry = new Telemetry();

Просмотреть файл

@ -83,6 +83,7 @@ const prefs = {
AUTOCOMPLETE: "devtools.webconsole.input.autocomplete", AUTOCOMPLETE: "devtools.webconsole.input.autocomplete",
GROUP_WARNINGS: "devtools.webconsole.groupWarningMessages", GROUP_WARNINGS: "devtools.webconsole.groupWarningMessages",
EDITOR: "devtools.webconsole.features.editor", EDITOR: "devtools.webconsole.features.editor",
BROWSER_TOOLBOX_FISSION: "devtools.browsertoolbox.fission",
}, },
}, },
}; };

Просмотреть файл

@ -12,6 +12,10 @@ const TEST_URI =
"test/browser/test-eval-in-stackframe.html"; "test/browser/test-eval-in-stackframe.html";
add_task(async function() { add_task(async function() {
// TODO: Remove this pref change when middleware for terminating requests
// when closing a panel is implemented
await pushPref("devtools.debugger.features.inline-preview", false);
info("open the console"); info("open the console");
const hud = await openNewTabAndConsole(TEST_URI); const hud = await openNewTabAndConsole(TEST_URI);

Просмотреть файл

@ -12,6 +12,10 @@ const TEST_URI =
"test/browser/test-eval-in-stackframe.html"; "test/browser/test-eval-in-stackframe.html";
add_task(async function() { add_task(async function() {
// TODO: Remove this pref change when middleware for terminating requests
// when closing a panel is implemented
await pushPref("devtools.debugger.features.inline-preview", false);
info("open the console"); info("open the console");
const hud = await openNewTabAndConsole(TEST_URI); const hud = await openNewTabAndConsole(TEST_URI);

Просмотреть файл

@ -11,6 +11,10 @@ const TEST_URI =
"test/browser/test-eval-in-stackframe.html"; "test/browser/test-eval-in-stackframe.html";
add_task(async function() { add_task(async function() {
// TODO: Remove this pref change when middleware for terminating requests
// when closing a panel is implemented
await pushPref("devtools.debugger.features.inline-preview", false);
const hud = await openNewTabAndConsole(TEST_URI); const hud = await openNewTabAndConsole(TEST_URI);
info("Switch to the debugger"); info("Switch to the debugger");

Просмотреть файл

@ -20,13 +20,20 @@ class WebConsoleConnectionProxy {
* @constructor * @constructor
* @param {WebConsoleUI} webConsoleUI * @param {WebConsoleUI} webConsoleUI
* A WebConsoleUI instance that owns this connection proxy. * A WebConsoleUI instance that owns this connection proxy.
* @param RemoteTarget target * @param {RemoteTarget} target
* The target that the console will connect to. * The target that the console will connect to.
* @param {Boolean} needContentProcessMessagesListener
* Set to true to specifically add a ContentProcessMessages listener. This is
* needed for non-fission Browser Console for example.
*/ */
constructor(webConsoleUI, target) { constructor(
webConsoleUI,
target,
needContentProcessMessagesListener = false
) {
this.webConsoleUI = webConsoleUI; this.webConsoleUI = webConsoleUI;
this.target = target; this.target = target;
this.fissionSupport = this.webConsoleUI.fissionSupport; this.needContentProcessMessagesListener = needContentProcessMessagesListener;
this._connecter = null; this._connecter = null;
@ -116,7 +123,7 @@ class WebConsoleConnectionProxy {
// when we open the Browser Console or Toolbox without fission support. If Fission // when we open the Browser Console or Toolbox without fission support. If Fission
// is enabled, we don't use the ContentProcessMessages listener, but attach to the // is enabled, we don't use the ContentProcessMessages listener, but attach to the
// content processes directly. // content processes directly.
if (this.target.chrome && !this.target.isAddon && !this.fissionSupport) { if (this.needContentProcessMessagesListener) {
listeners.push("ContentProcessMessages"); listeners.push("ContentProcessMessages");
} }
return this.webConsoleClient.startListeners(listeners); return this.webConsoleClient.startListeners(listeners);

Просмотреть файл

@ -24,6 +24,12 @@ loader.lazyRequireGetter(
"resource://gre/modules/AppConstants.jsm", "resource://gre/modules/AppConstants.jsm",
true true
); );
loader.lazyRequireGetter(
this,
"PREFS",
"devtools/client/webconsole/constants",
true
);
const ZoomKeys = require("devtools/client/shared/zoom-keys"); const ZoomKeys = require("devtools/client/shared/zoom-keys");
@ -45,7 +51,6 @@ class WebConsoleUI {
this.hud = hud; this.hud = hud;
this.hudId = this.hud.hudId; this.hudId = this.hud.hudId;
this.isBrowserConsole = this.hud.isBrowserConsole; this.isBrowserConsole = this.hud.isBrowserConsole;
this.fissionSupport = this.hud.fissionSupport;
this.window = this.hud.iframeWindow; this.window = this.hud.iframeWindow;
this._onPanelSelected = this._onPanelSelected.bind(this); this._onPanelSelected = this._onPanelSelected.bind(this);
@ -257,10 +262,20 @@ class WebConsoleUI {
* A promise object that is resolved/reject based on the proxies connections. * A promise object that is resolved/reject based on the proxies connections.
*/ */
async _initConnection() { async _initConnection() {
this.proxy = new WebConsoleConnectionProxy(this, this.hud.currentTarget);
const target = this.hud.currentTarget; const target = this.hud.currentTarget;
if (this.fissionSupport && target.chrome && !target.isAddon) { const fissionSupport = Services.prefs.getBoolPref(
PREFS.FEATURES.BROWSER_TOOLBOX_FISSION
);
const needContentProcessMessagesListener =
target.isParentProcess && !target.isAddon && !fissionSupport;
this.proxy = new WebConsoleConnectionProxy(
this,
target,
needContentProcessMessagesListener
);
if (fissionSupport && target.isParentProcess && !target.isAddon) {
const { mainRoot } = target.client; const { mainRoot } = target.client;
const { processes } = await mainRoot.listProcesses(); const { processes } = await mainRoot.listProcesses();

Просмотреть файл

@ -59,20 +59,13 @@ class WebConsole {
* The window of the web console owner. * The window of the web console owner.
* @param bool isBrowserConsole * @param bool isBrowserConsole
*/ */
constructor( constructor(toolbox, iframeWindow, chromeWindow, isBrowserConsole = false) {
toolbox,
iframeWindow,
chromeWindow,
isBrowserConsole = false,
fissionSupport = false
) {
this.toolbox = toolbox; this.toolbox = toolbox;
this.iframeWindow = iframeWindow; this.iframeWindow = iframeWindow;
this.chromeWindow = chromeWindow; this.chromeWindow = chromeWindow;
this.hudId = "hud_" + ++gHudId; this.hudId = "hud_" + ++gHudId;
this.browserWindow = this.chromeWindow.top; this.browserWindow = this.chromeWindow.top;
this.isBrowserConsole = isBrowserConsole; this.isBrowserConsole = isBrowserConsole;
this.fissionSupport = fissionSupport;
const element = this.browserWindow.document.documentElement; const element = this.browserWindow.document.documentElement;
if (element.getAttribute("windowtype") != gDevTools.chromeWindowType) { if (element.getAttribute("windowtype") != gDevTools.chromeWindowType) {

Просмотреть файл

@ -21,9 +21,6 @@ const CONTENT_PROCESS_SERVER_STARTUP_SCRIPT =
loader.lazyRequireGetter(this, "EventEmitter", "devtools/shared/event-emitter"); loader.lazyRequireGetter(this, "EventEmitter", "devtools/shared/event-emitter");
const ContentProcessConnector = { const ContentProcessConnector = {
// Flag to check if the content process server startup script was already loaded.
_contentProcessServerStartupScriptLoaded: false,
/** /**
* Start a DevTools server in a content process (representing the entire process, not * Start a DevTools server in a content process (representing the entire process, not
* just a single frame) and add it as a child server for an active connection. * just a single frame) and add it as a child server for an active connection.
@ -36,8 +33,6 @@ const ContentProcessConnector = {
mm.addMessageListener("debug:content-process-actor", function listener( mm.addMessageListener("debug:content-process-actor", function listener(
msg msg
) { ) {
// Arbitrarily choose the first content process to reply
// XXX: This code needs to be updated if we use more than one content process
mm.removeMessageListener("debug:content-process-actor", listener); mm.removeMessageListener("debug:content-process-actor", listener);
// Pipe Debugger message from/to parent/child via the message manager // Pipe Debugger message from/to parent/child via the message manager
@ -58,13 +53,15 @@ const ContentProcessConnector = {
}); });
// Load the content process server startup script only once. // Load the content process server startup script only once.
if (!this._contentProcessServerStartupScriptLoaded) { const isContentProcessServerStartupScripLoaded = Services.ppmm
.getDelayedProcessScripts()
.some(([uri]) => uri === CONTENT_PROCESS_SERVER_STARTUP_SCRIPT);
if (!isContentProcessServerStartupScripLoaded) {
// Load the process script that will receive the debug:init-content-server message // Load the process script that will receive the debug:init-content-server message
Services.ppmm.loadProcessScript( Services.ppmm.loadProcessScript(
CONTENT_PROCESS_SERVER_STARTUP_SCRIPT, CONTENT_PROCESS_SERVER_STARTUP_SCRIPT,
true true
); );
this._contentProcessServerStartupScriptLoaded = true;
} }
// Send a message to the content process server startup script to forward it the // Send a message to the content process server startup script to forward it the

Просмотреть файл

@ -144,7 +144,7 @@ skip-if = e10s # Bug 1183605 - devtools/server/tests/browser/ tests are still di
[browser_storage_browser_toolbox_indexeddb.js] [browser_storage_browser_toolbox_indexeddb.js]
[browser_storage_cookies-duplicate-names.js] [browser_storage_cookies-duplicate-names.js]
[browser_storage_dynamic_windows.js] [browser_storage_dynamic_windows.js]
fail-if = fission skip-if = fission # Timeouts
[browser_storage_listings.js] [browser_storage_listings.js]
fail-if = fission fail-if = fission
[browser_storage_updates.js] [browser_storage_updates.js]

Просмотреть файл

@ -489,6 +489,11 @@ nsresult CharacterData::BindToTree(BindContext& aContext, nsINode& aParent) {
UpdateEditableState(false); UpdateEditableState(false);
// Ensure we only do these once, in the case we move the shadow host around.
if (aContext.SubtreeRootChanges()) {
HandleShadowDOMRelatedInsertionSteps(hadParent);
}
MOZ_ASSERT(OwnerDoc() == aParent.OwnerDoc(), "Bound to wrong document"); MOZ_ASSERT(OwnerDoc() == aParent.OwnerDoc(), "Bound to wrong document");
MOZ_ASSERT(IsInComposedDoc() == aContext.InComposedDoc()); MOZ_ASSERT(IsInComposedDoc() == aContext.InComposedDoc());
MOZ_ASSERT(IsInUncomposedDoc() == aContext.InUncomposedDoc()); MOZ_ASSERT(IsInUncomposedDoc() == aContext.InUncomposedDoc());
@ -506,6 +511,8 @@ void CharacterData::UnbindFromTree(bool aNullParent) {
// Unset frame flags; if we need them again later, they'll get set again. // Unset frame flags; if we need them again later, they'll get set again.
UnsetFlags(NS_CREATE_FRAME_IF_NON_WHITESPACE | NS_REFRAME_IF_WHITESPACE); UnsetFlags(NS_CREATE_FRAME_IF_NON_WHITESPACE | NS_REFRAME_IF_WHITESPACE);
HandleShadowDOMRelatedRemovalSteps(aNullParent);
Document* document = GetComposedDoc(); Document* document = GetComposedDoc();
if (aNullParent) { if (aNullParent) {

Просмотреть файл

@ -1721,6 +1721,7 @@ nsresult Element::BindToTree(BindContext& aContext, nsINode& aParent) {
if (HasID()) { if (HasID()) {
AddToIdTable(DoGetID()); AddToIdTable(DoGetID());
} }
HandleShadowDOMRelatedInsertionSteps(hadParent);
} }
if (MayHaveStyle() && !IsXULElement()) { if (MayHaveStyle() && !IsXULElement()) {
@ -1801,6 +1802,8 @@ bool WillDetachFromShadowOnUnbind(const Element& aElement, bool aNullParent) {
} }
void Element::UnbindFromTree(bool aNullParent) { void Element::UnbindFromTree(bool aNullParent) {
HandleShadowDOMRelatedRemovalSteps(aNullParent);
const bool detachingFromShadow = const bool detachingFromShadow =
WillDetachFromShadowOnUnbind(*this, aNullParent); WillDetachFromShadowOnUnbind(*this, aNullParent);
// Make sure to only remove from the ID table if our subtree root is actually // Make sure to only remove from the ID table if our subtree root is actually
@ -1922,7 +1925,6 @@ void Element::UnbindFromTree(bool aNullParent) {
#ifdef MOZ_XUL #ifdef MOZ_XUL
if (nsXULElement* xulElem = nsXULElement::FromNode(this)) { if (nsXULElement* xulElem = nsXULElement::FromNode(this)) {
;
xulElem->SetXULBindingParent(nullptr); xulElem->SetXULBindingParent(nullptr);
clearBindingParent = false; clearBindingParent = false;
} }
@ -2629,19 +2631,25 @@ nsresult Element::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
const nsAttrValue* aOldValue, const nsAttrValue* aOldValue,
nsIPrincipal* aMaybeScriptedPrincipal, nsIPrincipal* aMaybeScriptedPrincipal,
bool aNotify) { bool aNotify) {
if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::part) { if (aNamespaceID == kNameSpaceID_None) {
bool isPart = !!aValue; if (aName == nsGkAtoms::part) {
if (HasPartAttribute() != isPart) { bool isPart = !!aValue;
SetHasPartAttribute(isPart); if (HasPartAttribute() != isPart) {
if (ShadowRoot* shadow = GetContainingShadow()) { SetHasPartAttribute(isPart);
if (isPart) { if (ShadowRoot* shadow = GetContainingShadow()) {
shadow->PartAdded(*this); if (isPart) {
} else { shadow->PartAdded(*this);
shadow->PartRemoved(*this); } else {
shadow->PartRemoved(*this);
}
} }
} }
MOZ_ASSERT(HasPartAttribute() == isPart);
} else if (aName == nsGkAtoms::slot && GetParent()) {
if (ShadowRoot* shadow = GetParent()->GetShadowRoot()) {
shadow->MaybeReassignElement(*this);
}
} }
MOZ_ASSERT(HasPartAttribute() == isPart);
} }
return NS_OK; return NS_OK;
} }

Просмотреть файл

@ -1118,7 +1118,7 @@ void nsIContent::AssertAnonymousSubtreeRelatedInvariants() const {
(GetParent() && GetBindingParent() == GetParent()), (GetParent() && GetBindingParent() == GetParent()),
"root of native anonymous subtree must have parent equal " "root of native anonymous subtree must have parent equal "
"to binding parent"); "to binding parent");
NS_ASSERTION(!GetParent() || NS_ASSERTION(!GetParent() || !IsInComposedDoc() ||
((GetBindingParent() == GetParent()) == ((GetBindingParent() == GetParent()) ==
HasFlag(NODE_IS_ANONYMOUS_ROOT)) || HasFlag(NODE_IS_ANONYMOUS_ROOT)) ||
// Unfortunately default content for XBL insertion points // Unfortunately default content for XBL insertion points
@ -1129,7 +1129,7 @@ void nsIContent::AssertAnonymousSubtreeRelatedInvariants() const {
(GetBindingParent() && (GetBindingParent() &&
(GetBindingParent() == GetParent()->GetBindingParent()) == (GetBindingParent() == GetParent()->GetBindingParent()) ==
HasFlag(NODE_IS_ANONYMOUS_ROOT)), HasFlag(NODE_IS_ANONYMOUS_ROOT)),
"For nodes with parent, flag and GetBindingParent() check " "For connected nodes, flag and GetBindingParent() check "
"should match"); "should match");
} }
#endif #endif

Просмотреть файл

@ -36,15 +36,11 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ShadowRoot, DocumentFragment)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ShadowRoot) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ShadowRoot)
if (tmp->GetHost()) {
tmp->GetHost()->RemoveMutationObserver(tmp);
}
DocumentOrShadowRoot::Unlink(tmp); DocumentOrShadowRoot::Unlink(tmp);
NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED(DocumentFragment) NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED(DocumentFragment)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ShadowRoot) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ShadowRoot)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContent) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContent)
NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
NS_INTERFACE_MAP_ENTRY(nsIRadioGroupContainer) NS_INTERFACE_MAP_ENTRY(nsIRadioGroupContainer)
NS_INTERFACE_MAP_END_INHERITING(DocumentFragment) NS_INTERFACE_MAP_END_INHERITING(DocumentFragment)
@ -69,19 +65,9 @@ ShadowRoot::ShadowRoot(Element* aElement, ShadowRootMode aMode,
ExtendedDOMSlots()->mBindingParent = aElement; ExtendedDOMSlots()->mBindingParent = aElement;
ExtendedDOMSlots()->mContainingShadow = this; ExtendedDOMSlots()->mContainingShadow = this;
// Add the ShadowRoot as a mutation observer on the host to watch
// for mutations because the insertion points in this ShadowRoot
// may need to be updated when the host children are modified.
GetHost()->AddMutationObserver(this);
} }
ShadowRoot::~ShadowRoot() { ShadowRoot::~ShadowRoot() {
if (auto* host = GetHost()) {
// mHost may have been unlinked.
host->RemoveMutationObserver(this);
}
if (IsInComposedDoc()) { if (IsInComposedDoc()) {
OwnerDoc()->RemoveComposedDocShadowRoot(*this); OwnerDoc()->RemoveComposedDocShadowRoot(*this);
} }
@ -158,13 +144,11 @@ void ShadowRoot::Unattach() {
MOZ_ASSERT(!HasSlots(), "Won't work!"); MOZ_ASSERT(!HasSlots(), "Won't work!");
if (!GetHost()) { if (!GetHost()) {
// It is possible that we've been unlinked already. In such case host // It is possible that we've been unlinked already. In such case host
// should have called Unbind and ShadowRoot's own unlink // should have called Unbind and ShadowRoot's own unlink.
// RemoveMutationObserver.
return; return;
} }
Unbind(); Unbind();
GetHost()->RemoveMutationObserver(this);
SetHost(nullptr); SetHost(nullptr);
} }
@ -220,8 +204,8 @@ void ShadowRoot::AddSlot(HTMLSlotElement* aSlot) {
while (assignedNodes.Length() > 0) { while (assignedNodes.Length() > 0) {
nsINode* assignedNode = assignedNodes[0]; nsINode* assignedNode = assignedNodes[0];
oldSlot->RemoveAssignedNode(assignedNode); oldSlot->RemoveAssignedNode(*assignedNode->AsContent());
aSlot->AppendAssignedNode(assignedNode); aSlot->AppendAssignedNode(*assignedNode->AsContent());
doEnqueueSlotChange = true; doEnqueueSlotChange = true;
} }
@ -245,7 +229,7 @@ void ShadowRoot::AddSlot(HTMLSlotElement* aSlot) {
continue; continue;
} }
doEnqueueSlotChange = true; doEnqueueSlotChange = true;
aSlot->AppendAssignedNode(child); aSlot->AppendAssignedNode(*child);
} }
if (doEnqueueSlotChange) { if (doEnqueueSlotChange) {
@ -299,8 +283,8 @@ void ShadowRoot::RemoveSlot(HTMLSlotElement* aSlot) {
while (!assignedNodes.IsEmpty()) { while (!assignedNodes.IsEmpty()) {
nsINode* assignedNode = assignedNodes[0]; nsINode* assignedNode = assignedNodes[0];
aSlot->RemoveAssignedNode(assignedNode); aSlot->RemoveAssignedNode(*assignedNode->AsContent());
replacementSlot->AppendAssignedNode(assignedNode); replacementSlot->AppendAssignedNode(*assignedNode->AsContent());
} }
aSlot->EnqueueSlotChangeEvent(); aSlot->EnqueueSlotChangeEvent();
@ -488,7 +472,7 @@ void ShadowRoot::GetEventTargetParent(EventChainPreVisitor& aVisitor) {
} }
} }
ShadowRoot::SlotAssignment ShadowRoot::SlotAssignmentFor(nsIContent* aContent) { ShadowRoot::SlotAssignment ShadowRoot::SlotAssignmentFor(nsIContent& aContent) {
nsAutoString slotName; nsAutoString slotName;
// Note that if slot attribute is missing, assign it to the first default // Note that if slot attribute is missing, assign it to the first default
// slot, if exists. // slot, if exists.
@ -513,7 +497,7 @@ ShadowRoot::SlotAssignment ShadowRoot::SlotAssignmentFor(nsIContent* aContent) {
// Seek through the host's explicit children until the // Seek through the host's explicit children until the
// assigned content is found. // assigned content is found.
while (currentContent && currentContent != assignedNodes[i]) { while (currentContent && currentContent != assignedNodes[i]) {
if (currentContent == aContent) { if (currentContent == &aContent) {
insertionIndex.emplace(i); insertionIndex.emplace(i);
break; break;
} }
@ -529,9 +513,9 @@ ShadowRoot::SlotAssignment ShadowRoot::SlotAssignmentFor(nsIContent* aContent) {
return {slot, insertionIndex}; return {slot, insertionIndex};
} }
void ShadowRoot::MaybeReassignElement(Element* aElement) { void ShadowRoot::MaybeReassignElement(Element& aElement) {
MOZ_ASSERT(aElement->GetParent() == GetHost()); MOZ_ASSERT(aElement.GetParent() == GetHost());
HTMLSlotElement* oldSlot = aElement->GetAssignedSlot(); HTMLSlotElement* oldSlot = aElement.GetAssignedSlot();
SlotAssignment assignment = SlotAssignmentFor(aElement); SlotAssignment assignment = SlotAssignmentFor(aElement);
if (assignment.mSlot == oldSlot) { if (assignment.mSlot == oldSlot) {
@ -541,7 +525,7 @@ void ShadowRoot::MaybeReassignElement(Element* aElement) {
if (Document* doc = GetComposedDoc()) { if (Document* doc = GetComposedDoc()) {
if (RefPtr<PresShell> presShell = doc->GetPresShell()) { if (RefPtr<PresShell> presShell = doc->GetPresShell()) {
presShell->SlotAssignmentWillChange(*aElement, oldSlot, assignment.mSlot); presShell->SlotAssignmentWillChange(aElement, oldSlot, assignment.mSlot);
} }
} }
@ -615,103 +599,56 @@ nsINode* ShadowRoot::CreateElementAndAppendChildAt(nsINode& aParentNode,
return aParentNode.AppendChild(*node, rv); return aParentNode.AppendChild(*node, rv);
} }
void ShadowRoot::AttributeChanged(Element* aElement, int32_t aNameSpaceID, void ShadowRoot::MaybeUnslotHostChild(nsIContent& aChild) {
nsAtom* aAttribute, int32_t aModType, // Need to null-check the host because we may be unlinked already.
const nsAttrValue* aOldValue) { MOZ_ASSERT(!GetHost() || aChild.GetParent() == GetHost());
if (aNameSpaceID != kNameSpaceID_None || aAttribute != nsGkAtoms::slot) {
HTMLSlotElement* slot = aChild.GetAssignedSlot();
if (!slot) {
return; return;
} }
if (aElement->GetParent() != GetHost()) { MOZ_DIAGNOSTIC_ASSERT(!aChild.IsRootOfAnonymousSubtree(),
return; "How did aChild end up assigned to a slot?");
// If the slot is going to start showing fallback content, we need to tell
// layout about it.
if (slot->AssignedNodes().Length() == 1) {
InvalidateStyleAndLayoutOnSubtree(slot);
} }
MaybeReassignElement(aElement); slot->RemoveAssignedNode(aChild);
slot->EnqueueSlotChangeEvent();
} }
void ShadowRoot::ContentAppended(nsIContent* aFirstNewContent) { void ShadowRoot::MaybeSlotHostChild(nsIContent& aChild) {
for (nsIContent* content = aFirstNewContent; content; MOZ_ASSERT(aChild.GetParent() == GetHost());
content = content->GetNextSibling()) { // Check to ensure that the child not an anonymous subtree root because even
ContentInserted(content); // though its parent could be the host it may not be in the host's child list.
} if (aChild.IsRootOfAnonymousSubtree()) {
}
void ShadowRoot::ContentInserted(nsIContent* aChild) {
// Check to ensure that the child not an anonymous subtree root because
// even though its parent could be the host it may not be in the host's child
// list.
if (aChild->IsRootOfAnonymousSubtree()) {
return; return;
} }
if (!aChild->IsSlotable()) { if (!aChild.IsSlotable()) {
return; return;
} }
if (aChild->GetParent() == GetHost()) { SlotAssignment assignment = SlotAssignmentFor(aChild);
SlotAssignment assignment = SlotAssignmentFor(aChild); if (!assignment.mSlot) {
if (!assignment.mSlot) {
return;
}
// Fallback content will go away, let layout know.
if (assignment.mSlot->AssignedNodes().IsEmpty()) {
InvalidateStyleAndLayoutOnSubtree(assignment.mSlot);
}
if (assignment.mIndex) {
assignment.mSlot->InsertAssignedNode(*assignment.mIndex, aChild);
} else {
assignment.mSlot->AppendAssignedNode(aChild);
}
assignment.mSlot->EnqueueSlotChangeEvent();
SlotStateChanged(assignment.mSlot);
return; return;
} }
// If parent's root is a shadow root, and parent is a slot whose assigned // Fallback content will go away, let layout know.
// nodes is the empty list, then run signal a slot change for parent. if (assignment.mSlot->AssignedNodes().IsEmpty()) {
HTMLSlotElement* slot = HTMLSlotElement::FromNodeOrNull(aChild->GetParent()); InvalidateStyleAndLayoutOnSubtree(assignment.mSlot);
if (slot && slot->GetContainingShadow() == this &&
slot->AssignedNodes().IsEmpty()) {
slot->EnqueueSlotChangeEvent();
}
}
void ShadowRoot::ContentRemoved(nsIContent* aChild,
nsIContent* aPreviousSibling) {
// Check to ensure that the child not an anonymous subtree root because
// even though its parent could be the host it may not be in the host's child
// list.
if (aChild->IsRootOfAnonymousSubtree()) {
return;
} }
if (!aChild->IsSlotable()) { if (assignment.mIndex) {
return; assignment.mSlot->InsertAssignedNode(*assignment.mIndex, aChild);
} } else {
assignment.mSlot->AppendAssignedNode(aChild);
if (aChild->GetParent() == GetHost()) {
if (HTMLSlotElement* slot = aChild->GetAssignedSlot()) {
// If the slot is going to start showing fallback content, we need to tell
// layout about it.
if (slot->AssignedNodes().Length() == 1) {
InvalidateStyleAndLayoutOnSubtree(slot);
}
slot->RemoveAssignedNode(aChild);
slot->EnqueueSlotChangeEvent();
}
return;
}
// If parent's root is a shadow root, and parent is a slot whose assigned
// nodes is the empty list, then run signal a slot change for parent.
HTMLSlotElement* slot = HTMLSlotElement::FromNodeOrNull(aChild->GetParent());
if (slot && slot->GetContainingShadow() == this &&
slot->AssignedNodes().IsEmpty()) {
slot->EnqueueSlotChangeEvent();
} }
assignment.mSlot->EnqueueSlotChangeEvent();
SlotStateChanged(assignment.mSlot);
} }
ServoStyleRuleMap& ShadowRoot::ServoStyleRuleMap() { ServoStyleRuleMap& ShadowRoot::ServoStyleRuleMap() {

Просмотреть файл

@ -39,7 +39,6 @@ class HTMLInputElement;
class ShadowRoot final : public DocumentFragment, class ShadowRoot final : public DocumentFragment,
public DocumentOrShadowRoot, public DocumentOrShadowRoot,
public nsStubMutationObserver,
public nsIRadioGroupContainer { public nsIRadioGroupContainer {
public: public:
NS_IMPL_FROMNODE_HELPER(ShadowRoot, IsShadowRoot()); NS_IMPL_FROMNODE_HELPER(ShadowRoot, IsShadowRoot());
@ -47,16 +46,20 @@ class ShadowRoot final : public DocumentFragment,
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ShadowRoot, DocumentFragment) NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ShadowRoot, DocumentFragment)
NS_DECL_ISUPPORTS_INHERITED NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
ShadowRoot(Element* aElement, ShadowRootMode aMode, ShadowRoot(Element* aElement, ShadowRootMode aMode,
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo); already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
void AddSizeOfExcludingThis(nsWindowSizes&, size_t* aNodeSize) const final; void AddSizeOfExcludingThis(nsWindowSizes&, size_t* aNodeSize) const final;
// Try to reassign an element to a slot.
void MaybeReassignElement(Element&);
// Called when an element is inserted as a direct child of our host. Tries to
// slot the child in one of our slots.
void MaybeSlotHostChild(nsIContent&);
// Called when a direct child of our host is removed. Tries to un-slot the
// child from the currently-assigned slot, if any.
void MaybeUnslotHostChild(nsIContent&);
// Shadow DOM v1 // Shadow DOM v1
Element* Host() const { Element* Host() const {
MOZ_ASSERT(GetHost(), MOZ_ASSERT(GetHost(),
@ -106,12 +109,6 @@ class ShadowRoot final : public DocumentFragment,
InsertSheetAt(SheetCount(), aSheet); InsertSheetAt(SheetCount(), aSheet);
} }
/**
* Try to reassign an element to a slot and returns whether the assignment
* changed.
*/
void MaybeReassignElement(Element* aElement);
/** /**
* Represents the insertion point in a slot for a given node. * Represents the insertion point in a slot for a given node.
*/ */
@ -131,7 +128,7 @@ class ShadowRoot final : public DocumentFragment,
* It's the caller's responsibility to actually call InsertAssignedNode / * It's the caller's responsibility to actually call InsertAssignedNode /
* AppendAssignedNode in the slot as needed. * AppendAssignedNode in the slot as needed.
*/ */
SlotAssignment SlotAssignmentFor(nsIContent* aContent); SlotAssignment SlotAssignmentFor(nsIContent&);
/** /**
* Explicitly invalidates the style and layout of the flattened-tree subtree * Explicitly invalidates the style and layout of the flattened-tree subtree

Просмотреть файл

@ -468,6 +468,12 @@ if CONFIG['INTEL_ARCHITECTURE']:
SOURCES += ['nsTextFragmentSSE2.cpp'] SOURCES += ['nsTextFragmentSSE2.cpp']
SOURCES['nsTextFragmentSSE2.cpp'].flags += CONFIG['SSE2_FLAGS'] SOURCES['nsTextFragmentSSE2.cpp'].flags += CONFIG['SSE2_FLAGS']
# Are we targeting PowerPC? If so, we can enable a SIMD version for
# nsTextFragment.cpp as well.
if CONFIG['CPU_ARCH'].startswith('ppc'):
SOURCES += ['nsTextFragmentVMX.cpp']
SOURCES['nsTextFragmentVMX.cpp'].flags += CONFIG['PPC_VMX_FLAGS']
EXTRA_JS_MODULES += [ EXTRA_JS_MODULES += [
'ContentAreaDropListener.jsm', 'ContentAreaDropListener.jsm',
'DOMRequestHelper.jsm', 'DOMRequestHelper.jsm',

Просмотреть файл

@ -239,7 +239,8 @@ class nsDocumentEncoder : public nsIDocumentEncoder {
nsresult SerializeToStringRecursive(nsINode* aNode, nsAString& aStr, nsresult SerializeToStringRecursive(nsINode* aNode, nsAString& aStr,
bool aDontSerializeRoot, bool aDontSerializeRoot,
uint32_t aMaxLength = 0); uint32_t aMaxLength = 0);
nsresult SerializeNodeEnd(nsINode& aNode, nsAString& aStr); nsresult SerializeNodeEnd(nsINode& aOriginalNode, nsAString& aStr,
nsINode* aFixupNode = nullptr);
// This serializes the content of aNode. // This serializes the content of aNode.
nsresult SerializeToStringIterative(nsINode* aNode, nsAString& aStr); nsresult SerializeToStringIterative(nsINode* aNode, nsAString& aStr);
nsresult SerializeRangeToString(nsRange* aRange, nsAString& aOutputString); nsresult SerializeRangeToString(nsRange* aRange, nsAString& aOutputString);
@ -660,9 +661,8 @@ nsresult nsDocumentEncoder::SerializeNodeStart(nsINode& aOriginalNode,
nsLayoutUtils::IsInvisibleBreak(node)) { nsLayoutUtils::IsInvisibleBreak(node)) {
return rv; return rv;
} }
Element* originalElement = aOriginalNode.AsElement(); rv = mSerializer->AppendElementStart(node->AsElement(),
rv = mSerializer->AppendElementStart(node->AsElement(), originalElement, aOriginalNode.AsElement(), aStr);
aStr);
return rv; return rv;
} }
@ -697,26 +697,33 @@ nsresult nsDocumentEncoder::SerializeNodeStart(nsINode& aOriginalNode,
return rv; return rv;
} }
nsresult nsDocumentEncoder::SerializeNodeEnd(nsINode& aNode, nsAString& aStr) { nsresult nsDocumentEncoder::SerializeNodeEnd(nsINode& aOriginalNode,
nsAString& aStr,
nsINode* aFixupNode) {
if (mNeedsPreformatScanning) { if (mNeedsPreformatScanning) {
if (aNode.IsElement()) { if (aOriginalNode.IsElement()) {
mSerializer->ForgetElementForPreformat(aNode.AsElement()); mSerializer->ForgetElementForPreformat(aOriginalNode.AsElement());
} else if (aNode.IsText()) { } else if (aOriginalNode.IsText()) {
const nsCOMPtr<nsINode> parent = aNode.GetParent(); const nsCOMPtr<nsINode> parent = aOriginalNode.GetParent();
if (parent && parent->IsElement()) { if (parent && parent->IsElement()) {
mSerializer->ForgetElementForPreformat(parent->AsElement()); mSerializer->ForgetElementForPreformat(parent->AsElement());
} }
} }
} }
if (IsInvisibleNodeAndShouldBeSkipped(aNode)) { if (IsInvisibleNodeAndShouldBeSkipped(aOriginalNode)) {
return NS_OK; return NS_OK;
} }
nsresult rv = NS_OK; nsresult rv = NS_OK;
if (aNode.IsElement()) { FixupNodeDeterminer fixupNodeDeterminer{mNodeFixup, aFixupNode,
rv = mSerializer->AppendElementEnd(aNode.AsElement(), aStr); aOriginalNode};
nsINode* node = &fixupNodeDeterminer.GetFixupNodeFallBackToOriginalNode();
if (node->IsElement()) {
rv = mSerializer->AppendElementEnd(node->AsElement(),
aOriginalNode.AsElement(), aStr);
} }
return rv; return rv;
@ -773,7 +780,7 @@ nsresult nsDocumentEncoder::SerializeToStringRecursive(nsINode* aNode,
} }
if (!aDontSerializeRoot) { if (!aDontSerializeRoot) {
rv = SerializeNodeEnd(*maybeFixedNode, aStr); rv = SerializeNodeEnd(*aNode, aStr, maybeFixedNode);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }

Просмотреть файл

@ -256,7 +256,9 @@ nsHTMLContentSerializer::AppendElementStart(Element* aElement,
} }
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLContentSerializer::AppendElementEnd(Element* aElement, nsAString& aStr) { nsHTMLContentSerializer::AppendElementEnd(Element* aElement,
Element* aOriginalElement,
nsAString& aStr) {
NS_ENSURE_ARG(aElement); NS_ENSURE_ARG(aElement);
nsAtom* name = aElement->NodeInfo()->NameAtom(); nsAtom* name = aElement->NodeInfo()->NameAtom();

Просмотреть файл

@ -29,6 +29,7 @@ class nsHTMLContentSerializer final : public nsXHTMLContentSerializer {
nsAString& aStr) override; nsAString& aStr) override;
NS_IMETHOD AppendElementEnd(mozilla::dom::Element* aElement, NS_IMETHOD AppendElementEnd(mozilla::dom::Element* aElement,
mozilla::dom::Element* aOriginalElement,
nsAString& aStr) override; nsAString& aStr) override;
NS_IMETHOD AppendDocumentStart(mozilla::dom::Document* aDocument, NS_IMETHOD AppendDocumentStart(mozilla::dom::Document* aDocument,

Просмотреть файл

@ -492,6 +492,22 @@ class nsIContent : public nsINode {
*/ */
inline nsIContent* GetFlattenedTreeParent() const; inline nsIContent* GetFlattenedTreeParent() const;
protected:
// Handles getting inserted or removed directly under a <slot> element.
// This is meant to only be called from the two functions below.
inline void HandleInsertionToOrRemovalFromSlot();
// Handles Shadow-DOM-related state tracking. Meant to be called near the
// end of BindToTree(), only if the tree we're in actually changed, that is,
// after the subtree has been bound to the new parent.
inline void HandleShadowDOMRelatedInsertionSteps(bool aHadParent);
// Handles Shadow-DOM related state tracking. Meant to be called near the
// beginning of UnbindFromTree(), before the node has lost the reference to
// its parent.
inline void HandleShadowDOMRelatedRemovalSteps(bool aNullParent);
public:
/** /**
* API to check if this is a link that's traversed in response to user input * API to check if this is a link that's traversed in response to user input
* (e.g. a click event). Specializations for HTML/SVG/generic XML allow for * (e.g. a click event). Specializations for HTML/SVG/generic XML allow for

Просмотреть файл

@ -221,4 +221,51 @@ inline bool nsIContent::IsInAnonymousSubtree() const {
return !bindingParent->GetShadowRoot(); return !bindingParent->GetShadowRoot();
} }
inline void nsIContent::HandleInsertionToOrRemovalFromSlot() {
using mozilla::dom::HTMLSlotElement;
MOZ_ASSERT(GetParentElement());
if (!IsInShadowTree() || IsRootOfAnonymousSubtree()) {
return;
}
HTMLSlotElement* slot = HTMLSlotElement::FromNode(mParent);
if (!slot) {
return;
}
// If parent's root is a shadow root, and parent is a slot whose
// assigned nodes is the empty list, then run signal a slot change for
// parent.
if (slot->AssignedNodes().IsEmpty()) {
slot->EnqueueSlotChangeEvent();
}
}
inline void nsIContent::HandleShadowDOMRelatedInsertionSteps(bool aHadParent) {
using mozilla::dom::Element;
using mozilla::dom::ShadowRoot;
if (!aHadParent) {
if (Element* parentElement = Element::FromNode(mParent)) {
if (ShadowRoot* shadow = parentElement->GetShadowRoot()) {
shadow->MaybeSlotHostChild(*this);
}
HandleInsertionToOrRemovalFromSlot();
}
}
}
inline void nsIContent::HandleShadowDOMRelatedRemovalSteps(bool aNullParent) {
using mozilla::dom::Element;
using mozilla::dom::ShadowRoot;
if (aNullParent) {
if (Element* parentElement = Element::FromNode(mParent)) {
if (ShadowRoot* shadow = parentElement->GetShadowRoot()) {
shadow->MaybeUnslotHostChild(*this);
}
HandleInsertionToOrRemovalFromSlot();
}
}
}
#endif // nsIContentInlines_h #endif // nsIContentInlines_h

Просмотреть файл

@ -60,6 +60,7 @@ class nsIContentSerializer : public nsISupports {
nsAString& aStr) = 0; nsAString& aStr) = 0;
NS_IMETHOD AppendElementEnd(mozilla::dom::Element* aElement, NS_IMETHOD AppendElementEnd(mozilla::dom::Element* aElement,
mozilla::dom::Element* aOriginalElement,
nsAString& aStr) = 0; nsAString& aStr) = 0;
NS_IMETHOD Flush(nsAString& aStr) = 0; NS_IMETHOD Flush(nsAString& aStr) = 0;

Просмотреть файл

@ -419,7 +419,9 @@ nsPlainTextSerializer::AppendElementStart(Element* aElement,
} }
NS_IMETHODIMP NS_IMETHODIMP
nsPlainTextSerializer::AppendElementEnd(Element* aElement, nsAString& aStr) { nsPlainTextSerializer::AppendElementEnd(Element* aElement,
Element* aOriginalElement,
nsAString& aStr) {
NS_ENSURE_ARG(aElement); NS_ENSURE_ARG(aElement);
mElement = aElement; mElement = aElement;

Просмотреть файл

@ -69,6 +69,7 @@ class nsPlainTextSerializer final : public nsIContentSerializer {
mozilla::dom::Element* aOriginalElement, mozilla::dom::Element* aOriginalElement,
nsAString& aStr) override; nsAString& aStr) override;
NS_IMETHOD AppendElementEnd(mozilla::dom::Element* aElement, NS_IMETHOD AppendElementEnd(mozilla::dom::Element* aElement,
mozilla::dom::Element* aOriginalElement,
nsAString& aStr) override; nsAString& aStr) override;
NS_IMETHOD Flush(nsAString& aStr) override; NS_IMETHOD Flush(nsAString& aStr) override;

Просмотреть файл

@ -19,6 +19,7 @@
#include "mozilla/CheckedInt.h" #include "mozilla/CheckedInt.h"
#include "mozilla/MemoryReporting.h" #include "mozilla/MemoryReporting.h"
#include "mozilla/SSE.h" #include "mozilla/SSE.h"
#include "mozilla/ppc.h"
#include "nsTextFragmentImpl.h" #include "nsTextFragmentImpl.h"
#include <algorithm> #include <algorithm>
@ -166,6 +167,14 @@ int32_t FirstNon8Bit(const char16_t* str, const char16_t* end);
} // namespace mozilla } // namespace mozilla
#endif #endif
#ifdef __powerpc__
namespace mozilla {
namespace VMX {
int32_t FirstNon8Bit(const char16_t* str, const char16_t* end);
} // namespace VMX
} // namespace mozilla
#endif
/* /*
* This function returns -1 if all characters in str are 8 bit characters. * This function returns -1 if all characters in str are 8 bit characters.
* Otherwise, it returns a value less than or equal to the index of the first * Otherwise, it returns a value less than or equal to the index of the first
@ -178,6 +187,10 @@ static inline int32_t FirstNon8Bit(const char16_t* str, const char16_t* end) {
if (mozilla::supports_sse2()) { if (mozilla::supports_sse2()) {
return mozilla::SSE2::FirstNon8Bit(str, end); return mozilla::SSE2::FirstNon8Bit(str, end);
} }
#elif defined(__powerpc__)
if (mozilla::supports_vmx()) {
return mozilla::VMX::FirstNon8Bit(str, end);
}
#endif #endif
return FirstNon8BitUnvectorized(str, end); return FirstNon8BitUnvectorized(str, end);

Просмотреть файл

@ -0,0 +1,100 @@
/* 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/. */
// This file should only be compiled if you're on Power ISA.
#include "nscore.h"
#include "nsAlgorithm.h"
#include "nsTextFragmentImpl.h"
#include <altivec.h>
namespace mozilla {
namespace VMX {
int32_t FirstNon8Bit(const char16_t* str, const char16_t* end) {
const uint32_t numUnicharsPerVector = 8;
const uint32_t numCharsPerVector = 16;
// Paranoia. If this assertion is wrong, change the vector loop below.
MOZ_ASSERT((numCharsPerVector / numUnicharsPerVector) == sizeof(char16_t));
typedef Non8BitParameters<sizeof(size_t)> p;
const uint32_t alignMask = p::alignMask();
const size_t mask = p::mask();
const uint32_t numUnicharsPerWord = p::numUnicharsPerWord();
const uint32_t len = end - str;
// i shall count the index in unichars; i2 shall count the index in chars.
uint32_t i = 0;
uint32_t i2 = 0;
// Align ourselves to a 16-byte boundary, as required by VMX loads.
uint32_t alignLen = std::min(
len, uint32_t(((-NS_PTR_TO_UINT32(str)) & 0xf) / sizeof(char16_t)));
if ((len - alignLen) >= numUnicharsPerVector) {
for (; i < alignLen; i++) {
if (str[i] > 255) return i;
}
// Construct a vector of shorts.
#if __LITTLE_ENDIAN__
register const vector unsigned short gtcompare =
reinterpret_cast<vector unsigned short>(
vec_mergel(vec_splat_s8(-1), vec_splat_s8(0)));
#else
register const vector unsigned short gtcompare =
reinterpret_cast<vector unsigned short>(
vec_mergel(vec_splat_s8(0), vec_splat_s8(-1)));
#endif
const uint32_t vectWalkEnd =
((len - i) / numUnicharsPerVector) * numUnicharsPerVector;
i2 = i * sizeof(char16_t);
while (1) {
register vector unsigned short vect;
// Check one VMX register (8 unichars) at a time. The vec_any_gt
// intrinsic does exactly what we want. This loop is manually unrolled;
// it yields notable performance improvements this way.
#define CheckForASCII \
vect = vec_ld(i2, reinterpret_cast<const unsigned short*>(str)); \
if (vec_any_gt(vect, gtcompare)) return i; \
i += numUnicharsPerVector; \
if (!(i < vectWalkEnd)) break; \
i2 += numCharsPerVector;
CheckForASCII CheckForASCII
#undef CheckForASCII
}
} else {
// Align ourselves to a word boundary.
alignLen = std::min(len, uint32_t(((-NS_PTR_TO_UINT32(str)) & alignMask) /
sizeof(char16_t)));
for (; i < alignLen; i++) {
if (str[i] > 255) return i;
}
}
// Check one word at a time.
const uint32_t wordWalkEnd =
((len - i) / numUnicharsPerWord) * numUnicharsPerWord;
for (; i < wordWalkEnd; i += numUnicharsPerWord) {
const size_t word = *reinterpret_cast<const size_t*>(str + i);
if (word & mask) return i;
}
// Take care of the remainder one character at a time.
for (; i < len; i++) {
if (str[i] > 255) {
return i;
}
}
return -1;
}
} // namespace VMX
} // namespace mozilla

Просмотреть файл

@ -410,6 +410,7 @@ bool nsXHTMLContentSerializer::CheckElementStart(Element* aElement,
} }
bool nsXHTMLContentSerializer::CheckElementEnd(Element* aElement, bool nsXHTMLContentSerializer::CheckElementEnd(Element* aElement,
Element* aOriginalElement,
bool& aForceFormat, bool& aForceFormat,
nsAString& aStr) { nsAString& aStr) {
NS_ASSERTION(!mIsHTMLSerializer, NS_ASSERTION(!mIsHTMLSerializer,
@ -428,7 +429,8 @@ bool nsXHTMLContentSerializer::CheckElementEnd(Element* aElement,
} }
bool dummyFormat; bool dummyFormat;
return nsXMLContentSerializer::CheckElementEnd(aElement, dummyFormat, aStr); return nsXMLContentSerializer::CheckElementEnd(aElement, aOriginalElement,
dummyFormat, aStr);
} }
bool nsXHTMLContentSerializer::AppendAndTranslateEntities( bool nsXHTMLContentSerializer::AppendAndTranslateEntities(

Просмотреть файл

@ -52,6 +52,7 @@ class nsXHTMLContentSerializer : public nsXMLContentSerializer {
nsAString& aStr) override; nsAString& aStr) override;
virtual bool CheckElementEnd(mozilla::dom::Element* aContent, virtual bool CheckElementEnd(mozilla::dom::Element* aContent,
mozilla::dom::Element* aOriginalElement,
bool& aForceFormat, nsAString& aStr) override; bool& aForceFormat, nsAString& aStr) override;
virtual void AfterElementEnd(nsIContent* aContent, nsAString& aStr) override; virtual void AfterElementEnd(nsIContent* aContent, nsAString& aStr) override;

Просмотреть файл

@ -955,13 +955,16 @@ bool nsXMLContentSerializer::AppendEndOfElementStart(Element* aElement,
} }
NS_IMETHODIMP NS_IMETHODIMP
nsXMLContentSerializer::AppendElementEnd(Element* aElement, nsAString& aStr) { nsXMLContentSerializer::AppendElementEnd(Element* aElement,
Element* aOriginalElement,
nsAString& aStr) {
NS_ENSURE_ARG(aElement); NS_ENSURE_ARG(aElement);
nsIContent* content = aElement; nsIContent* content = aElement;
bool forceFormat = false, outputElementEnd; bool forceFormat = false, outputElementEnd;
outputElementEnd = CheckElementEnd(aElement, forceFormat, aStr); outputElementEnd =
CheckElementEnd(aElement, aOriginalElement, forceFormat, aStr);
nsAtom* name = content->NodeInfo()->NameAtom(); nsAtom* name = content->NodeInfo()->NameAtom();
@ -1083,15 +1086,12 @@ bool nsXMLContentSerializer::CheckElementStart(Element*, bool& aForceFormat,
} }
bool nsXMLContentSerializer::CheckElementEnd(Element* aElement, bool nsXMLContentSerializer::CheckElementEnd(Element* aElement,
Element* aOriginalElement,
bool& aForceFormat, bool& aForceFormat,
nsAString& aStr) { nsAString& aStr) {
// We don't output a separate end tag for empty element // We don't output a separate end tag for empty element
aForceFormat = false; aForceFormat = false;
return ElementNeedsSeparateEndTag(aElement, aOriginalElement);
// XXXbz this is a bit messed up, but by now we don't have our fixed-up
// version of aElement anymore. Let's hope fixup never changes the localName
// or namespace...
return ElementNeedsSeparateEndTag(aElement, aElement);
} }
bool nsXMLContentSerializer::AppendToString(const char16_t aChar, bool nsXMLContentSerializer::AppendToString(const char16_t aChar,

Просмотреть файл

@ -63,6 +63,7 @@ class nsXMLContentSerializer : public nsIContentSerializer {
nsAString& aStr) override; nsAString& aStr) override;
NS_IMETHOD AppendElementEnd(mozilla::dom::Element* aElement, NS_IMETHOD AppendElementEnd(mozilla::dom::Element* aElement,
mozilla::dom::Element* aOriginalElement,
nsAString& aStr) override; nsAString& aStr) override;
NS_IMETHOD Flush(nsAString& aStr) override { return NS_OK; } NS_IMETHOD Flush(nsAString& aStr) override { return NS_OK; }
@ -305,6 +306,7 @@ class nsXMLContentSerializer : public nsIContentSerializer {
* @return boolean true if the element can be output * @return boolean true if the element can be output
*/ */
virtual bool CheckElementEnd(mozilla::dom::Element* aElement, virtual bool CheckElementEnd(mozilla::dom::Element* aElement,
mozilla::dom::Element* aOriginalElement,
bool& aForceFormat, nsAString& aStr); bool& aForceFormat, nsAString& aStr);
/** /**

Просмотреть файл

@ -154,26 +154,25 @@ const nsTArray<RefPtr<nsINode>>& HTMLSlotElement::AssignedNodes() const {
return mAssignedNodes; return mAssignedNodes;
} }
void HTMLSlotElement::InsertAssignedNode(uint32_t aIndex, nsINode* aNode) { void HTMLSlotElement::InsertAssignedNode(uint32_t aIndex, nsIContent& aNode) {
MOZ_ASSERT(!aNode->AsContent()->GetAssignedSlot(), "Losing track of a slot"); MOZ_ASSERT(!aNode.GetAssignedSlot(), "Losing track of a slot");
mAssignedNodes.InsertElementAt(aIndex, aNode); mAssignedNodes.InsertElementAt(aIndex, &aNode);
aNode->AsContent()->SetAssignedSlot(this); aNode.SetAssignedSlot(this);
} }
void HTMLSlotElement::AppendAssignedNode(nsINode* aNode) { void HTMLSlotElement::AppendAssignedNode(nsIContent& aNode) {
MOZ_ASSERT(!aNode->AsContent()->GetAssignedSlot(), "Losing track of a slot"); MOZ_ASSERT(!aNode.GetAssignedSlot(), "Losing track of a slot");
mAssignedNodes.AppendElement(aNode); mAssignedNodes.AppendElement(&aNode);
aNode->AsContent()->SetAssignedSlot(this); aNode.SetAssignedSlot(this);
} }
void HTMLSlotElement::RemoveAssignedNode(nsINode* aNode) { void HTMLSlotElement::RemoveAssignedNode(nsIContent& aNode) {
// This one runs from unlinking, so we can't guarantee that the slot pointer // This one runs from unlinking, so we can't guarantee that the slot pointer
// hasn't been cleared. // hasn't been cleared.
MOZ_ASSERT(!aNode->AsContent()->GetAssignedSlot() || MOZ_ASSERT(!aNode.GetAssignedSlot() || aNode.GetAssignedSlot() == this,
aNode->AsContent()->GetAssignedSlot() == this,
"How exactly?"); "How exactly?");
mAssignedNodes.RemoveElement(aNode); mAssignedNodes.RemoveElement(&aNode);
aNode->AsContent()->SetAssignedSlot(nullptr); aNode.SetAssignedSlot(nullptr);
} }
void HTMLSlotElement::ClearAssignedNodes() { void HTMLSlotElement::ClearAssignedNodes() {

Просмотреть файл

@ -54,9 +54,9 @@ class HTMLSlotElement final : public nsGenericHTMLElement {
// Helper methods // Helper methods
const nsTArray<RefPtr<nsINode>>& AssignedNodes() const; const nsTArray<RefPtr<nsINode>>& AssignedNodes() const;
void InsertAssignedNode(uint32_t aIndex, nsINode* aNode); void InsertAssignedNode(uint32_t aIndex, nsIContent&);
void AppendAssignedNode(nsINode* aNode); void AppendAssignedNode(nsIContent&);
void RemoveAssignedNode(nsINode* aNode); void RemoveAssignedNode(nsIContent&);
void ClearAssignedNodes(); void ClearAssignedNodes();
void EnqueueSlotChangeEvent(); void EnqueueSlotChangeEvent();

Просмотреть файл

@ -47,6 +47,7 @@ skip-if = toolkit == 'android'
[test_same_site_cookies_toplevel_nav.html] [test_same_site_cookies_toplevel_nav.html]
skip-if = fission # Crashes: @ mozilla::dom::ContentParent::CommonCreateWindow(mozilla::dom::PBrowserParent*, bool, unsigned int const&, bool const&, bool const&, bool const&, nsIURI*, nsTString<char> const&, float const&, unsigned long, nsTString<char16_t> const&, nsresult&, nsCOMPtr<nsIRemoteTab>&, bool*, int&, nsIPrincipal*, nsIReferrerInfo*, bool, nsIContentSecurityPolicy*) skip-if = fission # Crashes: @ mozilla::dom::ContentParent::CommonCreateWindow(mozilla::dom::PBrowserParent*, bool, unsigned int const&, bool const&, bool const&, bool const&, nsIURI*, nsTString<char> const&, float const&, unsigned long, nsTString<char16_t> const&, nsresult&, nsCOMPtr<nsIRemoteTab>&, bool*, int&, nsIPrincipal*, nsIReferrerInfo*, bool, nsIContentSecurityPolicy*)
[test_same_site_cookies_cross_origin_context.html] [test_same_site_cookies_cross_origin_context.html]
fail-if = fission
[test_same_site_cookies_from_script.html] [test_same_site_cookies_from_script.html]
[test_same_site_cookies_redirect.html] [test_same_site_cookies_redirect.html]
[test_same_site_cookies_toplevel_set_cookie.html] [test_same_site_cookies_toplevel_set_cookie.html]

Просмотреть файл

@ -156,7 +156,6 @@ skip-if = toolkit == 'android'
[test_bug1112040.html] [test_bug1112040.html]
[test_bug1160342_marquee.html] [test_bug1160342_marquee.html]
[test_bug1171215.html] [test_bug1171215.html]
fail-if = fission
support-files = window_bug1171215.html support-files = window_bug1171215.html
[test_bug1530292.html] [test_bug1530292.html]
fail-if = fission fail-if = fission

Просмотреть файл

@ -27,6 +27,7 @@ skip-if = os == "android" || verify # bug 962029
[test_cookieBlock.html] [test_cookieBlock.html]
[test_embededNulls.html] [test_embededNulls.html]
[test_keySync.html] [test_keySync.html]
fail-if = fission
[test_localStorageBase.html] [test_localStorageBase.html]
skip-if = e10s skip-if = e10s
[test_localStorageBaseSessionOnly.html] [test_localStorageBaseSessionOnly.html]
@ -34,12 +35,17 @@ skip-if = e10s
[test_localStorageEnablePref.html] [test_localStorageEnablePref.html]
[test_localStorageKeyOrder.html] [test_localStorageKeyOrder.html]
[test_localStorageOriginsDiff.html] [test_localStorageOriginsDiff.html]
fail-if = fission
[test_localStorageOriginsDomainDiffs.html] [test_localStorageOriginsDomainDiffs.html]
fail-if = fission
[test_localStorageOriginsEquals.html] [test_localStorageOriginsEquals.html]
skip-if = toolkit == 'android' skip-if = toolkit == 'android'
fail-if = fission
[test_localStorageOriginsPortDiffs.html] [test_localStorageOriginsPortDiffs.html]
fail-if = fission
[test_localStorageOriginsSchemaDiffs.html] [test_localStorageOriginsSchemaDiffs.html]
skip-if = toolkit == 'android' #TIMED_OUT skip-if = toolkit == 'android' #TIMED_OUT
fail-if = fission
[test_localStorageQuota.html] [test_localStorageQuota.html]
skip-if = toolkit == 'android' #TIMED_OUT skip-if = toolkit == 'android' #TIMED_OUT
[test_localStorageQuotaSessionOnly.html] [test_localStorageQuotaSessionOnly.html]

Просмотреть файл

@ -25,15 +25,11 @@ support-files =
skip-if = toolkit == 'android' #bug 894914 - wrong data - got FAIL, expected message skip-if = toolkit == 'android' #bug 894914 - wrong data - got FAIL, expected message
[test_postMessage_hash.html] [test_postMessage_hash.html]
[test_postMessage.html] [test_postMessage.html]
fail-if = fission
[test_postMessage_idn.xhtml] [test_postMessage_idn.xhtml]
fail-if = fission
[test_postMessage_joined.html] [test_postMessage_joined.html]
fail-if = fission
[test_postMessage_onOther.html] [test_postMessage_onOther.html]
skip-if = fission #Bug 1571273 skip-if = fission #Bug 1571273
[test_postMessage_origin.xhtml] [test_postMessage_origin.xhtml]
fail-if = fission
[test_postMessage_override.html] [test_postMessage_override.html]
skip-if = fission skip-if = fission
[test_postMessage_special.xhtml] [test_postMessage_special.xhtml]
@ -43,7 +39,6 @@ skip-if = fission #Bug 1570918
[test_postMessage_transfer.html] [test_postMessage_transfer.html]
skip-if = fission #Bug 1571208 skip-if = fission #Bug 1571208
[test_postMessage_userpass.html] [test_postMessage_userpass.html]
fail-if = fission
[test_bug500328.html] [test_bug500328.html]
skip-if = true || toolkit=='android' # bug 696306, #TIMED_OUT android skip-if = true || toolkit=='android' # bug 696306, #TIMED_OUT android
support-files = file_bug500328_1.html file_bug500328_2.html support-files = file_bug500328_1.html file_bug500328_2.html

Просмотреть файл

@ -16,6 +16,7 @@ support-files =
[test_bug1081686.html] [test_bug1081686.html]
[test_bug1384658.html] [test_bug1384658.html]
skip-if = fission # Timeouts
support-files = window_bug1384658.html frame_bug1384658.html file_bug1384658.html support-files = window_bug1384658.html frame_bug1384658.html file_bug1384658.html
[test_event_listener_leaks.html] [test_event_listener_leaks.html]
support-files = file_websocket_bigBlob_wsh.py support-files = file_websocket_bigBlob_wsh.py

Просмотреть файл

@ -145,6 +145,7 @@ tags = mcb
[test_location.html] [test_location.html]
[test_longThread.html] [test_longThread.html]
[test_multi_sharedWorker.html] [test_multi_sharedWorker.html]
skip-if = fission # Timeouts
[test_multi_sharedWorker_lifetimes.html] [test_multi_sharedWorker_lifetimes.html]
[test_navigator.html] [test_navigator.html]
support-files = support-files =

Просмотреть файл

@ -58,6 +58,16 @@ struct SurfaceDescriptorMacIOSurface {
YUVColorSpace yUVColorSpace; YUVColorSpace yUVColorSpace;
}; };
struct SurfaceDescriptorDMABuf {
uint32_t width;
uint32_t height;
uint32_t format;
uint32_t flags;
FileDescriptor fd;
uint32_t stride;
uint32_t offset;
};
struct SurfaceTextureDescriptor { struct SurfaceTextureDescriptor {
uint64_t handle; uint64_t handle;
IntSize size; IntSize size;
@ -148,6 +158,7 @@ union SurfaceDescriptor {
SurfaceDescriptorFileMapping; SurfaceDescriptorFileMapping;
SurfaceDescriptorDXGIYCbCr; SurfaceDescriptorDXGIYCbCr;
SurfaceDescriptorX11; SurfaceDescriptorX11;
SurfaceDescriptorDMABuf;
SurfaceTextureDescriptor; SurfaceTextureDescriptor;
EGLImageDescriptor; EGLImageDescriptor;
SurfaceDescriptorMacIOSurface; SurfaceDescriptorMacIOSurface;

Просмотреть файл

@ -439,7 +439,7 @@ set_define('JS_BUILD_BINAST', depends_if('--enable-binast')(lambda x: True))
# ============================================================== # ==============================================================
js_option('--enable-cranelift', js_option('--enable-cranelift',
default=milestone.is_nightly & js_standalone, default=milestone.is_nightly,
help='{Enable|Disable} Cranelift code generator for wasm') help='{Enable|Disable} Cranelift code generator for wasm')
set_config('ENABLE_WASM_CRANELIFT', depends_if('--enable-cranelift')(lambda x: True)) set_config('ENABLE_WASM_CRANELIFT', depends_if('--enable-cranelift')(lambda x: True))

Просмотреть файл

@ -291,6 +291,7 @@ struct LazyScriptCreationData {
} }
if (!closedOverBindings.appendAll(COB)) { if (!closedOverBindings.appendAll(COB)) {
ReportOutOfMemory(cx); // closedOverBindings uses SystemAllocPolicy.
return false; return false;
} }
return true; return true;

Просмотреть файл

@ -0,0 +1,49 @@
// |jit-test| skip-if: !('oomTest' in this)
var sourceText = `
function Outer() {
var X00, X01, X02, X03, X04, X05, X06, X07;
var X08, X09, X10, X11, X12, X13, X14, X15;
var X16, X17, X18, X19, X20, X21, X22, X23;
var X24, X25, X26, X27, X28, X29, X30, X31;
function LazyFunction() {
// Lots of closed-over bindings.
{ X00 = true; };
{ X01 = true; };
{ X02 = true; };
{ X03 = true; };
{ X04 = true; };
{ X05 = true; };
{ X06 = true; };
{ X07 = true; };
{ X08 = true; };
{ X09 = true; };
{ X10 = true; };
{ X11 = true; };
{ X12 = true; };
{ X13 = true; };
{ X14 = true; };
{ X15 = true; };
{ X16 = true; };
{ X17 = true; };
{ X18 = true; };
{ X19 = true; };
{ X20 = true; };
{ X21 = true; };
{ X22 = true; };
{ X23 = true; };
{ X24 = true; };
{ X25 = true; };
{ X26 = true; };
{ X27 = true; };
{ X28 = true; };
{ X29 = true; };
{ X30 = true; };
{ X31 = true; };
}
}
`;
oomTest(function() {
evaluate(sourceText);
});

Просмотреть файл

@ -0,0 +1,44 @@
// |jit-test| skip-if: !('oomTest' in this)
var sourceText = `
function Outer() {
function LazyFunction() {
// Lots of inner functions.
function F00() { }
function F01() { }
function F02() { }
function F03() { }
function F04() { }
function F05() { }
function F06() { }
function F07() { }
function F08() { }
function F09() { }
function F10() { }
function F11() { }
function F12() { }
function F13() { }
function F14() { }
function F15() { }
function F16() { }
function F17() { }
function F18() { }
function F19() { }
function F20() { }
function F21() { }
function F22() { }
function F23() { }
function F24() { }
function F25() { }
function F26() { }
function F27() { }
function F28() { }
function F29() { }
function F30() { }
function F31() { }
}
}
`;
oomTest(function() {
evaluate(sourceText);
});

Просмотреть файл

@ -47,6 +47,9 @@ for stlfile in ['jsdate.*', 'jsnum.*']:
with Files('builtin/intl/*'): with Files('builtin/intl/*'):
BUG_COMPONENT = component_intl BUG_COMPONENT = component_intl
if CONFIG['ENABLE_WASM_CRANELIFT']:
CONFIGURE_SUBST_FILES += ['rust/extra-bindgen-flags']
if not CONFIG['JS_DISABLE_SHELL']: if not CONFIG['JS_DISABLE_SHELL']:
DIRS += [ DIRS += [
'rust', 'rust',

Просмотреть файл

@ -18,8 +18,6 @@ if CONFIG['ENABLE_WASM_CRANELIFT']:
RustLibrary('jsrust', features) RustLibrary('jsrust', features)
CONFIGURE_SUBST_FILES += ['extra-bindgen-flags']
if CONFIG['JS_SHARED_LIBRARY']: if CONFIG['JS_SHARED_LIBRARY']:
FINAL_LIBRARY = 'js' FINAL_LIBRARY = 'js'

Просмотреть файл

@ -4012,9 +4012,7 @@ void PaintedLayerData::AccumulateHitTestItem(ContainerState* aState,
nsDisplayItem* aItem, nsDisplayItem* aItem,
const DisplayItemClip& aClip, const DisplayItemClip& aClip,
TransformClipNode* aTransform) { TransformClipNode* aTransform) {
MOZ_ASSERT(aItem->HasHitTestInfo());
auto* item = static_cast<nsDisplayHitTestInfoItem*>(aItem); auto* item = static_cast<nsDisplayHitTestInfoItem*>(aItem);
const HitTestInfo& info = item->GetHitTestInfo(); const HitTestInfo& info = item->GetHitTestInfo();
nsRect area = info.mArea; nsRect area = info.mArea;
@ -4556,6 +4554,7 @@ void ContainerState::ProcessDisplayItems(nsDisplayList* aList) {
nsRect itemContent; nsRect itemContent;
if (marker == DisplayItemEntryType::HitTestInfo) { if (marker == DisplayItemEntryType::HitTestInfo) {
MOZ_ASSERT(item->IsHitTestItem());
const auto& hitTestInfo = const auto& hitTestInfo =
static_cast<nsDisplayHitTestInfoItem*>(item)->GetHitTestInfo(); static_cast<nsDisplayHitTestInfoItem*>(item)->GetHitTestInfo();

Просмотреть файл

@ -3874,8 +3874,8 @@ struct HitTestInfo {
nsRect mArea; nsRect mArea;
mozilla::gfx::CompositorHitTestInfo mFlags; mozilla::gfx::CompositorHitTestInfo mFlags;
AnimatedGeometryRoot* mAGR; RefPtr<AnimatedGeometryRoot> mAGR;
const mozilla::ActiveScrolledRoot* mASR; RefPtr<const mozilla::ActiveScrolledRoot> mASR;
RefPtr<const mozilla::DisplayItemClipChain> mClipChain; RefPtr<const mozilla::DisplayItemClipChain> mClipChain;
const mozilla::DisplayItemClip* mClip; const mozilla::DisplayItemClip* mClip;
}; };
@ -3893,7 +3893,10 @@ class nsDisplayHitTestInfoItem : public nsPaintedDisplayItem {
const nsDisplayHitTestInfoItem& aOther) const nsDisplayHitTestInfoItem& aOther)
: nsPaintedDisplayItem(aBuilder, aOther) {} : nsPaintedDisplayItem(aBuilder, aOther) {}
const HitTestInfo& GetHitTestInfo() const { return *mHitTestInfo; } const HitTestInfo& GetHitTestInfo() const {
MOZ_ASSERT(HasHitTestInfo());
return *mHitTestInfo;
}
void SetActiveScrolledRoot( void SetActiveScrolledRoot(
const ActiveScrolledRoot* aActiveScrolledRoot) override { const ActiveScrolledRoot* aActiveScrolledRoot) override {

Просмотреть файл

@ -456,7 +456,9 @@ this.tabs = class extends ExtensionAPI {
queryInfo = Object.assign({}, queryInfo); queryInfo = Object.assign({}, queryInfo);
if (queryInfo.url !== null) { if (queryInfo.url !== null) {
queryInfo.url = new MatchPatternSet([].concat(queryInfo.url)); queryInfo.url = new MatchPatternSet([].concat(queryInfo.url), {
restrictSchemes: false,
});
} }
if (queryInfo.title !== null) { if (queryInfo.title !== null) {
queryInfo.title = new MatchGlob(queryInfo.title); queryInfo.title = new MatchGlob(queryInfo.title);

Просмотреть файл

@ -1240,4 +1240,41 @@ class NavigationDelegateTest : BaseSessionTest() {
mainSession.loadTestPath(HELLO_HTML_PATH) mainSession.loadTestPath(HELLO_HTML_PATH)
sessionRule.waitForPageStop() sessionRule.waitForPageStop()
} }
@Test fun setLocationHash() {
sessionRule.session.loadUri("$TEST_ENDPOINT$HELLO_HTML_PATH")
sessionRule.waitForPageStop()
sessionRule.session.evaluateJS("location.hash = 'test1';")
sessionRule.session.waitUntilCalled(object : Callbacks.NavigationDelegate {
@AssertCalled(count = 0)
override fun onLoadRequest(session: GeckoSession,
request: LoadRequest):
GeckoResult<AllowOrDeny>? {
return null
}
@AssertCalled(count = 1)
override fun onLocationChange(session: GeckoSession, url: String?) {
assertThat("URI should match", url, endsWith("#test1"))
}
})
sessionRule.session.evaluateJS("location.hash = 'test2';")
sessionRule.session.waitUntilCalled(object : Callbacks.NavigationDelegate {
@AssertCalled(count = 0)
override fun onLoadRequest(session: GeckoSession,
request: LoadRequest):
GeckoResult<AllowOrDeny>? {
return null
}
@AssertCalled(count = 1)
override fun onLocationChange(session: GeckoSession, url: String?) {
assertThat("URI should match", url, endsWith("#test2"))
}
})
}
} }

Просмотреть файл

@ -83,6 +83,7 @@ skip-if = verify
[test_1503201.html] [test_1503201.html]
[test_origin_header.html] [test_origin_header.html]
[test_1502055.html] [test_1502055.html]
skip-if = fission # Timeouts
support-files = sw_1502055.js file_1502055.sjs iframe_1502055.html support-files = sw_1502055.js file_1502055.sjs iframe_1502055.html
[test_accept_header.html] [test_accept_header.html]
support-files = test_accept_header.sjs support-files = test_accept_header.sjs

Просмотреть файл

@ -221,3 +221,45 @@ rustfmt:
when: when:
files-changed: files-changed:
- '**/*.rs' - '**/*.rs'
file-whitespace:
description: Check for trailing whitespaces and Windows CR
platform: lint/opt
treeherder:
symbol: file-whitespace
run:
mach: lint -l file-whitespace -f treeherder -f json:/builds/worker/mozlint.json
when:
files-changed:
- '**/*.c'
- '**/*.cc'
- '**/*.cpp'
- '**/*.h'
- '**/*.py'
- '**/*.rs'
file-perm:
description: Check for incorrect permissions on source files
platform: lint/opt
treeherder:
symbol: file-perm
run:
mach: lint -l file-perm -f treeherder -f json:/builds/worker/mozlint.json
when:
files-changed:
- '**/*.c'
- '**/*.cc'
- '**/*.cpp'
- '**/*.h'
- '**/*.html'
- '**/*.js'
- '**/*.jsm'
- '**/*.jsx'
- '**/*.m'
- '**/*.mm'
- '**/*.rs'
- '**/*.xhtml'
- '**/*.xml'
- '**/*.xul'

Просмотреть файл

@ -238,7 +238,8 @@ def use_fetches(config, jobs):
extract = artifact.get('extract', True) extract = artifact.get('extract', True)
fetch = { fetch = {
'artifact': '{prefix}/{path}'.format(prefix=prefix, path=path), 'artifact': '{prefix}/{path}'.format(prefix=prefix, path=path)
if not path.startswith('/') else path[1:],
'task': '<{dep}>'.format(dep=kind), 'task': '<{dep}>'.format(dep=kind),
'extract': extract, 'extract': extract,
} }

Просмотреть файл

@ -0,0 +1,2 @@
[multicol-breaking-005.html]
prefs: [layout.css.column-span.enabled:true]

Просмотреть файл

@ -0,0 +1,2 @@
[multicol-breaking-nobackground-005.html]
prefs: [layout.css.column-span.enabled:true]

Просмотреть файл

@ -0,0 +1,100 @@
<!DOCTYPE HTML>
<title>CSS Test Reference: breaking of a multicolumn</title>
<meta charset="utf-8">
<link rel="author" title="L. David Baron" href="https://dbaron.org/">
<link rel="author" title="Ting-Yu Lin" href="tlin@mozilla.com">
<link rel="author" title="Mozilla" href="https://mozilla.org/">
<style>
.outer {
height: 200px;
width: 800px;
background: rgba(0, 0, 255, 0.3);
position: relative;
}
.blueborders {
position: absolute;
top: 0;
left: 262px; /* 256px first column + (16px gap - 4px rule) / 2 */
width: 268px; /* 256px second column + (16px gap - 4px rule) */
height: 200px;
border-right: blue solid 4px;
border-left: blue solid 4px;
}
.innerbg {
height: 100px;
width: 256px;
background: rgba(255, 0, 255, 0.3);
position: absolute;
top: 0;
}
.inner {
height: 100px;
width: 120px;
font: 16px/1.25 sans-serif;
position: absolute;
top: 0;
}
.lefthalf {
border-right: 2px solid fuchsia;
padding-right: 7px;
}
.righthalf {
padding-left: 7px;
}
</style>
<div class="outer">
<div class="blueborders"></div>
<div class="innerbg" style="left: 0"></div>
<div class="inner lefthalf" style="left: 0">
AAAAA<br>
BBBBB<br>
CCCCC<br>
DDDDD<br>
EEEEE
</div>
<div class="inner righthalf" style="left: 129px">
FFFFF<br>
GGGGG<br>
HHHHH<br>
IIIII<br>
JJJJJ
</div>
<div class="innerbg" style="left: 272px"></div>
<div class="inner lefthalf" style="left: 272px">
KKKKK<br>
LLLLL<br>
MMMMM<br>
NNNNN<br>
OOOOO
</div>
<div class="inner righthalf" style="left: 401px">
PPPPP<br>
QQQQQ<br>
RRRRR<br>
SSSSS<br>
TTTTT
</div>
<div class="innerbg" style="left: 544px"></div>
<div class="inner lefthalf" style="left: 544px">
UUUUU<br>
VVVVV<br>
WWWWW<br>
XXXXX<br>
YYYYY
</div>
<div class="inner righthalf" style="left: 673px">
ZZZZZ<br>
aaaaa<br>
bbbbb<br>
ccccc<br>
ddddd
</div>
</div>

Просмотреть файл

@ -0,0 +1,70 @@
<!DOCTYPE HTML>
<title>CSS Test: breaking of a multicolumn</title>
<meta charset="utf-8">
<link rel="author" title="L. David Baron" href="https://dbaron.org/">
<link rel="author" title="Ting-Yu Lin" href="tlin@mozilla.com">
<link rel="author" title="Mozilla" href="https://mozilla.org/">
<link rel="help" href="https://drafts.csswg.org/css-multicol/#column-gaps-and-rules">
<link rel="help" href="https://drafts.csswg.org/css-multicol/#cf">
<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/2309">
<link rel="match" href="multicol-breaking-005-ref.html">
<style>
.outer {
height: 200px;
width: 800px;
column-fill: balance;
column-count: 3;
column-rule: 4px solid blue;
column-gap: 16px;
background: rgba(0, 0, 255, 0.3);
}
.inner {
column-count: 2;
column-fill: balance;
column-rule: 2px solid fuchsia;
column-gap: 16px;
background: rgba(255, 0, 255, 0.3);
font: 16px/1.25 sans-serif;
}
</style>
<!-- This test is similar to multicol-breaking-002.html,
but both outer and inner columns are balancing. The outer multi-column is
made explicitly taller than the inner columns' optimal balance height. -->
<div class="outer">
<div class="inner" style="height: 300px">
AAAAA<br>
BBBBB<br>
CCCCC<br>
DDDDD<br>
EEEEE<br>
FFFFF<br>
GGGGG<br>
HHHHH<br>
IIIII<br>
JJJJJ<br>
KKKKK<br>
LLLLL<br>
MMMMM<br>
NNNNN<br>
OOOOO<br>
PPPPP<br>
QQQQQ<br>
RRRRR<br>
SSSSS<br>
TTTTT<br>
UUUUU<br>
VVVVV<br>
WWWWW<br>
XXXXX<br>
YYYYY<br>
ZZZZZ<br>
aaaaa<br>
bbbbb<br>
ccccc<br>
ddddd
</div>
</div>

Просмотреть файл

@ -0,0 +1,86 @@
<!DOCTYPE HTML>
<title>CSS Test Reference: breaking of a multicolumn</title>
<meta charset="utf-8">
<link rel="author" title="L. David Baron" href="https://dbaron.org/">
<link rel="author" title="Ting-Yu Lin" href="tlin@mozilla.com">
<link rel="author" title="Mozilla" href="https://mozilla.org/">
<style>
.outer {
height: 200px;
width: 800px;
background: rgba(0, 0, 255, 0.3);
position: relative;
}
.innerbg {
height: 100px;
width: 256px;
background: rgba(255, 0, 255, 0.3);
position: absolute;
top: 0;
}
.inner {
height: 100px;
width: 120px;
font: 16px/1.25 sans-serif;
position: absolute;
top: 0;
}
.lefthalf {
border-right: 2px solid fuchsia;
padding-right: 7px;
}
.righthalf {
padding-left: 7px;
}
</style>
<div class="outer">
<div class="inner lefthalf" style="left: 0">
AAAAA<br>
BBBBB<br>
CCCCC<br>
DDDDD<br>
EEEEE
</div>
<div class="inner righthalf" style="left: 129px">
FFFFF<br>
GGGGG<br>
HHHHH<br>
IIIII<br>
JJJJJ
</div>
<div class="inner lefthalf" style="left: 272px">
KKKKK<br>
LLLLL<br>
MMMMM<br>
NNNNN<br>
OOOOO
</div>
<div class="inner righthalf" style="left: 401px">
PPPPP<br>
QQQQQ<br>
RRRRR<br>
SSSSS<br>
TTTTT
</div>
<div class="inner lefthalf" style="left: 544px">
UUUUU<br>
VVVVV<br>
WWWWW<br>
XXXXX<br>
YYYYY
</div>
<div class="inner righthalf" style="left: 673px">
ZZZZZ<br>
aaaaa<br>
bbbbb<br>
ccccc<br>
ddddd
</div>
</div>

Просмотреть файл

@ -0,0 +1,68 @@
<!DOCTYPE HTML>
<title>CSS Test: breaking of a multicolumn</title>
<meta charset="utf-8">
<link rel="author" title="L. David Baron" href="https://dbaron.org/">
<link rel="author" title="Ting-Yu Lin" href="tlin@mozilla.com">
<link rel="author" title="Mozilla" href="https://mozilla.org/">
<link rel="help" href="https://drafts.csswg.org/css-multicol/#column-gaps-and-rules">
<link rel="help" href="https://drafts.csswg.org/css-multicol/#cf">
<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/2309">
<link rel="match" href="multicol-breaking-nobackground-005-ref.html">
<style>
.outer {
height: 200px;
width: 800px;
column-fill: balance;
column-count: 3;
column-gap: 16px;
background: rgba(0, 0, 255, 0.3);
}
.inner {
column-count: 2;
column-fill: balance;
column-rule: 2px solid fuchsia;
column-gap: 16px;
font: 16px/1.25 sans-serif;
}
</style>
<!-- This test is similar to multicol-breaking-nobackground-002.html,
but both outer and inner columns are balancing. The outer multi-column is
made explicitly taller than the inner columns' optimal balance height. -->
<div class="outer">
<div class="inner" style="height: 300px">
AAAAA<br>
BBBBB<br>
CCCCC<br>
DDDDD<br>
EEEEE<br>
FFFFF<br>
GGGGG<br>
HHHHH<br>
IIIII<br>
JJJJJ<br>
KKKKK<br>
LLLLL<br>
MMMMM<br>
NNNNN<br>
OOOOO<br>
PPPPP<br>
QQQQQ<br>
RRRRR<br>
SSSSS<br>
TTTTT<br>
UUUUU<br>
VVVVV<br>
WWWWW<br>
XXXXX<br>
YYYYY<br>
ZZZZZ<br>
aaaaa<br>
bbbbb<br>
ccccc<br>
ddddd
</div>
</div>

Просмотреть файл

@ -1 +1 @@
{"files":{"CODE_OF_CONDUCT.md":"e85149c44f478f164f7d5f55f6e66c9b5ae236d4a11107d5e2a93fe71dd874b9","Cargo.toml":"cfc0416b0a1c11ade3b5c11ec579c8e26ed3fc3b5871dd99d4fbcc12bd2614d0","LICENSE":"c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4","README.md":"303ea5ec53d4e86f2c321056e8158e31aa061353a99e52de3d76859d40919efc","src/driver.rs":"913de08a578b38902f4eb0d78147289897af5d3b1ecdad818c4ea6f83da6c714","src/error.rs":"d4ef0cba5c7fc54959ed62da166f10435548d705e0a817eed449fb001fe4e21d","src/guid.rs":"c82af64fba3ad87948a9b599241e48753d17587e8c642f610949163be3d499bf","src/lib.rs":"0606e69b235650bf404ae0b03a1e85c2063bb4b7147fa4d5e8ff2c128a757453","src/merge.rs":"e74727171831585d304eee3a3c7ba24fec52a5e7c6999ed4e647fefa14b8be99","src/store.rs":"629410e44485c0473617911be0e06dc5ce504c7427782be02f05a2f4096b5351","src/tests.rs":"51bc77eb989974f7594dfa0cdf7741f8e26f2956eebc34d1f71cbfd137512940","src/tree.rs":"fcdc9a5ae0e3f1b0d62d01bf1024db2a0aa8660e6839ada607a6a20e0fe2ad83"},"package":"251a15c9a597d70eb53cbb0c5473d8d8c6241aef615c092030ebab27fb5b26ef"} {"files":{"CODE_OF_CONDUCT.md":"e85149c44f478f164f7d5f55f6e66c9b5ae236d4a11107d5e2a93fe71dd874b9","Cargo.toml":"9c145c9ecdad0143f95fb00d5646fb3f46203779a201f2f2389961563ca37397","LICENSE":"c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4","README.md":"303ea5ec53d4e86f2c321056e8158e31aa061353a99e52de3d76859d40919efc","src/driver.rs":"913de08a578b38902f4eb0d78147289897af5d3b1ecdad818c4ea6f83da6c714","src/error.rs":"d4ef0cba5c7fc54959ed62da166f10435548d705e0a817eed449fb001fe4e21d","src/guid.rs":"c82af64fba3ad87948a9b599241e48753d17587e8c642f610949163be3d499bf","src/lib.rs":"0606e69b235650bf404ae0b03a1e85c2063bb4b7147fa4d5e8ff2c128a757453","src/merge.rs":"bfc83aa6f42c196a5c6c75e095d1e44470198a38f3a62a6537cd5854d51208cd","src/store.rs":"629410e44485c0473617911be0e06dc5ce504c7427782be02f05a2f4096b5351","src/tests.rs":"fd2f03fd47e02459b7a3c7f799896be71536054184a2eca7e30cdbe817da0a97","src/tree.rs":"30c7d0c80f180936d1f99d2a3fbe9add36f3fe36a64998e3176d0242f425c488"},"package":"57cd6ee785daa898686f3e2fb4a2b1ce490fcd6d69665c857d16fb61b48f4aae"}

2
third_party/rust/dogear/Cargo.toml поставляемый
Просмотреть файл

@ -13,7 +13,7 @@
[package] [package]
edition = "2018" edition = "2018"
name = "dogear" name = "dogear"
version = "0.3.1" version = "0.3.3"
authors = ["Lina Cambridge <lina@mozilla.com>"] authors = ["Lina Cambridge <lina@mozilla.com>"]
exclude = ["/.travis/**", ".travis.yml", "/docs/**", "book.toml"] exclude = ["/.travis/**", ".travis.yml", "/docs/**", "book.toml"]
description = "A library for merging bookmark trees." description = "A library for merging bookmark trees."

150
third_party/rust/dogear/src/merge.rs поставляемый
Просмотреть файл

@ -1528,47 +1528,44 @@ impl<'t, D: Driver, A: AbortSignal> Merger<'t, D, A> {
for (local_position, local_child_node) in local_parent_node.children().enumerate() { for (local_position, local_child_node) in local_parent_node.children().enumerate() {
self.signal.err_if_aborted()?; self.signal.err_if_aborted()?;
if local_child_node.is_built_in_root() { if local_child_node.is_built_in_root() {
continue;
}
if let Some(local_child_content) = local_child_node.content() {
if let Some(remote_child_node) =
self.remote_tree.node_for_guid(&local_child_node.guid)
{
trace!(
self.driver,
"Not deduping local child {}; already exists remotely as {}",
local_child_node,
remote_child_node
);
continue;
}
if self.remote_tree.is_deleted(&local_child_node.guid) {
trace!(
self.driver,
"Not deduping local child {}; deleted remotely",
local_child_node
);
continue;
}
// Store matching local children in an array, in case multiple children
// have the same dupe key (for example, a toolbar containing multiple
// empty folders, as in bug 1213369).
let dupe_key = match local_child_content {
Content::Bookmark { .. } | Content::Folder { .. } => {
DupeKey::WithoutPosition(local_child_content)
}
Content::Separator => {
DupeKey::WithPosition(local_child_content, local_position)
}
};
let local_nodes_for_key = dupe_key_to_local_nodes.entry(dupe_key).or_default();
local_nodes_for_key.push_back(local_child_node);
} else {
trace!( trace!(
self.driver, self.driver,
"Not deduping local child {}; already uploaded", "Not deduping local built-in root {}",
local_child_node local_child_node
); );
continue;
}
if self.remote_tree.mentions(&local_child_node.guid) {
trace!(
self.driver,
"Not deduping local child {}; already deleted or exists remotely",
local_child_node
);
continue;
}
match local_child_node.content() {
Some(local_child_content) => {
// Store matching local children in an array, in case multiple children
// have the same dupe key (for example, a toolbar containing multiple
// empty folders, as in bug 1213369).
let dupe_key = match local_child_content {
Content::Bookmark { .. } | Content::Folder { .. } => {
DupeKey::WithoutPosition(local_child_content)
}
Content::Separator => {
DupeKey::WithPosition(local_child_content, local_position)
}
};
let local_nodes_for_key = dupe_key_to_local_nodes.entry(dupe_key).or_default();
local_nodes_for_key.push_back(local_child_node);
}
None => {
trace!(
self.driver,
"Not deduping local child {} without content info",
local_child_node
);
}
} }
} }
@ -1577,6 +1574,22 @@ impl<'t, D: Driver, A: AbortSignal> Merger<'t, D, A> {
for (remote_position, remote_child_node) in remote_parent_node.children().enumerate() { for (remote_position, remote_child_node) in remote_parent_node.children().enumerate() {
self.signal.err_if_aborted()?; self.signal.err_if_aborted()?;
if remote_child_node.is_built_in_root() {
trace!(
self.driver,
"Not deduping remote built-in root {}",
remote_child_node
);
continue;
}
if self.local_tree.mentions(&remote_child_node.guid) {
trace!(
self.driver,
"Not deduping remote child {}; already deleted or exists locally",
remote_child_node
);
continue;
}
if remote_to_local.contains_key(&remote_child_node.guid) { if remote_to_local.contains_key(&remote_child_node.guid) {
trace!( trace!(
self.driver, self.driver,
@ -1588,47 +1601,52 @@ impl<'t, D: Driver, A: AbortSignal> Merger<'t, D, A> {
// Note that we don't need to check if the remote node is deleted // Note that we don't need to check if the remote node is deleted
// locally, because it wouldn't have local content entries if it // locally, because it wouldn't have local content entries if it
// were. // were.
if let Some(remote_child_content) = remote_child_node.content() { match remote_child_node.content() {
let dupe_key = match remote_child_content { Some(remote_child_content) => {
Content::Bookmark { .. } | Content::Folder { .. } => { let dupe_key = match remote_child_content {
DupeKey::WithoutPosition(remote_child_content) Content::Bookmark { .. } | Content::Folder { .. } => {
} DupeKey::WithoutPosition(remote_child_content)
Content::Separator => { }
DupeKey::WithPosition(remote_child_content, remote_position) Content::Separator => {
} DupeKey::WithPosition(remote_child_content, remote_position)
}; }
if let Some(local_nodes_for_key) = dupe_key_to_local_nodes.get_mut(&dupe_key) { };
if let Some(local_child_node) = local_nodes_for_key.pop_front() { if let Some(local_nodes_for_key) = dupe_key_to_local_nodes.get_mut(&dupe_key) {
trace!( if let Some(local_child_node) = local_nodes_for_key.pop_front() {
self.driver, trace!(
"Deduping local child {} to remote child {}", self.driver,
local_child_node, "Deduping local child {} to remote child {}",
remote_child_node local_child_node,
); remote_child_node
local_to_remote.insert(local_child_node.guid.clone(), remote_child_node); );
remote_to_local.insert(remote_child_node.guid.clone(), local_child_node); local_to_remote
.insert(local_child_node.guid.clone(), remote_child_node);
remote_to_local
.insert(remote_child_node.guid.clone(), local_child_node);
} else {
trace!(
self.driver,
"Not deduping remote child {}; no remaining local content matches",
remote_child_node
);
continue;
}
} else { } else {
trace!( trace!(
self.driver, self.driver,
"Not deduping remote child {}; no remaining local content matches", "Not deduping remote child {}; no local content matches",
remote_child_node remote_child_node
); );
continue; continue;
} }
} else { }
None => {
trace!( trace!(
self.driver, self.driver,
"Not deduping remote child {}; no local content matches", "Not deduping remote child {} without content info",
remote_child_node remote_child_node
); );
continue;
} }
} else {
trace!(
self.driver,
"Not deduping remote child {}; already merged",
remote_child_node
);
} }
} }

78
third_party/rust/dogear/src/tests.rs поставляемый
Просмотреть файл

@ -60,7 +60,7 @@ impl TryFrom<Node> for Builder {
_ => return Err(err), _ => return Err(err),
} }
} }
b.mutate(&guid).by_structure(&parent_guid)?; b.parent_for(&guid).by_structure(&parent_guid)?;
for child in node.children { for child in node.children {
inflate(b, &guid, child)?; inflate(b, &guid, child)?;
} }
@ -1323,6 +1323,82 @@ fn newer_move_to_deleted() {
assert_eq!(merged_root.counts(), &expected_telem); assert_eq!(merged_root.counts(), &expected_telem);
} }
#[test]
fn deduping_multiple_candidates() {
before_each();
let mut local_tree_builder = Builder::try_from(nodes!({
("menu________", Folder[needs_merge = true, age = 5], {
("folderAAAAA1", Folder[needs_merge = true, age = 5]),
("folderAAAAA2", Folder[needs_merge = true, age = 5])
}),
("toolbar_____", Folder[needs_merge = true], {
("folderBBBBB1", Folder[needs_merge = true])
})
}))
.unwrap();
local_tree_builder
.mutate(&"folderAAAAA1".into())
.content(Content::Folder { title: "A".into() });
local_tree_builder
.mutate(&"folderAAAAA2".into())
.content(Content::Folder { title: "A".into() });
local_tree_builder
.mutate(&"folderBBBBB1".into())
.content(Content::Folder { title: "B".into() });
let local_tree = local_tree_builder.into_tree().unwrap();
let mut remote_tree_builder = Builder::try_from(nodes!({
("menu________", Folder[needs_merge = true], {
("folderAAAAA1", Folder[needs_merge = true])
}),
("toolbar_____", Folder[needs_merge = true, age = 5], {
("folderBBBBB1", Folder[needs_merge = true, age = 5]),
("folderBBBBB2", Folder[needs_merge = true, age = 5])
})
}))
.unwrap();
remote_tree_builder
.mutate(&"folderAAAAA1".into())
.content(Content::Folder { title: "A".into() });
remote_tree_builder
.mutate(&"folderBBBBB1".into())
.content(Content::Folder { title: "B".into() });
remote_tree_builder
.mutate(&"folderBBBBB2".into())
.content(Content::Folder { title: "B".into() });
let remote_tree = remote_tree_builder.into_tree().unwrap();
let merger = Merger::new(&local_tree, &remote_tree);
let merged_root = merger.merge().unwrap();
let expected_tree = merged_nodes!({
("menu________", LocalWithNewLocalStructure, {
("folderAAAAA1", Remote),
("folderAAAAA2", Local)
}),
("toolbar_____", LocalWithNewLocalStructure, {
("folderBBBBB1", Local),
("folderBBBBB2", Remote)
})
});
let expected_telem = StructureCounts {
remote_revives: 0,
local_deletes: 0,
local_revives: 0,
remote_deletes: 0,
dupes: 0,
merged_nodes: 6,
merged_deletions: 0,
};
assert_eq!(&expected_tree, merged_root.node());
assert_eq!(merged_root.deletions().count(), 0);
assert_eq!(merged_root.counts(), &expected_telem);
}
#[test] #[test]
fn deduping_local_newer() { fn deduping_local_newer() {
before_each(); before_each();

98
third_party/rust/dogear/src/tree.rs поставляемый
Просмотреть файл

@ -499,52 +499,10 @@ impl<'b> ItemBuilder<'b> {
b.by_parent_guid(parent_guid) b.by_parent_guid(parent_guid)
} }
/// Records a `parent_guid` from a valid tree structure. This is for #[inline]
/// callers who already know their structure is consistent, like
/// `Store::fetch_local_tree()` on Desktop, and
/// `std::convert::TryInto<Tree>` in the tests.
///
/// Both the item and `parent_guid` must exist, and the `parent_guid` must
/// refer to a folder.
///
/// `by_structure(parent_guid)` is logically the same as:
///
/// ```no_run
/// # use dogear::{Item, Kind, Result, ROOT_GUID, Tree};
/// # fn main() -> Result<()> {
/// # let mut builder = Tree::with_root(Item::new(ROOT_GUID, Kind::Folder));
/// # let child_guid = "bookmarkAAAA".into();
/// # let parent_guid = "folderAAAAAA".into();
/// builder.parent_for(&child_guid)
/// .by_children(&parent_guid)?
/// .parent_for(&child_guid)
/// .by_parent_guid(parent_guid)?;
/// # Ok(())
/// # }
/// ```
///
/// ...But more convenient. It's also more efficient, because it avoids
/// multiple lookups for the item and parent, as well as an extra heap
/// allocation to store the parents.
pub fn by_structure(self, parent_guid: &Guid) -> Result<&'b mut Builder> { pub fn by_structure(self, parent_guid: &Guid) -> Result<&'b mut Builder> {
let parent_index = match self.0.entry_index_by_guid.get(parent_guid) { let b = ParentBuilder(self.0, BuilderEntryChild::Exists(self.1));
Some(&parent_index) if self.0.entries[parent_index].item.is_folder() => parent_index, b.by_structure(parent_guid)
_ => {
return Err(ErrorKind::InvalidParent(
self.0.entries[self.1].item.guid.clone(),
parent_guid.clone(),
)
.into());
}
};
self.0.entries[self.1].parents_by(&[
BuilderParentBy::Children(parent_index),
BuilderParentBy::KnownItem(parent_index),
])?;
self.0.entries[parent_index]
.children
.push(BuilderEntryChild::Exists(self.1));
Ok(self.0)
} }
} }
@ -593,6 +551,56 @@ impl<'b> ParentBuilder<'b> {
} }
Ok(self.0) Ok(self.0)
} }
/// Records a `parent_guid` from a valid tree structure. This is for
/// callers who already know their structure is consistent, like
/// `Store::fetch_local_tree()` on Desktop, and
/// `std::convert::TryInto<Tree>` in the tests.
///
/// Both the item and `parent_guid` must exist, and the `parent_guid` must
/// refer to a folder.
///
/// `by_structure(parent_guid)` is logically the same as:
///
/// ```no_run
/// # use dogear::{Item, Kind, Result, ROOT_GUID, Tree};
/// # fn main() -> Result<()> {
/// # let mut builder = Tree::with_root(Item::new(ROOT_GUID, Kind::Folder));
/// # let child_guid = "bookmarkAAAA".into();
/// # let parent_guid = "folderAAAAAA".into();
/// builder.parent_for(&child_guid)
/// .by_children(&parent_guid)?
/// .parent_for(&child_guid)
/// .by_parent_guid(parent_guid)?;
/// # Ok(())
/// # }
/// ```
///
/// ...But more convenient. It's also more efficient, because it avoids
/// multiple lookups for the item and parent, as well as an extra heap
/// allocation to store the parents.
pub fn by_structure(self, parent_guid: &Guid) -> Result<&'b mut Builder> {
let parent_index = match self.0.entry_index_by_guid.get(parent_guid) {
Some(&parent_index) if self.0.entries[parent_index].item.is_folder() => parent_index,
_ => {
let child_guid = match &self.1 {
BuilderEntryChild::Exists(index) => &self.0.entries[*index].item.guid,
BuilderEntryChild::Missing(guid) => guid,
};
return Err(
ErrorKind::InvalidParent(child_guid.clone(), parent_guid.clone()).into(),
);
}
};
if let BuilderEntryChild::Exists(child_index) = &self.1 {
self.0.entries[*child_index].parents_by(&[
BuilderParentBy::Children(parent_index),
BuilderParentBy::KnownItem(parent_index),
])?;
}
self.0.entries[parent_index].children.push(self.1);
Ok(self.0)
}
} }
/// An entry wraps a tree item with references to its parents and children, /// An entry wraps a tree item with references to its parents and children,

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше