зеркало из https://github.com/mozilla/gecko-dev.git
Merge autoland to mozilla-central. a=merge
This commit is contained in:
Коммит
786d0c66bc
|
@ -385,7 +385,7 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"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)",
|
||||
"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)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"moz_task 0.1.0",
|
||||
|
@ -956,7 +956,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "dogear"
|
||||
version = "0.3.1"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"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 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 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-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"
|
||||
|
|
|
@ -112,6 +112,7 @@ support-files =
|
|||
test_no_mcb_on_http_site_font2.html
|
||||
test_no_mcb_on_http_site_font2.css
|
||||
[browser_no_mcb_for_loopback.js]
|
||||
skip-if = fission # Timeouts
|
||||
tags = mcb
|
||||
support-files =
|
||||
../general/moz.png
|
||||
|
|
|
@ -3,8 +3,9 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
body {
|
||||
--sidebar-width: 320px;
|
||||
display: grid;
|
||||
grid-template-columns: 320px 1fr;
|
||||
grid-template-columns: var(--sidebar-width) 1fr;
|
||||
grid-template-rows: 75px 1fr;
|
||||
grid-template-areas: "header header"
|
||||
"logins login";
|
||||
|
@ -17,12 +18,13 @@ header {
|
|||
align-items: center;
|
||||
background-color: var(--in-content-box-background);
|
||||
border-bottom: 1px solid var(--in-content-box-border-color);
|
||||
padding-inline: 60px 23px;
|
||||
padding-inline-end: 23px;
|
||||
}
|
||||
|
||||
login-filter {
|
||||
max-width: 30%;
|
||||
margin: auto;
|
||||
min-width: 320px;
|
||||
max-width: 400px;
|
||||
margin-inline: 40px auto;
|
||||
flex-grow: 1;
|
||||
align-self: center;
|
||||
}
|
||||
|
@ -52,8 +54,9 @@ login-item {
|
|||
}
|
||||
|
||||
#branding-logo {
|
||||
flex-basis: var(--sidebar-width);
|
||||
flex-shrink: 0;
|
||||
height: 32px;
|
||||
margin-inline-end: 18px;
|
||||
-moz-context-properties: fill;
|
||||
fill: #20123a;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,9 @@
|
|||
|
||||
.fxaccounts-avatar-button {
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.fxaccount-email {
|
||||
|
|
|
@ -978,6 +978,12 @@ var Policies = {
|
|||
},
|
||||
},
|
||||
|
||||
OfferToSaveLoginsDefault: {
|
||||
onBeforeUIStartup(manager, param) {
|
||||
setDefaultPref("signon.rememberSignons", param);
|
||||
},
|
||||
},
|
||||
|
||||
OverrideFirstRunPage: {
|
||||
onProfileAfterChange(manager, param) {
|
||||
let url = param ? param.href : "";
|
||||
|
|
|
@ -497,6 +497,10 @@
|
|||
"type": "boolean"
|
||||
},
|
||||
|
||||
"OfferToSaveLoginsDefault": {
|
||||
"type": "boolean"
|
||||
},
|
||||
|
||||
"OverrideFirstRunPage": {
|
||||
"type": "URLorEmpty"
|
||||
},
|
||||
|
|
|
@ -456,6 +456,16 @@ const POLICIES_TESTS = [
|
|||
"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() {
|
||||
|
|
|
@ -205,7 +205,9 @@ class TabsUpdateFilterEventManager extends EventManager {
|
|||
let register = (fire, filterProps) => {
|
||||
let filter = { ...filterProps };
|
||||
if (filter.urls) {
|
||||
filter.urls = new MatchPatternSet(filter.urls);
|
||||
filter.urls = new MatchPatternSet(filter.urls, {
|
||||
restrictSchemes: false,
|
||||
});
|
||||
}
|
||||
let needsModified = true;
|
||||
if (filter.properties) {
|
||||
|
@ -944,7 +946,9 @@ this.tabs = class extends ExtensionAPI {
|
|||
queryInfo = Object.assign({}, queryInfo);
|
||||
|
||||
if (queryInfo.url !== null) {
|
||||
queryInfo.url = new MatchPatternSet([].concat(queryInfo.url));
|
||||
queryInfo.url = new MatchPatternSet([].concat(queryInfo.url), {
|
||||
restrictSchemes: false,
|
||||
});
|
||||
}
|
||||
if (queryInfo.title !== null) {
|
||||
queryInfo.title = new MatchGlob(queryInfo.title);
|
||||
|
|
|
@ -164,6 +164,7 @@ skip-if = (verify && debug && (os == 'mac'))
|
|||
[browser_ext_pageAction_simple.js]
|
||||
[browser_ext_pageAction_telemetry.js]
|
||||
[browser_ext_pageAction_title.js]
|
||||
skip-if = fission # Timeouts Bug 1574926
|
||||
[browser_ext_popup_api_injection.js]
|
||||
[browser_ext_popup_background.js]
|
||||
[browser_ext_popup_corners.js]
|
||||
|
|
|
@ -21,12 +21,8 @@ add_task(async function() {
|
|||
permissions: ["tabs"],
|
||||
},
|
||||
|
||||
background: function() {
|
||||
browser.tabs.query(
|
||||
{
|
||||
lastFocusedWindow: true,
|
||||
},
|
||||
function(tabs) {
|
||||
async background() {
|
||||
let tabs = await browser.tabs.query({ lastFocusedWindow: true });
|
||||
browser.test.assertEq(tabs.length, 3, "should have three tabs");
|
||||
|
||||
tabs.sort((tab1, tab2) => tab1.index - tab2.index);
|
||||
|
@ -40,27 +36,11 @@ add_task(async function() {
|
|||
browser.test.assertFalse(tabs[0].pinned, "tab 0 unpinned");
|
||||
browser.test.assertFalse(tabs[1].pinned, "tab 1 unpinned");
|
||||
|
||||
browser.test.assertEq(
|
||||
tabs[0].url,
|
||||
"about:robots",
|
||||
"tab 0 url correct"
|
||||
);
|
||||
browser.test.assertEq(
|
||||
tabs[1].url,
|
||||
"about:config",
|
||||
"tab 1 url correct"
|
||||
);
|
||||
browser.test.assertEq(tabs[0].url, "about:robots", "tab 0 url correct");
|
||||
browser.test.assertEq(tabs[1].url, "about:config", "tab 1 url correct");
|
||||
|
||||
browser.test.assertEq(
|
||||
tabs[0].status,
|
||||
"complete",
|
||||
"tab 0 status correct"
|
||||
);
|
||||
browser.test.assertEq(
|
||||
tabs[1].status,
|
||||
"complete",
|
||||
"tab 1 status correct"
|
||||
);
|
||||
browser.test.assertEq(tabs[0].status, "complete", "tab 0 status correct");
|
||||
browser.test.assertEq(tabs[1].status, "complete", "tab 1 status correct");
|
||||
|
||||
browser.test.assertEq(
|
||||
tabs[0].title,
|
||||
|
@ -68,9 +48,11 @@ add_task(async function() {
|
|||
"tab 0 title correct"
|
||||
);
|
||||
|
||||
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_dynamical_window_rounding.js]
|
||||
[browser_navigator.js]
|
||||
skip-if = fission # Timeouts
|
||||
[browser_netInfo.js]
|
||||
[browser_performanceAPI.js]
|
||||
[browser_roundedWindow_dialogWindow.js]
|
||||
|
|
|
@ -72,6 +72,7 @@ support-files =
|
|||
skip-if = (os == 'mac' && os_version == '10.14') # bug 1554807
|
||||
[browser_locationBarExternalLoad.js]
|
||||
[browser_moz_action_link.js]
|
||||
skip-if = fission # Timeouts
|
||||
[browser_new_tab_urlbar_reset.js]
|
||||
[browser_openViewOnFocus.js]
|
||||
[browser_pasteAndGo.js]
|
||||
|
|
|
@ -41,7 +41,6 @@ ac_add_options --disable-jemalloc
|
|||
ac_add_options --enable-proxy-bypass-protection
|
||||
|
||||
# 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-geckodriver # Bug 1489320
|
||||
|
||||
|
|
|
@ -41,7 +41,6 @@ ac_add_options --disable-jemalloc
|
|||
ac_add_options --enable-proxy-bypass-protection
|
||||
|
||||
# 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-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-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-OverridePostUpdatePage = Override the post-update “What’s 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
|
||||
|
||||
#wrapper-urlbar-container[place="palette"] {
|
||||
max-width: 20em;
|
||||
}
|
||||
|
||||
#pageAction-urlbar-shareURL,
|
||||
#pageAction-panel-shareURL {
|
||||
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);
|
||||
display: flex;
|
||||
flex: 1 auto;
|
||||
height: 40px; /* fixed item height to prevent flex sizing; height + 2*4px padding */
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.panel-header > label {
|
||||
flex: auto;
|
||||
font-weight: 600;
|
||||
margin: 0;
|
||||
margin: 4px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
|
|
@ -574,10 +574,6 @@ menuitem.bookmark-item {
|
|||
%include ../shared/autocomplete.inc.css
|
||||
%include ../shared/urlbar-autocomplete.inc.css
|
||||
|
||||
.urlbarView {
|
||||
font-size: 1.15em;
|
||||
}
|
||||
|
||||
#PopupAutoComplete > richlistbox > richlistitem[originaltype~="datalist-first"] {
|
||||
border-top: 1px solid ThreeDShadow;
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ Important Concepts
|
|||
sparse
|
||||
Support for projects building with GN <gn>
|
||||
telemetry
|
||||
sccache-dist
|
||||
test_certificates
|
||||
|
||||
integrated development environment (IDE)
|
||||
|
|
|
@ -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 { pauseOnExceptions } from "./pauseOnExceptions";
|
||||
export { selectFrame } from "./selectFrame";
|
||||
export { toggleSkipPausing } from "./skipPausing";
|
||||
export { toggleSkipPausing, setSkipPausing } from "./skipPausing";
|
||||
export { toggleMapScopes } from "./mapScopes";
|
||||
export { setExpandedScope } from "./expandScopes";
|
||||
export { generateInlinePreview } from "./inlinePreview";
|
||||
|
|
|
@ -18,3 +18,19 @@ export function toggleSkipPausing() {
|
|||
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: {},
|
||||
},
|
||||
clear: jest.fn(),
|
||||
features: {
|
||||
inlinePreview: true,
|
||||
},
|
||||
}));
|
||||
|
||||
import {
|
||||
|
|
|
@ -30,6 +30,10 @@ export type UIAction =
|
|||
+type: "TOGGLE_FRAMEWORK_GROUPING",
|
||||
+value: boolean,
|
||||
|}
|
||||
| {|
|
||||
+type: "TOGGLE_INLINE_PREVIEW",
|
||||
+value: boolean,
|
||||
|}
|
||||
| {|
|
||||
+type: "SHOW_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) {
|
||||
return ({ dispatch, getState }: ThunkArgs) => {
|
||||
const source = getSource(getState(), sourceId);
|
||||
|
|
|
@ -54,6 +54,7 @@ class InlinePreviews extends Component<Props> {
|
|||
return (
|
||||
<InlinePreviewRow
|
||||
editor={editor}
|
||||
key={line}
|
||||
line={lineNum}
|
||||
previews={previews[line]}
|
||||
numColumnBreakpoints={numColumnBreakpoints}
|
||||
|
|
|
@ -37,6 +37,7 @@ import {
|
|||
getCurrentThread,
|
||||
getThreadContext,
|
||||
getSkipPausing,
|
||||
getInlinePreview,
|
||||
} from "../../selectors";
|
||||
|
||||
// Redux actions
|
||||
|
@ -103,6 +104,7 @@ export type Props = {
|
|||
symbols: SymbolDeclarations,
|
||||
isPaused: boolean,
|
||||
skipPausing: boolean,
|
||||
inlinePreviewEnabled: boolean,
|
||||
|
||||
// Actions
|
||||
openConditionalPanel: typeof actions.openConditionalPanel,
|
||||
|
@ -584,6 +586,7 @@ class Editor extends PureComponent<Props, State> {
|
|||
selectedSource,
|
||||
conditionalPanelLocation,
|
||||
isPaused,
|
||||
inlinePreviewEnabled,
|
||||
} = this.props;
|
||||
const { editor, contextMenu } = this.state;
|
||||
|
||||
|
@ -611,7 +614,7 @@ class Editor extends PureComponent<Props, State> {
|
|||
{features.columnBreakpoints ? (
|
||||
<ColumnBreakpoints editor={editor} />
|
||||
) : null}
|
||||
{isPaused && features.inlinePreview ? (
|
||||
{isPaused && inlinePreviewEnabled ? (
|
||||
<InlinePreviews editor={editor} selectedSource={selectedSource} />
|
||||
) : null}
|
||||
</div>
|
||||
|
@ -665,6 +668,7 @@ const mapStateToProps = state => {
|
|||
symbols: getSymbols(state, selectedSource),
|
||||
isPaused: getIsPaused(state, getCurrentThread(state)),
|
||||
skipPausing: getSkipPausing(state),
|
||||
inlinePreviewEnabled: getInlinePreview(state),
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ import {
|
|||
} from "../../../utils/source";
|
||||
|
||||
import { downloadFile } from "../../../utils/utils";
|
||||
import { features } from "../../../utils/prefs";
|
||||
|
||||
import { isFulfilled } from "../../../utils/async-value";
|
||||
import actions from "../../../actions";
|
||||
|
@ -159,6 +160,14 @@ const downloadFileItem = (
|
|||
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({
|
||||
cx,
|
||||
editorActions,
|
||||
|
@ -218,6 +227,8 @@ export function editorMenuItems({
|
|||
);
|
||||
}
|
||||
|
||||
items.push({ type: "separator" }, inlinePreviewItem(editorActions));
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
|
@ -229,6 +240,7 @@ export type EditorItemActions = {
|
|||
jumpToMappedLocation: typeof actions.jumpToMappedLocation,
|
||||
showSource: typeof actions.showSource,
|
||||
toggleBlackBox: typeof actions.toggleBlackBox,
|
||||
toggleInlinePreview: typeof actions.toggleInlinePreview,
|
||||
};
|
||||
|
||||
export function editorItemActions(dispatch: Function) {
|
||||
|
@ -241,6 +253,7 @@ export function editorItemActions(dispatch: Function) {
|
|||
jumpToMappedLocation: actions.jumpToMappedLocation,
|
||||
showSource: actions.showSource,
|
||||
toggleBlackBox: actions.toggleBlackBox,
|
||||
toggleInlinePreview: actions.toggleInlinePreview,
|
||||
},
|
||||
dispatch
|
||||
);
|
||||
|
|
|
@ -31,6 +31,7 @@ type Props = {
|
|||
unHighlightDomElement: typeof actions.unHighlightDomElement,
|
||||
deleteBreakpoint: typeof deleteDOMMutationBreakpoint,
|
||||
toggleBreakpoint: typeof toggleDOMMutationBreakpointState,
|
||||
setSkipPausing: typeof actions.setSkipPausing,
|
||||
};
|
||||
|
||||
const localizationTerms = {
|
||||
|
@ -40,12 +41,22 @@ const localizationTerms = {
|
|||
};
|
||||
|
||||
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) {
|
||||
const {
|
||||
openElementInInspector,
|
||||
highlightDomElement,
|
||||
unHighlightDomElement,
|
||||
toggleBreakpoint,
|
||||
deleteBreakpoint,
|
||||
} = this.props;
|
||||
const { enabled, id: breakpointId, nodeFront, mutationType } = breakpoint;
|
||||
|
@ -55,7 +66,7 @@ class DOMMutationBreakpointsContents extends Component<Props> {
|
|||
<input
|
||||
type="checkbox"
|
||||
checked={enabled}
|
||||
onChange={() => toggleBreakpoint(breakpointId, !enabled)}
|
||||
onChange={() => this.handleBreakpoint(breakpointId, !enabled)}
|
||||
/>
|
||||
<div className="dom-mutation-info">
|
||||
<div className="dom-mutation-label">
|
||||
|
@ -123,6 +134,7 @@ class DomMutationBreakpoints extends Component<Props> {
|
|||
openElementInInspector={this.props.openElementInInspector}
|
||||
highlightDomElement={this.props.highlightDomElement}
|
||||
unHighlightDomElement={this.props.unHighlightDomElement}
|
||||
setSkipPausing={this.props.setSkipPausing}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -136,5 +148,6 @@ export default connect(
|
|||
openElementInInspector: actions.openElementInInspectorCommand,
|
||||
highlightDomElement: actions.highlightDomElement,
|
||||
unHighlightDomElement: actions.unHighlightDomElement,
|
||||
setSkipPausing: actions.setSkipPausing,
|
||||
}
|
||||
)(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": {
|
||||
const { skipPausing } = action;
|
||||
prefs.skipPausing = skipPausing;
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
* @module reducers/ui
|
||||
*/
|
||||
|
||||
import { prefs } from "../utils/prefs";
|
||||
import { prefs, features } from "../utils/prefs";
|
||||
|
||||
import type { Source, Range, SourceLocation } from "../types";
|
||||
|
||||
|
@ -37,6 +37,7 @@ export type UIState = {
|
|||
},
|
||||
conditionalPanelLocation: null | SourceLocation,
|
||||
isLogPoint: boolean,
|
||||
inlinePreviewEnabled: boolean,
|
||||
};
|
||||
|
||||
export const createUIState = (): UIState => ({
|
||||
|
@ -51,6 +52,7 @@ export const createUIState = (): UIState => ({
|
|||
isLogPoint: false,
|
||||
orientation: "horizontal",
|
||||
viewport: null,
|
||||
inlinePreviewEnabled: features.inlinePreview,
|
||||
});
|
||||
|
||||
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 };
|
||||
}
|
||||
|
||||
case "TOGGLE_INLINE_PREVIEW": {
|
||||
features.inlinePreview = action.value;
|
||||
return { ...state, inlinePreviewEnabled: action.value };
|
||||
}
|
||||
|
||||
case "SET_ORIENTATION": {
|
||||
return { ...state, orientation: action.orientation };
|
||||
}
|
||||
|
@ -185,4 +192,8 @@ export function getViewport(state: OuterState) {
|
|||
return state.ui.viewport;
|
||||
}
|
||||
|
||||
export function getInlinePreview(state: OuterState) {
|
||||
return state.ui.inlinePreviewEnabled;
|
||||
}
|
||||
|
||||
export default update;
|
||||
|
|
|
@ -7,6 +7,19 @@ function skipPausing(dbg) {
|
|||
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
|
||||
* invoking functions without pausing.
|
||||
|
@ -25,4 +38,14 @@ add_task(async function() {
|
|||
await reload(dbg, "simple3");
|
||||
res = await invokeInTab("simple");
|
||||
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]
|
||||
fail-if = fission
|
||||
[browser_inspector_search-05.js]
|
||||
fail-if = fission
|
||||
skip-if = fission # Timeouts
|
||||
[browser_inspector_search-06.js]
|
||||
[browser_inspector_search-07.js]
|
||||
[browser_inspector_search-08.js]
|
||||
|
|
|
@ -430,6 +430,14 @@ editor.jumpToMappedLocation1.accesskey=m
|
|||
downloadFile.label=Download file
|
||||
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
|
||||
# context menu to 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.log-points", true);
|
||||
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_bom.js]
|
||||
[browser_styleeditor_bug_740541_iframes.js]
|
||||
fail-if = fission
|
||||
skip-if = fission # Timeouts
|
||||
[browser_styleeditor_bug_851132_middle_click.js]
|
||||
[browser_styleeditor_bug_870339.js]
|
||||
[browser_styleeditor_bug_1405342_serviceworker_iframes.js]
|
||||
|
|
|
@ -18,6 +18,12 @@ loader.lazyRequireGetter(
|
|||
"BrowserConsole",
|
||||
"devtools/client/webconsole/browser-console"
|
||||
);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"PREFS",
|
||||
"devtools/client/webconsole/constants",
|
||||
true
|
||||
);
|
||||
|
||||
const BC_WINDOW_FEATURES =
|
||||
"chrome,titlebar,toolbar,centerscreen,resizable,dialog=no";
|
||||
|
@ -46,12 +52,11 @@ class BrowserConsoleManager {
|
|||
* The target that the browser console will connect to.
|
||||
* @param nsIDOMWindow iframeWindow
|
||||
* The window where the browser console UI is already loaded.
|
||||
* @param Boolean fissionSupport
|
||||
* @return object
|
||||
* A promise object for the opening of the new BrowserConsole instance.
|
||||
*/
|
||||
async openBrowserConsole(target, win, fissionSupport = false) {
|
||||
const hud = new BrowserConsole(target, win, win, fissionSupport);
|
||||
async openBrowserConsole(target, win) {
|
||||
const hud = new BrowserConsole(target, win, win);
|
||||
this._browserConsole = hud;
|
||||
hud.once("destroyed", () => {
|
||||
this._browserConsole = null;
|
||||
|
@ -73,11 +78,6 @@ class BrowserConsoleManager {
|
|||
return this._browserConsoleInitializing;
|
||||
}
|
||||
|
||||
const fissionSupport = Services.prefs.getBoolPref(
|
||||
"devtools.browsertoolbox.fission",
|
||||
false
|
||||
);
|
||||
|
||||
async function connect() {
|
||||
// The Browser console ends up using the debugger in autocomplete.
|
||||
// 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 });
|
||||
});
|
||||
|
||||
const fissionSupport = Services.prefs.getBoolPref(
|
||||
PREFS.FEATURES.BROWSER_TOOLBOX_FISSION
|
||||
);
|
||||
const title = fissionSupport
|
||||
? `💥 Fission Browser Console 💥`
|
||||
: l10n.getStr("browserConsole.title");
|
||||
|
@ -137,11 +140,7 @@ class BrowserConsoleManager {
|
|||
const target = await connect();
|
||||
await target.attach();
|
||||
const win = await openWindow(target);
|
||||
const browserConsole = await this.openBrowserConsole(
|
||||
target,
|
||||
win,
|
||||
fissionSupport
|
||||
);
|
||||
const browserConsole = await this.openBrowserConsole(target, win);
|
||||
return browserConsole;
|
||||
})();
|
||||
|
||||
|
|
|
@ -35,10 +35,9 @@ class BrowserConsole extends WebConsole {
|
|||
* The window where the browser console UI is already loaded.
|
||||
* @param nsIDOMWindow chromeWindow
|
||||
* The window of the browser console owner.
|
||||
* @param Boolean fissionSupport
|
||||
*/
|
||||
constructor(target, iframeWindow, chromeWindow, fissionSupport = false) {
|
||||
super(null, iframeWindow, chromeWindow, true, fissionSupport);
|
||||
constructor(target, iframeWindow, chromeWindow) {
|
||||
super(null, iframeWindow, chromeWindow, true);
|
||||
|
||||
this._browserConsoleTarget = target;
|
||||
this._telemetry = new Telemetry();
|
||||
|
|
|
@ -83,6 +83,7 @@ const prefs = {
|
|||
AUTOCOMPLETE: "devtools.webconsole.input.autocomplete",
|
||||
GROUP_WARNINGS: "devtools.webconsole.groupWarningMessages",
|
||||
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";
|
||||
|
||||
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");
|
||||
const hud = await openNewTabAndConsole(TEST_URI);
|
||||
|
||||
|
|
|
@ -12,6 +12,10 @@ const TEST_URI =
|
|||
"test/browser/test-eval-in-stackframe.html";
|
||||
|
||||
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");
|
||||
const hud = await openNewTabAndConsole(TEST_URI);
|
||||
|
||||
|
|
|
@ -11,6 +11,10 @@ const TEST_URI =
|
|||
"test/browser/test-eval-in-stackframe.html";
|
||||
|
||||
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);
|
||||
|
||||
info("Switch to the debugger");
|
||||
|
|
|
@ -20,13 +20,20 @@ class WebConsoleConnectionProxy {
|
|||
* @constructor
|
||||
* @param {WebConsoleUI} webConsoleUI
|
||||
* A WebConsoleUI instance that owns this connection proxy.
|
||||
* @param RemoteTarget target
|
||||
* @param {RemoteTarget} target
|
||||
* 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.target = target;
|
||||
this.fissionSupport = this.webConsoleUI.fissionSupport;
|
||||
this.needContentProcessMessagesListener = needContentProcessMessagesListener;
|
||||
|
||||
this._connecter = null;
|
||||
|
||||
|
@ -116,7 +123,7 @@ class WebConsoleConnectionProxy {
|
|||
// 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
|
||||
// content processes directly.
|
||||
if (this.target.chrome && !this.target.isAddon && !this.fissionSupport) {
|
||||
if (this.needContentProcessMessagesListener) {
|
||||
listeners.push("ContentProcessMessages");
|
||||
}
|
||||
return this.webConsoleClient.startListeners(listeners);
|
||||
|
|
|
@ -24,6 +24,12 @@ loader.lazyRequireGetter(
|
|||
"resource://gre/modules/AppConstants.jsm",
|
||||
true
|
||||
);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"PREFS",
|
||||
"devtools/client/webconsole/constants",
|
||||
true
|
||||
);
|
||||
|
||||
const ZoomKeys = require("devtools/client/shared/zoom-keys");
|
||||
|
||||
|
@ -45,7 +51,6 @@ class WebConsoleUI {
|
|||
this.hud = hud;
|
||||
this.hudId = this.hud.hudId;
|
||||
this.isBrowserConsole = this.hud.isBrowserConsole;
|
||||
this.fissionSupport = this.hud.fissionSupport;
|
||||
this.window = this.hud.iframeWindow;
|
||||
|
||||
this._onPanelSelected = this._onPanelSelected.bind(this);
|
||||
|
@ -257,10 +262,20 @@ class WebConsoleUI {
|
|||
* A promise object that is resolved/reject based on the proxies connections.
|
||||
*/
|
||||
async _initConnection() {
|
||||
this.proxy = new WebConsoleConnectionProxy(this, 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 { processes } = await mainRoot.listProcesses();
|
||||
|
||||
|
|
|
@ -59,20 +59,13 @@ class WebConsole {
|
|||
* The window of the web console owner.
|
||||
* @param bool isBrowserConsole
|
||||
*/
|
||||
constructor(
|
||||
toolbox,
|
||||
iframeWindow,
|
||||
chromeWindow,
|
||||
isBrowserConsole = false,
|
||||
fissionSupport = false
|
||||
) {
|
||||
constructor(toolbox, iframeWindow, chromeWindow, isBrowserConsole = false) {
|
||||
this.toolbox = toolbox;
|
||||
this.iframeWindow = iframeWindow;
|
||||
this.chromeWindow = chromeWindow;
|
||||
this.hudId = "hud_" + ++gHudId;
|
||||
this.browserWindow = this.chromeWindow.top;
|
||||
this.isBrowserConsole = isBrowserConsole;
|
||||
this.fissionSupport = fissionSupport;
|
||||
|
||||
const element = this.browserWindow.document.documentElement;
|
||||
if (element.getAttribute("windowtype") != gDevTools.chromeWindowType) {
|
||||
|
|
|
@ -21,9 +21,6 @@ const CONTENT_PROCESS_SERVER_STARTUP_SCRIPT =
|
|||
loader.lazyRequireGetter(this, "EventEmitter", "devtools/shared/event-emitter");
|
||||
|
||||
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
|
||||
* 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(
|
||||
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);
|
||||
|
||||
// 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.
|
||||
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
|
||||
Services.ppmm.loadProcessScript(
|
||||
CONTENT_PROCESS_SERVER_STARTUP_SCRIPT,
|
||||
true
|
||||
);
|
||||
this._contentProcessServerStartupScriptLoaded = true;
|
||||
}
|
||||
|
||||
// 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_cookies-duplicate-names.js]
|
||||
[browser_storage_dynamic_windows.js]
|
||||
fail-if = fission
|
||||
skip-if = fission # Timeouts
|
||||
[browser_storage_listings.js]
|
||||
fail-if = fission
|
||||
[browser_storage_updates.js]
|
||||
|
|
|
@ -489,6 +489,11 @@ nsresult CharacterData::BindToTree(BindContext& aContext, nsINode& aParent) {
|
|||
|
||||
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(IsInComposedDoc() == aContext.InComposedDoc());
|
||||
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.
|
||||
UnsetFlags(NS_CREATE_FRAME_IF_NON_WHITESPACE | NS_REFRAME_IF_WHITESPACE);
|
||||
|
||||
HandleShadowDOMRelatedRemovalSteps(aNullParent);
|
||||
|
||||
Document* document = GetComposedDoc();
|
||||
|
||||
if (aNullParent) {
|
||||
|
|
|
@ -1721,6 +1721,7 @@ nsresult Element::BindToTree(BindContext& aContext, nsINode& aParent) {
|
|||
if (HasID()) {
|
||||
AddToIdTable(DoGetID());
|
||||
}
|
||||
HandleShadowDOMRelatedInsertionSteps(hadParent);
|
||||
}
|
||||
|
||||
if (MayHaveStyle() && !IsXULElement()) {
|
||||
|
@ -1801,6 +1802,8 @@ bool WillDetachFromShadowOnUnbind(const Element& aElement, bool aNullParent) {
|
|||
}
|
||||
|
||||
void Element::UnbindFromTree(bool aNullParent) {
|
||||
HandleShadowDOMRelatedRemovalSteps(aNullParent);
|
||||
|
||||
const bool detachingFromShadow =
|
||||
WillDetachFromShadowOnUnbind(*this, aNullParent);
|
||||
// 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
|
||||
if (nsXULElement* xulElem = nsXULElement::FromNode(this)) {
|
||||
;
|
||||
xulElem->SetXULBindingParent(nullptr);
|
||||
clearBindingParent = false;
|
||||
}
|
||||
|
@ -2629,7 +2631,8 @@ nsresult Element::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
|
|||
const nsAttrValue* aOldValue,
|
||||
nsIPrincipal* aMaybeScriptedPrincipal,
|
||||
bool aNotify) {
|
||||
if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::part) {
|
||||
if (aNamespaceID == kNameSpaceID_None) {
|
||||
if (aName == nsGkAtoms::part) {
|
||||
bool isPart = !!aValue;
|
||||
if (HasPartAttribute() != isPart) {
|
||||
SetHasPartAttribute(isPart);
|
||||
|
@ -2642,6 +2645,11 @@ nsresult Element::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
|
|||
}
|
||||
}
|
||||
MOZ_ASSERT(HasPartAttribute() == isPart);
|
||||
} else if (aName == nsGkAtoms::slot && GetParent()) {
|
||||
if (ShadowRoot* shadow = GetParent()->GetShadowRoot()) {
|
||||
shadow->MaybeReassignElement(*this);
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -1118,7 +1118,7 @@ void nsIContent::AssertAnonymousSubtreeRelatedInvariants() const {
|
|||
(GetParent() && GetBindingParent() == GetParent()),
|
||||
"root of native anonymous subtree must have parent equal "
|
||||
"to binding parent");
|
||||
NS_ASSERTION(!GetParent() ||
|
||||
NS_ASSERTION(!GetParent() || !IsInComposedDoc() ||
|
||||
((GetBindingParent() == GetParent()) ==
|
||||
HasFlag(NODE_IS_ANONYMOUS_ROOT)) ||
|
||||
// Unfortunately default content for XBL insertion points
|
||||
|
@ -1129,7 +1129,7 @@ void nsIContent::AssertAnonymousSubtreeRelatedInvariants() const {
|
|||
(GetBindingParent() &&
|
||||
(GetBindingParent() == GetParent()->GetBindingParent()) ==
|
||||
HasFlag(NODE_IS_ANONYMOUS_ROOT)),
|
||||
"For nodes with parent, flag and GetBindingParent() check "
|
||||
"For connected nodes, flag and GetBindingParent() check "
|
||||
"should match");
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -36,15 +36,11 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ShadowRoot, DocumentFragment)
|
|||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ShadowRoot)
|
||||
if (tmp->GetHost()) {
|
||||
tmp->GetHost()->RemoveMutationObserver(tmp);
|
||||
}
|
||||
DocumentOrShadowRoot::Unlink(tmp);
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED(DocumentFragment)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ShadowRoot)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContent)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIRadioGroupContainer)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DocumentFragment)
|
||||
|
||||
|
@ -69,19 +65,9 @@ ShadowRoot::ShadowRoot(Element* aElement, ShadowRootMode aMode,
|
|||
|
||||
ExtendedDOMSlots()->mBindingParent = aElement;
|
||||
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() {
|
||||
if (auto* host = GetHost()) {
|
||||
// mHost may have been unlinked.
|
||||
host->RemoveMutationObserver(this);
|
||||
}
|
||||
|
||||
if (IsInComposedDoc()) {
|
||||
OwnerDoc()->RemoveComposedDocShadowRoot(*this);
|
||||
}
|
||||
|
@ -158,13 +144,11 @@ void ShadowRoot::Unattach() {
|
|||
MOZ_ASSERT(!HasSlots(), "Won't work!");
|
||||
if (!GetHost()) {
|
||||
// It is possible that we've been unlinked already. In such case host
|
||||
// should have called Unbind and ShadowRoot's own unlink
|
||||
// RemoveMutationObserver.
|
||||
// should have called Unbind and ShadowRoot's own unlink.
|
||||
return;
|
||||
}
|
||||
|
||||
Unbind();
|
||||
GetHost()->RemoveMutationObserver(this);
|
||||
SetHost(nullptr);
|
||||
}
|
||||
|
||||
|
@ -220,8 +204,8 @@ void ShadowRoot::AddSlot(HTMLSlotElement* aSlot) {
|
|||
while (assignedNodes.Length() > 0) {
|
||||
nsINode* assignedNode = assignedNodes[0];
|
||||
|
||||
oldSlot->RemoveAssignedNode(assignedNode);
|
||||
aSlot->AppendAssignedNode(assignedNode);
|
||||
oldSlot->RemoveAssignedNode(*assignedNode->AsContent());
|
||||
aSlot->AppendAssignedNode(*assignedNode->AsContent());
|
||||
doEnqueueSlotChange = true;
|
||||
}
|
||||
|
||||
|
@ -245,7 +229,7 @@ void ShadowRoot::AddSlot(HTMLSlotElement* aSlot) {
|
|||
continue;
|
||||
}
|
||||
doEnqueueSlotChange = true;
|
||||
aSlot->AppendAssignedNode(child);
|
||||
aSlot->AppendAssignedNode(*child);
|
||||
}
|
||||
|
||||
if (doEnqueueSlotChange) {
|
||||
|
@ -299,8 +283,8 @@ void ShadowRoot::RemoveSlot(HTMLSlotElement* aSlot) {
|
|||
while (!assignedNodes.IsEmpty()) {
|
||||
nsINode* assignedNode = assignedNodes[0];
|
||||
|
||||
aSlot->RemoveAssignedNode(assignedNode);
|
||||
replacementSlot->AppendAssignedNode(assignedNode);
|
||||
aSlot->RemoveAssignedNode(*assignedNode->AsContent());
|
||||
replacementSlot->AppendAssignedNode(*assignedNode->AsContent());
|
||||
}
|
||||
|
||||
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;
|
||||
// Note that if slot attribute is missing, assign it to the first default
|
||||
// slot, if exists.
|
||||
|
@ -513,7 +497,7 @@ ShadowRoot::SlotAssignment ShadowRoot::SlotAssignmentFor(nsIContent* aContent) {
|
|||
// Seek through the host's explicit children until the
|
||||
// assigned content is found.
|
||||
while (currentContent && currentContent != assignedNodes[i]) {
|
||||
if (currentContent == aContent) {
|
||||
if (currentContent == &aContent) {
|
||||
insertionIndex.emplace(i);
|
||||
break;
|
||||
}
|
||||
|
@ -529,9 +513,9 @@ ShadowRoot::SlotAssignment ShadowRoot::SlotAssignmentFor(nsIContent* aContent) {
|
|||
return {slot, insertionIndex};
|
||||
}
|
||||
|
||||
void ShadowRoot::MaybeReassignElement(Element* aElement) {
|
||||
MOZ_ASSERT(aElement->GetParent() == GetHost());
|
||||
HTMLSlotElement* oldSlot = aElement->GetAssignedSlot();
|
||||
void ShadowRoot::MaybeReassignElement(Element& aElement) {
|
||||
MOZ_ASSERT(aElement.GetParent() == GetHost());
|
||||
HTMLSlotElement* oldSlot = aElement.GetAssignedSlot();
|
||||
SlotAssignment assignment = SlotAssignmentFor(aElement);
|
||||
|
||||
if (assignment.mSlot == oldSlot) {
|
||||
|
@ -541,7 +525,7 @@ void ShadowRoot::MaybeReassignElement(Element* aElement) {
|
|||
|
||||
if (Document* doc = GetComposedDoc()) {
|
||||
if (RefPtr<PresShell> presShell = doc->GetPresShell()) {
|
||||
presShell->SlotAssignmentWillChange(*aElement, oldSlot, assignment.mSlot);
|
||||
presShell->SlotAssignmentWillChange(aElement, oldSlot, assignment.mSlot);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -615,40 +599,39 @@ nsINode* ShadowRoot::CreateElementAndAppendChildAt(nsINode& aParentNode,
|
|||
return aParentNode.AppendChild(*node, rv);
|
||||
}
|
||||
|
||||
void ShadowRoot::AttributeChanged(Element* aElement, int32_t aNameSpaceID,
|
||||
nsAtom* aAttribute, int32_t aModType,
|
||||
const nsAttrValue* aOldValue) {
|
||||
if (aNameSpaceID != kNameSpaceID_None || aAttribute != nsGkAtoms::slot) {
|
||||
void ShadowRoot::MaybeUnslotHostChild(nsIContent& aChild) {
|
||||
// Need to null-check the host because we may be unlinked already.
|
||||
MOZ_ASSERT(!GetHost() || aChild.GetParent() == GetHost());
|
||||
|
||||
HTMLSlotElement* slot = aChild.GetAssignedSlot();
|
||||
if (!slot) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aElement->GetParent() != GetHost()) {
|
||||
return;
|
||||
MOZ_DIAGNOSTIC_ASSERT(!aChild.IsRootOfAnonymousSubtree(),
|
||||
"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) {
|
||||
for (nsIContent* content = aFirstNewContent; content;
|
||||
content = content->GetNextSibling()) {
|
||||
ContentInserted(content);
|
||||
}
|
||||
}
|
||||
|
||||
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()) {
|
||||
void ShadowRoot::MaybeSlotHostChild(nsIContent& aChild) {
|
||||
MOZ_ASSERT(aChild.GetParent() == GetHost());
|
||||
// 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 (!aChild.IsSlotable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aChild->GetParent() == GetHost()) {
|
||||
SlotAssignment assignment = SlotAssignmentFor(aChild);
|
||||
if (!assignment.mSlot) {
|
||||
return;
|
||||
|
@ -665,53 +648,7 @@ void ShadowRoot::ContentInserted(nsIContent* aChild) {
|
|||
assignment.mSlot->AppendAssignedNode(aChild);
|
||||
}
|
||||
assignment.mSlot->EnqueueSlotChangeEvent();
|
||||
|
||||
SlotStateChanged(assignment.mSlot);
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
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()) {
|
||||
return;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
ServoStyleRuleMap& ShadowRoot::ServoStyleRuleMap() {
|
||||
|
|
|
@ -39,7 +39,6 @@ class HTMLInputElement;
|
|||
|
||||
class ShadowRoot final : public DocumentFragment,
|
||||
public DocumentOrShadowRoot,
|
||||
public nsStubMutationObserver,
|
||||
public nsIRadioGroupContainer {
|
||||
public:
|
||||
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_ISUPPORTS_INHERITED
|
||||
|
||||
NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
|
||||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
|
||||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
|
||||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
|
||||
|
||||
ShadowRoot(Element* aElement, ShadowRootMode aMode,
|
||||
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
|
||||
|
||||
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
|
||||
Element* Host() const {
|
||||
MOZ_ASSERT(GetHost(),
|
||||
|
@ -106,12 +109,6 @@ class ShadowRoot final : public DocumentFragment,
|
|||
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.
|
||||
*/
|
||||
|
@ -131,7 +128,7 @@ class ShadowRoot final : public DocumentFragment,
|
|||
* It's the caller's responsibility to actually call InsertAssignedNode /
|
||||
* AppendAssignedNode in the slot as needed.
|
||||
*/
|
||||
SlotAssignment SlotAssignmentFor(nsIContent* aContent);
|
||||
SlotAssignment SlotAssignmentFor(nsIContent&);
|
||||
|
||||
/**
|
||||
* 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'].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 += [
|
||||
'ContentAreaDropListener.jsm',
|
||||
'DOMRequestHelper.jsm',
|
||||
|
|
|
@ -239,7 +239,8 @@ class nsDocumentEncoder : public nsIDocumentEncoder {
|
|||
nsresult SerializeToStringRecursive(nsINode* aNode, nsAString& aStr,
|
||||
bool aDontSerializeRoot,
|
||||
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.
|
||||
nsresult SerializeToStringIterative(nsINode* aNode, nsAString& aStr);
|
||||
nsresult SerializeRangeToString(nsRange* aRange, nsAString& aOutputString);
|
||||
|
@ -660,9 +661,8 @@ nsresult nsDocumentEncoder::SerializeNodeStart(nsINode& aOriginalNode,
|
|||
nsLayoutUtils::IsInvisibleBreak(node)) {
|
||||
return rv;
|
||||
}
|
||||
Element* originalElement = aOriginalNode.AsElement();
|
||||
rv = mSerializer->AppendElementStart(node->AsElement(), originalElement,
|
||||
aStr);
|
||||
rv = mSerializer->AppendElementStart(node->AsElement(),
|
||||
aOriginalNode.AsElement(), aStr);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -697,26 +697,33 @@ nsresult nsDocumentEncoder::SerializeNodeStart(nsINode& aOriginalNode,
|
|||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsDocumentEncoder::SerializeNodeEnd(nsINode& aNode, nsAString& aStr) {
|
||||
nsresult nsDocumentEncoder::SerializeNodeEnd(nsINode& aOriginalNode,
|
||||
nsAString& aStr,
|
||||
nsINode* aFixupNode) {
|
||||
if (mNeedsPreformatScanning) {
|
||||
if (aNode.IsElement()) {
|
||||
mSerializer->ForgetElementForPreformat(aNode.AsElement());
|
||||
} else if (aNode.IsText()) {
|
||||
const nsCOMPtr<nsINode> parent = aNode.GetParent();
|
||||
if (aOriginalNode.IsElement()) {
|
||||
mSerializer->ForgetElementForPreformat(aOriginalNode.AsElement());
|
||||
} else if (aOriginalNode.IsText()) {
|
||||
const nsCOMPtr<nsINode> parent = aOriginalNode.GetParent();
|
||||
if (parent && parent->IsElement()) {
|
||||
mSerializer->ForgetElementForPreformat(parent->AsElement());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (IsInvisibleNodeAndShouldBeSkipped(aNode)) {
|
||||
if (IsInvisibleNodeAndShouldBeSkipped(aOriginalNode)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (aNode.IsElement()) {
|
||||
rv = mSerializer->AppendElementEnd(aNode.AsElement(), aStr);
|
||||
FixupNodeDeterminer fixupNodeDeterminer{mNodeFixup, aFixupNode,
|
||||
aOriginalNode};
|
||||
nsINode* node = &fixupNodeDeterminer.GetFixupNodeFallBackToOriginalNode();
|
||||
|
||||
if (node->IsElement()) {
|
||||
rv = mSerializer->AppendElementEnd(node->AsElement(),
|
||||
aOriginalNode.AsElement(), aStr);
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
@ -773,7 +780,7 @@ nsresult nsDocumentEncoder::SerializeToStringRecursive(nsINode* aNode,
|
|||
}
|
||||
|
||||
if (!aDontSerializeRoot) {
|
||||
rv = SerializeNodeEnd(*maybeFixedNode, aStr);
|
||||
rv = SerializeNodeEnd(*aNode, aStr, maybeFixedNode);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
|
|
|
@ -256,7 +256,9 @@ nsHTMLContentSerializer::AppendElementStart(Element* aElement,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLContentSerializer::AppendElementEnd(Element* aElement, nsAString& aStr) {
|
||||
nsHTMLContentSerializer::AppendElementEnd(Element* aElement,
|
||||
Element* aOriginalElement,
|
||||
nsAString& aStr) {
|
||||
NS_ENSURE_ARG(aElement);
|
||||
|
||||
nsAtom* name = aElement->NodeInfo()->NameAtom();
|
||||
|
|
|
@ -29,6 +29,7 @@ class nsHTMLContentSerializer final : public nsXHTMLContentSerializer {
|
|||
nsAString& aStr) override;
|
||||
|
||||
NS_IMETHOD AppendElementEnd(mozilla::dom::Element* aElement,
|
||||
mozilla::dom::Element* aOriginalElement,
|
||||
nsAString& aStr) override;
|
||||
|
||||
NS_IMETHOD AppendDocumentStart(mozilla::dom::Document* aDocument,
|
||||
|
|
|
@ -492,6 +492,22 @@ class nsIContent : public nsINode {
|
|||
*/
|
||||
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
|
||||
* (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();
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -60,6 +60,7 @@ class nsIContentSerializer : public nsISupports {
|
|||
nsAString& aStr) = 0;
|
||||
|
||||
NS_IMETHOD AppendElementEnd(mozilla::dom::Element* aElement,
|
||||
mozilla::dom::Element* aOriginalElement,
|
||||
nsAString& aStr) = 0;
|
||||
|
||||
NS_IMETHOD Flush(nsAString& aStr) = 0;
|
||||
|
|
|
@ -419,7 +419,9 @@ nsPlainTextSerializer::AppendElementStart(Element* aElement,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPlainTextSerializer::AppendElementEnd(Element* aElement, nsAString& aStr) {
|
||||
nsPlainTextSerializer::AppendElementEnd(Element* aElement,
|
||||
Element* aOriginalElement,
|
||||
nsAString& aStr) {
|
||||
NS_ENSURE_ARG(aElement);
|
||||
|
||||
mElement = aElement;
|
||||
|
|
|
@ -69,6 +69,7 @@ class nsPlainTextSerializer final : public nsIContentSerializer {
|
|||
mozilla::dom::Element* aOriginalElement,
|
||||
nsAString& aStr) override;
|
||||
NS_IMETHOD AppendElementEnd(mozilla::dom::Element* aElement,
|
||||
mozilla::dom::Element* aOriginalElement,
|
||||
nsAString& aStr) override;
|
||||
NS_IMETHOD Flush(nsAString& aStr) override;
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/SSE.h"
|
||||
#include "mozilla/ppc.h"
|
||||
#include "nsTextFragmentImpl.h"
|
||||
#include <algorithm>
|
||||
|
||||
|
@ -166,6 +167,14 @@ int32_t FirstNon8Bit(const char16_t* str, const char16_t* end);
|
|||
} // namespace mozilla
|
||||
#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.
|
||||
* 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()) {
|
||||
return mozilla::SSE2::FirstNon8Bit(str, end);
|
||||
}
|
||||
#elif defined(__powerpc__)
|
||||
if (mozilla::supports_vmx()) {
|
||||
return mozilla::VMX::FirstNon8Bit(str, end);
|
||||
}
|
||||
#endif
|
||||
|
||||
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,
|
||||
Element* aOriginalElement,
|
||||
bool& aForceFormat,
|
||||
nsAString& aStr) {
|
||||
NS_ASSERTION(!mIsHTMLSerializer,
|
||||
|
@ -428,7 +429,8 @@ bool nsXHTMLContentSerializer::CheckElementEnd(Element* aElement,
|
|||
}
|
||||
|
||||
bool dummyFormat;
|
||||
return nsXMLContentSerializer::CheckElementEnd(aElement, dummyFormat, aStr);
|
||||
return nsXMLContentSerializer::CheckElementEnd(aElement, aOriginalElement,
|
||||
dummyFormat, aStr);
|
||||
}
|
||||
|
||||
bool nsXHTMLContentSerializer::AppendAndTranslateEntities(
|
||||
|
|
|
@ -52,6 +52,7 @@ class nsXHTMLContentSerializer : public nsXMLContentSerializer {
|
|||
nsAString& aStr) override;
|
||||
|
||||
virtual bool CheckElementEnd(mozilla::dom::Element* aContent,
|
||||
mozilla::dom::Element* aOriginalElement,
|
||||
bool& aForceFormat, nsAString& aStr) override;
|
||||
|
||||
virtual void AfterElementEnd(nsIContent* aContent, nsAString& aStr) override;
|
||||
|
|
|
@ -955,13 +955,16 @@ bool nsXMLContentSerializer::AppendEndOfElementStart(Element* aElement,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXMLContentSerializer::AppendElementEnd(Element* aElement, nsAString& aStr) {
|
||||
nsXMLContentSerializer::AppendElementEnd(Element* aElement,
|
||||
Element* aOriginalElement,
|
||||
nsAString& aStr) {
|
||||
NS_ENSURE_ARG(aElement);
|
||||
|
||||
nsIContent* content = aElement;
|
||||
|
||||
bool forceFormat = false, outputElementEnd;
|
||||
outputElementEnd = CheckElementEnd(aElement, forceFormat, aStr);
|
||||
outputElementEnd =
|
||||
CheckElementEnd(aElement, aOriginalElement, forceFormat, aStr);
|
||||
|
||||
nsAtom* name = content->NodeInfo()->NameAtom();
|
||||
|
||||
|
@ -1083,15 +1086,12 @@ bool nsXMLContentSerializer::CheckElementStart(Element*, bool& aForceFormat,
|
|||
}
|
||||
|
||||
bool nsXMLContentSerializer::CheckElementEnd(Element* aElement,
|
||||
Element* aOriginalElement,
|
||||
bool& aForceFormat,
|
||||
nsAString& aStr) {
|
||||
// We don't output a separate end tag for empty element
|
||||
aForceFormat = false;
|
||||
|
||||
// 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);
|
||||
return ElementNeedsSeparateEndTag(aElement, aOriginalElement);
|
||||
}
|
||||
|
||||
bool nsXMLContentSerializer::AppendToString(const char16_t aChar,
|
||||
|
|
|
@ -63,6 +63,7 @@ class nsXMLContentSerializer : public nsIContentSerializer {
|
|||
nsAString& aStr) override;
|
||||
|
||||
NS_IMETHOD AppendElementEnd(mozilla::dom::Element* aElement,
|
||||
mozilla::dom::Element* aOriginalElement,
|
||||
nsAString& aStr) override;
|
||||
|
||||
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
|
||||
*/
|
||||
virtual bool CheckElementEnd(mozilla::dom::Element* aElement,
|
||||
mozilla::dom::Element* aOriginalElement,
|
||||
bool& aForceFormat, nsAString& aStr);
|
||||
|
||||
/**
|
||||
|
|
|
@ -154,26 +154,25 @@ const nsTArray<RefPtr<nsINode>>& HTMLSlotElement::AssignedNodes() const {
|
|||
return mAssignedNodes;
|
||||
}
|
||||
|
||||
void HTMLSlotElement::InsertAssignedNode(uint32_t aIndex, nsINode* aNode) {
|
||||
MOZ_ASSERT(!aNode->AsContent()->GetAssignedSlot(), "Losing track of a slot");
|
||||
mAssignedNodes.InsertElementAt(aIndex, aNode);
|
||||
aNode->AsContent()->SetAssignedSlot(this);
|
||||
void HTMLSlotElement::InsertAssignedNode(uint32_t aIndex, nsIContent& aNode) {
|
||||
MOZ_ASSERT(!aNode.GetAssignedSlot(), "Losing track of a slot");
|
||||
mAssignedNodes.InsertElementAt(aIndex, &aNode);
|
||||
aNode.SetAssignedSlot(this);
|
||||
}
|
||||
|
||||
void HTMLSlotElement::AppendAssignedNode(nsINode* aNode) {
|
||||
MOZ_ASSERT(!aNode->AsContent()->GetAssignedSlot(), "Losing track of a slot");
|
||||
mAssignedNodes.AppendElement(aNode);
|
||||
aNode->AsContent()->SetAssignedSlot(this);
|
||||
void HTMLSlotElement::AppendAssignedNode(nsIContent& aNode) {
|
||||
MOZ_ASSERT(!aNode.GetAssignedSlot(), "Losing track of a slot");
|
||||
mAssignedNodes.AppendElement(&aNode);
|
||||
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
|
||||
// hasn't been cleared.
|
||||
MOZ_ASSERT(!aNode->AsContent()->GetAssignedSlot() ||
|
||||
aNode->AsContent()->GetAssignedSlot() == this,
|
||||
MOZ_ASSERT(!aNode.GetAssignedSlot() || aNode.GetAssignedSlot() == this,
|
||||
"How exactly?");
|
||||
mAssignedNodes.RemoveElement(aNode);
|
||||
aNode->AsContent()->SetAssignedSlot(nullptr);
|
||||
mAssignedNodes.RemoveElement(&aNode);
|
||||
aNode.SetAssignedSlot(nullptr);
|
||||
}
|
||||
|
||||
void HTMLSlotElement::ClearAssignedNodes() {
|
||||
|
|
|
@ -54,9 +54,9 @@ class HTMLSlotElement final : public nsGenericHTMLElement {
|
|||
|
||||
// Helper methods
|
||||
const nsTArray<RefPtr<nsINode>>& AssignedNodes() const;
|
||||
void InsertAssignedNode(uint32_t aIndex, nsINode* aNode);
|
||||
void AppendAssignedNode(nsINode* aNode);
|
||||
void RemoveAssignedNode(nsINode* aNode);
|
||||
void InsertAssignedNode(uint32_t aIndex, nsIContent&);
|
||||
void AppendAssignedNode(nsIContent&);
|
||||
void RemoveAssignedNode(nsIContent&);
|
||||
void ClearAssignedNodes();
|
||||
|
||||
void EnqueueSlotChangeEvent();
|
||||
|
|
|
@ -47,6 +47,7 @@ skip-if = toolkit == 'android'
|
|||
[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*)
|
||||
[test_same_site_cookies_cross_origin_context.html]
|
||||
fail-if = fission
|
||||
[test_same_site_cookies_from_script.html]
|
||||
[test_same_site_cookies_redirect.html]
|
||||
[test_same_site_cookies_toplevel_set_cookie.html]
|
||||
|
|
|
@ -156,7 +156,6 @@ skip-if = toolkit == 'android'
|
|||
[test_bug1112040.html]
|
||||
[test_bug1160342_marquee.html]
|
||||
[test_bug1171215.html]
|
||||
fail-if = fission
|
||||
support-files = window_bug1171215.html
|
||||
[test_bug1530292.html]
|
||||
fail-if = fission
|
||||
|
|
|
@ -27,6 +27,7 @@ skip-if = os == "android" || verify # bug 962029
|
|||
[test_cookieBlock.html]
|
||||
[test_embededNulls.html]
|
||||
[test_keySync.html]
|
||||
fail-if = fission
|
||||
[test_localStorageBase.html]
|
||||
skip-if = e10s
|
||||
[test_localStorageBaseSessionOnly.html]
|
||||
|
@ -34,12 +35,17 @@ skip-if = e10s
|
|||
[test_localStorageEnablePref.html]
|
||||
[test_localStorageKeyOrder.html]
|
||||
[test_localStorageOriginsDiff.html]
|
||||
fail-if = fission
|
||||
[test_localStorageOriginsDomainDiffs.html]
|
||||
fail-if = fission
|
||||
[test_localStorageOriginsEquals.html]
|
||||
skip-if = toolkit == 'android'
|
||||
fail-if = fission
|
||||
[test_localStorageOriginsPortDiffs.html]
|
||||
fail-if = fission
|
||||
[test_localStorageOriginsSchemaDiffs.html]
|
||||
skip-if = toolkit == 'android' #TIMED_OUT
|
||||
fail-if = fission
|
||||
[test_localStorageQuota.html]
|
||||
skip-if = toolkit == 'android' #TIMED_OUT
|
||||
[test_localStorageQuotaSessionOnly.html]
|
||||
|
|
|
@ -25,15 +25,11 @@ support-files =
|
|||
skip-if = toolkit == 'android' #bug 894914 - wrong data - got FAIL, expected message
|
||||
[test_postMessage_hash.html]
|
||||
[test_postMessage.html]
|
||||
fail-if = fission
|
||||
[test_postMessage_idn.xhtml]
|
||||
fail-if = fission
|
||||
[test_postMessage_joined.html]
|
||||
fail-if = fission
|
||||
[test_postMessage_onOther.html]
|
||||
skip-if = fission #Bug 1571273
|
||||
[test_postMessage_origin.xhtml]
|
||||
fail-if = fission
|
||||
[test_postMessage_override.html]
|
||||
skip-if = fission
|
||||
[test_postMessage_special.xhtml]
|
||||
|
@ -43,7 +39,6 @@ skip-if = fission #Bug 1570918
|
|||
[test_postMessage_transfer.html]
|
||||
skip-if = fission #Bug 1571208
|
||||
[test_postMessage_userpass.html]
|
||||
fail-if = fission
|
||||
[test_bug500328.html]
|
||||
skip-if = true || toolkit=='android' # bug 696306, #TIMED_OUT android
|
||||
support-files = file_bug500328_1.html file_bug500328_2.html
|
||||
|
|
|
@ -16,6 +16,7 @@ support-files =
|
|||
|
||||
[test_bug1081686.html]
|
||||
[test_bug1384658.html]
|
||||
skip-if = fission # Timeouts
|
||||
support-files = window_bug1384658.html frame_bug1384658.html file_bug1384658.html
|
||||
[test_event_listener_leaks.html]
|
||||
support-files = file_websocket_bigBlob_wsh.py
|
||||
|
|
|
@ -145,6 +145,7 @@ tags = mcb
|
|||
[test_location.html]
|
||||
[test_longThread.html]
|
||||
[test_multi_sharedWorker.html]
|
||||
skip-if = fission # Timeouts
|
||||
[test_multi_sharedWorker_lifetimes.html]
|
||||
[test_navigator.html]
|
||||
support-files =
|
||||
|
|
|
@ -58,6 +58,16 @@ struct SurfaceDescriptorMacIOSurface {
|
|||
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 {
|
||||
uint64_t handle;
|
||||
IntSize size;
|
||||
|
@ -148,6 +158,7 @@ union SurfaceDescriptor {
|
|||
SurfaceDescriptorFileMapping;
|
||||
SurfaceDescriptorDXGIYCbCr;
|
||||
SurfaceDescriptorX11;
|
||||
SurfaceDescriptorDMABuf;
|
||||
SurfaceTextureDescriptor;
|
||||
EGLImageDescriptor;
|
||||
SurfaceDescriptorMacIOSurface;
|
||||
|
|
|
@ -439,7 +439,7 @@ set_define('JS_BUILD_BINAST', depends_if('--enable-binast')(lambda x: True))
|
|||
# ==============================================================
|
||||
|
||||
js_option('--enable-cranelift',
|
||||
default=milestone.is_nightly & js_standalone,
|
||||
default=milestone.is_nightly,
|
||||
help='{Enable|Disable} Cranelift code generator for wasm')
|
||||
|
||||
set_config('ENABLE_WASM_CRANELIFT', depends_if('--enable-cranelift')(lambda x: True))
|
||||
|
|
|
@ -291,6 +291,7 @@ struct LazyScriptCreationData {
|
|||
}
|
||||
|
||||
if (!closedOverBindings.appendAll(COB)) {
|
||||
ReportOutOfMemory(cx); // closedOverBindings uses SystemAllocPolicy.
|
||||
return false;
|
||||
}
|
||||
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/*'):
|
||||
BUG_COMPONENT = component_intl
|
||||
|
||||
if CONFIG['ENABLE_WASM_CRANELIFT']:
|
||||
CONFIGURE_SUBST_FILES += ['rust/extra-bindgen-flags']
|
||||
|
||||
if not CONFIG['JS_DISABLE_SHELL']:
|
||||
DIRS += [
|
||||
'rust',
|
||||
|
|
|
@ -18,8 +18,6 @@ if CONFIG['ENABLE_WASM_CRANELIFT']:
|
|||
|
||||
RustLibrary('jsrust', features)
|
||||
|
||||
CONFIGURE_SUBST_FILES += ['extra-bindgen-flags']
|
||||
|
||||
if CONFIG['JS_SHARED_LIBRARY']:
|
||||
FINAL_LIBRARY = 'js'
|
||||
|
||||
|
|
|
@ -4012,9 +4012,7 @@ void PaintedLayerData::AccumulateHitTestItem(ContainerState* aState,
|
|||
nsDisplayItem* aItem,
|
||||
const DisplayItemClip& aClip,
|
||||
TransformClipNode* aTransform) {
|
||||
MOZ_ASSERT(aItem->HasHitTestInfo());
|
||||
auto* item = static_cast<nsDisplayHitTestInfoItem*>(aItem);
|
||||
|
||||
const HitTestInfo& info = item->GetHitTestInfo();
|
||||
|
||||
nsRect area = info.mArea;
|
||||
|
@ -4556,6 +4554,7 @@ void ContainerState::ProcessDisplayItems(nsDisplayList* aList) {
|
|||
nsRect itemContent;
|
||||
|
||||
if (marker == DisplayItemEntryType::HitTestInfo) {
|
||||
MOZ_ASSERT(item->IsHitTestItem());
|
||||
const auto& hitTestInfo =
|
||||
static_cast<nsDisplayHitTestInfoItem*>(item)->GetHitTestInfo();
|
||||
|
||||
|
|
|
@ -3874,8 +3874,8 @@ struct HitTestInfo {
|
|||
nsRect mArea;
|
||||
mozilla::gfx::CompositorHitTestInfo mFlags;
|
||||
|
||||
AnimatedGeometryRoot* mAGR;
|
||||
const mozilla::ActiveScrolledRoot* mASR;
|
||||
RefPtr<AnimatedGeometryRoot> mAGR;
|
||||
RefPtr<const mozilla::ActiveScrolledRoot> mASR;
|
||||
RefPtr<const mozilla::DisplayItemClipChain> mClipChain;
|
||||
const mozilla::DisplayItemClip* mClip;
|
||||
};
|
||||
|
@ -3893,7 +3893,10 @@ class nsDisplayHitTestInfoItem : public nsPaintedDisplayItem {
|
|||
const nsDisplayHitTestInfoItem& aOther)
|
||||
: nsPaintedDisplayItem(aBuilder, aOther) {}
|
||||
|
||||
const HitTestInfo& GetHitTestInfo() const { return *mHitTestInfo; }
|
||||
const HitTestInfo& GetHitTestInfo() const {
|
||||
MOZ_ASSERT(HasHitTestInfo());
|
||||
return *mHitTestInfo;
|
||||
}
|
||||
|
||||
void SetActiveScrolledRoot(
|
||||
const ActiveScrolledRoot* aActiveScrolledRoot) override {
|
||||
|
|
|
@ -456,7 +456,9 @@ this.tabs = class extends ExtensionAPI {
|
|||
queryInfo = Object.assign({}, queryInfo);
|
||||
|
||||
if (queryInfo.url !== null) {
|
||||
queryInfo.url = new MatchPatternSet([].concat(queryInfo.url));
|
||||
queryInfo.url = new MatchPatternSet([].concat(queryInfo.url), {
|
||||
restrictSchemes: false,
|
||||
});
|
||||
}
|
||||
if (queryInfo.title !== null) {
|
||||
queryInfo.title = new MatchGlob(queryInfo.title);
|
||||
|
|
|
@ -1240,4 +1240,41 @@ class NavigationDelegateTest : BaseSessionTest() {
|
|||
mainSession.loadTestPath(HELLO_HTML_PATH)
|
||||
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_origin_header.html]
|
||||
[test_1502055.html]
|
||||
skip-if = fission # Timeouts
|
||||
support-files = sw_1502055.js file_1502055.sjs iframe_1502055.html
|
||||
[test_accept_header.html]
|
||||
support-files = test_accept_header.sjs
|
||||
|
|
|
@ -221,3 +221,45 @@ rustfmt:
|
|||
when:
|
||||
files-changed:
|
||||
- '**/*.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)
|
||||
|
||||
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),
|
||||
'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"}
|
|
@ -13,7 +13,7 @@
|
|||
[package]
|
||||
edition = "2018"
|
||||
name = "dogear"
|
||||
version = "0.3.1"
|
||||
version = "0.3.3"
|
||||
authors = ["Lina Cambridge <lina@mozilla.com>"]
|
||||
exclude = ["/.travis/**", ".travis.yml", "/docs/**", "book.toml"]
|
||||
description = "A library for merging bookmark trees."
|
||||
|
|
|
@ -1528,28 +1528,23 @@ impl<'t, D: Driver, A: AbortSignal> Merger<'t, D, A> {
|
|||
for (local_position, local_child_node) in local_parent_node.children().enumerate() {
|
||||
self.signal.err_if_aborted()?;
|
||||
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",
|
||||
"Not deduping local built-in root {}",
|
||||
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).
|
||||
|
@ -1563,20 +1558,38 @@ impl<'t, D: Driver, A: AbortSignal> Merger<'t, D, A> {
|
|||
};
|
||||
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 {
|
||||
}
|
||||
None => {
|
||||
trace!(
|
||||
self.driver,
|
||||
"Not deduping local child {}; already uploaded",
|
||||
"Not deduping local child {} without content info",
|
||||
local_child_node
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut local_to_remote = HashMap::new();
|
||||
let mut remote_to_local = HashMap::new();
|
||||
|
||||
for (remote_position, remote_child_node) in remote_parent_node.children().enumerate() {
|
||||
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) {
|
||||
trace!(
|
||||
self.driver,
|
||||
|
@ -1588,7 +1601,8 @@ impl<'t, D: Driver, A: AbortSignal> Merger<'t, D, A> {
|
|||
// 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
|
||||
// were.
|
||||
if let Some(remote_child_content) = remote_child_node.content() {
|
||||
match remote_child_node.content() {
|
||||
Some(remote_child_content) => {
|
||||
let dupe_key = match remote_child_content {
|
||||
Content::Bookmark { .. } | Content::Folder { .. } => {
|
||||
DupeKey::WithoutPosition(remote_child_content)
|
||||
|
@ -1605,8 +1619,10 @@ impl<'t, D: Driver, A: AbortSignal> Merger<'t, D, A> {
|
|||
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,
|
||||
|
@ -1623,14 +1639,16 @@ impl<'t, D: Driver, A: AbortSignal> Merger<'t, D, A> {
|
|||
);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
None => {
|
||||
trace!(
|
||||
self.driver,
|
||||
"Not deduping remote child {}; already merged",
|
||||
"Not deduping remote child {} without content info",
|
||||
remote_child_node
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok((local_to_remote, remote_to_local))
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ impl TryFrom<Node> for Builder {
|
|||
_ => return Err(err),
|
||||
}
|
||||
}
|
||||
b.mutate(&guid).by_structure(&parent_guid)?;
|
||||
b.parent_for(&guid).by_structure(&parent_guid)?;
|
||||
for child in node.children {
|
||||
inflate(b, &guid, child)?;
|
||||
}
|
||||
|
@ -1323,6 +1323,82 @@ fn newer_move_to_deleted() {
|
|||
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]
|
||||
fn deduping_local_newer() {
|
||||
before_each();
|
||||
|
|
|
@ -499,52 +499,10 @@ impl<'b> ItemBuilder<'b> {
|
|||
b.by_parent_guid(parent_guid)
|
||||
}
|
||||
|
||||
/// 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.
|
||||
#[inline]
|
||||
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,
|
||||
_ => {
|
||||
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)
|
||||
let b = ParentBuilder(self.0, BuilderEntryChild::Exists(self.1));
|
||||
b.by_structure(parent_guid)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -593,6 +551,56 @@ impl<'b> ParentBuilder<'b> {
|
|||
}
|
||||
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,
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче