Merge autoland to mozilla-central. a=merge

This commit is contained in:
Noemi Erli 2023-04-11 00:24:38 +03:00
commit 2ce39261ea
46 changed files with 587 additions and 859 deletions

View File

@ -106,7 +106,7 @@ export class ChromeProfileMigrator extends MigratorBase {
let path = await lazy.ChromeMigrationUtils.getDataPath(
this._chromeUserDataPathSuffix
);
let exists = await IOUtils.exists(path);
let exists = path && (await IOUtils.exists(path));
if (exists) {
this._chromeUserDataPath = path;
} else {

View File

@ -12,6 +12,11 @@ const { AddonManager } = ChromeUtils.import(
const { WebRequest } = ChromeUtils.import(
"resource://gre/modules/WebRequest.jsm"
);
const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
AddonSearchEngine: "resource://gre/modules/AddonSearchEngine.sys.mjs",
});
// eslint-disable-next-line mozilla/reject-importGlobalProperties
XPCOMUtils.defineLazyGlobalGetters(this, ["ChannelWrapper"]);
@ -55,7 +60,10 @@ this.addonsSearchDetection = class extends ExtensionAPI {
const visibleEngines = await Services.search.getEngines();
visibleEngines.forEach(engine => {
const { _extensionID, _urls } = engine;
if (!(engine instanceof lazy.AddonSearchEngine)) {
return;
}
const { _extensionID, _urls } = engine.wrappedJSObject;
if (!_extensionID) {
// OpenSearch engines don't have an extension ID.

View File

@ -64,10 +64,6 @@ label:not([hidden]) {
width: fit-content;
}
button {
margin-block-end: 0;
}
#wizard-deck > div {
display: flex;
flex-direction: column;
@ -75,6 +71,7 @@ button {
#browser-profile-selector {
display: flex;
align-items: center;
border: 0;
padding: 8px;
margin: 0;
@ -101,7 +98,6 @@ button {
fill: var(--in-content-icon-color);
height: 16px;
width: 16px;
align-self: center;
}
.migrator-description {

View File

@ -168,6 +168,7 @@ const TEST_DATA = [
slot
::before
div!slotted
default content
::after
::before
class="light-dom"

View File

@ -61,13 +61,24 @@ add_task(async function() {
await expandContainer(inspector, slotContainer);
let slotChildContainers = slotContainer.getChildContainers();
is(slotChildContainers.length, 2, "Expecting 2 slotted children");
slotChildContainers.forEach(container => assertContainerSlotted(container));
is(
slotChildContainers.length,
3,
"Expecting 3 children (2 slotted, fallback)"
);
assertContainerSlotted(slotChildContainers[0]);
assertContainerSlotted(slotChildContainers[1]);
assertContainerHasText(slotChildContainers[2], "div");
await deleteNode(inspector, "#el1");
slotChildContainers = slotContainer.getChildContainers();
is(slotChildContainers.length, 1, "Expecting 1 slotted child");
is(
slotChildContainers.length,
2,
"Expecting 2 children (1 slotted, fallback)"
);
assertContainerSlotted(slotChildContainers[0]);
assertContainerHasText(slotChildContainers[1], "div");
await deleteNode(inspector, "#el2");
slotChildContainers = slotContainer.getChildContainers();

View File

@ -65,6 +65,7 @@ const TEST_DATA = [
#shadow-root
slot
div!slotted
default content
::marker
::before
class="light-dom"`,

View File

@ -25,8 +25,10 @@ const TEST_URL = `data:text/html;charset=utf-8,
});
</script>`;
const MAX_CHILDREN = 5;
add_task(async function() {
await pushPref("devtools.markup.pagesize", 5);
await pushPref("devtools.markup.pagesize", MAX_CHILDREN);
const { inspector } = await openInspectorForURL(TEST_URL);
@ -45,11 +47,11 @@ add_task(async function() {
is(
childContainers.length,
6,
"Expecting 6 children: shadowroot, 5 host children"
MAX_CHILDREN,
"Expecting 5 children: shadowroot, 4 host children"
);
assertContainerHasText(childContainers[0], "#shadow-root");
for (let i = 1; i < 6; i++) {
for (let i = 1; i < 5; i++) {
assertContainerHasText(childContainers[i], "div");
assertContainerHasText(childContainers[i], "node " + i);
}
@ -85,7 +87,7 @@ add_task(async function() {
await waitForMultipleChildrenUpdates(inspector);
let slotChildContainers = slotContainer.getChildContainers();
is(slotChildContainers.length, 5, "Expecting 5 slotted children");
is(slotChildContainers.length, MAX_CHILDREN, "Expecting 5 slotted children");
for (const slotChildContainer of slotChildContainers) {
assertContainerHasText(slotChildContainer, "div");
ok(
@ -107,7 +109,11 @@ add_task(async function() {
await inspector.markup._waitForChildren();
slotChildContainers = slotContainer.getChildContainers();
is(slotChildContainers.length, 6, "Expecting one additional slotted element");
is(
slotChildContainers.length,
7,
"Expecting one additional slotted element and fallback"
);
assertContainerHasText(slotChildContainers[5], "div");
ok(
slotChildContainers[5].elt.querySelector(".reveal-link"),

View File

@ -46,8 +46,9 @@ add_task(async function() {
await selectNode(pContainer.node, inspector, "no-reason", false);
const ruleView = inspector.getPanel("ruleview").view;
// We only display the style attribute.
is(
ruleView.element.querySelectorAll("#ruleview-no-results").length,
ruleView.element.querySelectorAll(".ruleview-rule").length,
1,
"No rules are displayed for this p element"
);

View File

@ -4,12 +4,6 @@
"use strict";
loader.lazyRequireGetter(
this,
"isShadowRoot",
"resource://devtools/shared/layout/utils.js",
true
);
loader.lazyRequireGetter(
this,
"nodeFilterConstants",
@ -83,17 +77,6 @@ class DocumentWalker {
}
parentNode() {
if (isShadowRoot(this.currentNode)) {
this.currentNode = this.currentNode.host;
return this.currentNode;
}
const parentNode = this.currentNode.parentNode;
// deep-tree-walker currently does not return shadowRoot elements as parentNodes.
if (parentNode && isShadowRoot(parentNode)) {
this.currentNode = parentNode;
return this.currentNode;
}
return this.walker.parentNode();
}
@ -112,8 +95,7 @@ class DocumentWalker {
}
firstChild() {
const node = this.walker.currentNode;
if (!node) {
if (!this.walker.currentNode) {
return null;
}
@ -126,8 +108,7 @@ class DocumentWalker {
}
lastChild() {
const node = this.walker.currentNode;
if (!node) {
if (!this.walker.currentNode) {
return null;
}

View File

@ -67,14 +67,6 @@ class NodePicker {
node = this._findNodeAtMouseEventPosition(event) || node;
}
// The node picker should only surface elements valid for the current walker
// configuration. UserAgent shadow DOM should only be visible if
// showAllAnonymousContent is set to true. Otherwise, fallback to the host.
const shadowRoot = node.containingShadowRoot;
if (shadowRoot?.isUAWidget() && !this._walker.showAllAnonymousContent) {
node = shadowRoot.host;
}
return this._walker.attachElement(node);
}

View File

@ -153,13 +153,7 @@ function standardTreeWalkerFilter(node) {
// Ignore all native anonymous roots inside a non-XUL document.
// We need to do this to skip things like form controls, scrollbars,
// video controls, etc (see bug 1187482).
// Accept the children of NAC roots (like UA widgets). If our root is
// anonymous the whole tree is anonymous.
if (
isNativeAnonymous(node) &&
!isInXULDocument(node) &&
!isNativeAnonymous(node.getRootNode())
) {
if (isNativeAnonymous(node) && !isInXULDocument(node)) {
return nodeFilterConstants.FILTER_SKIP;
}

View File

@ -14,21 +14,24 @@ const {
EXCLUDED_LISTENER,
} = require("resource://devtools/server/actors/inspector/constants.js");
loader.lazyRequireGetter(
this,
"nodeFilterConstants",
"resource://devtools/shared/dom-node-filter-constants.js"
);
loader.lazyRequireGetter(
this,
[
"getFrameElement",
"isAfterPseudoElement",
"isAnonymous",
"isBeforePseudoElement",
"isDirectShadowHostChild",
"isMarkerPseudoElement",
"isNativeAnonymous",
"isFrameBlockedByCSP",
"isFrameWithChildTarget",
"isShadowHost",
"isShadowRoot",
"isTemplateElement",
"loadSheet",
],
"resource://devtools/shared/layout/utils.js",
@ -335,7 +338,7 @@ class WalkerActor extends Actor {
return "[WalkerActor " + this.actorID + "]";
}
getAnonymousDocumentWalker(node, skipTo) {
getDocumentWalker(node, skipTo) {
// Allow native anon content (like <video> controls) if preffed on
const filter = this.showAllAnonymousContent
? allAnonymousContentTreeWalkerFilter
@ -348,28 +351,6 @@ class WalkerActor extends Actor {
});
}
getNonAnonymousDocumentWalker(node, skipTo) {
const nodeFilter = standardTreeWalkerFilter;
return new DocumentWalker(node, this.rootWin, {
nodeFilter,
skipTo,
showAnonymousContent: false,
});
}
/**
* Will first try to create a regular anonymous document walker. If it fails, will fall
* back on a non-anonymous walker.
*/
getDocumentWalker(node, skipTo) {
try {
return this.getAnonymousDocumentWalker(node, skipTo);
} catch (e) {
return this.getNonAnonymousDocumentWalker(node, skipTo);
}
}
destroy() {
if (this._destroyed) {
return;
@ -635,10 +616,17 @@ class WalkerActor extends Actor {
for (let node of nodes) {
if (!(node instanceof NodeActor)) {
// If an anonymous node was passed in and we aren't supposed to know
// about it, then consult with the document walker as the source of
// truth about which elements exist.
if (!this.showAllAnonymousContent && isAnonymous(node)) {
node = this.getDocumentWalker(node).currentNode;
// about it, then use the closest ancestor.
if (!this.showAllAnonymousContent) {
while (
node &&
standardTreeWalkerFilter(node) != nodeFilterConstants.FILTER_ACCEPT
) {
node = this.rawParentNode(node);
}
if (!node) {
continue;
}
}
node = this._getOrCreateNodeActor(node);
@ -692,23 +680,11 @@ class WalkerActor extends Actor {
}
rawParentNode(node) {
let parent;
try {
// If the node is the child of a shadow host, we can not use an anonymous walker to
// get the shadow host parent.
const walker = isDirectShadowHostChild(node.rawNode)
? this.getNonAnonymousDocumentWalker(node.rawNode)
: this.getAnonymousDocumentWalker(node.rawNode);
parent = walker.parentNode();
} catch (e) {
// When getting the parent node for a child of a non-slotted shadow host child,
// walker.parentNode() will throw if the walker is anonymous, because non-slotted
// shadow host children are not accessible anywhere in the anonymous tree.
const walker = this.getNonAnonymousDocumentWalker(node.rawNode);
parent = walker.parentNode();
const rawNode = node instanceof NodeActor ? node.rawNode : node;
if (rawNode == this.rootDoc) {
return null;
}
return parent;
return InspectorUtils.getParentForNode(rawNode, /* anonymous = */ true);
}
/**
@ -732,8 +708,8 @@ class WalkerActor extends Actor {
return undefined;
}
const walker = this.getDocumentWalker(rawNode);
const firstChild = walker.firstChild();
const children = this._rawChildren(rawNode, /* includeAssigned = */ true);
const firstChild = children[0];
// Bail out if:
// - more than one child
@ -743,8 +719,8 @@ class WalkerActor extends Actor {
// a link to the original node.
// - we are a flex item -> these are always shown on their own lines so they can be
// selected by the flexbox inspector.
const isAssignedSlot =
!!firstChild &&
const isAssignedToSlot =
firstChild &&
rawNode.nodeName === "SLOT" &&
isDirectShadowHostChild(firstChild);
@ -752,10 +728,10 @@ class WalkerActor extends Actor {
if (
!firstChild ||
walker.nextSibling() ||
children.length > 1 ||
firstChild.nodeType !== Node.TEXT_NODE ||
firstChild.nodeValue.length > gValueSummaryLength ||
isAssignedSlot ||
isAssignedToSlot ||
isFlexItem
) {
return undefined;
@ -815,15 +791,11 @@ class WalkerActor extends Actor {
this._retainedOrphans.delete(node);
}
const walker = this.getDocumentWalker(node.rawNode);
let child = walker.firstChild();
while (child) {
for (const child of this._rawChildren(node.rawNode)) {
const childActor = this.getNode(child);
if (childActor) {
this.releaseNode(childActor, options);
}
child = walker.nextSibling();
}
node.destroy();
@ -896,6 +868,32 @@ class WalkerActor extends Actor {
};
}
/**
* Returns the raw children of the DOM node, with anon content filtered as needed
* @param Node rawNode.
* @param boolean includeAssigned
* Whether <slot> assigned children should be returned. See
* HTMLSlotElement.assignedNodes().
* @returns Array<Node> the list of children.
*/
_rawChildren(rawNode, includeAssigned) {
const filter = this.showAllAnonymousContent
? allAnonymousContentTreeWalkerFilter
: standardTreeWalkerFilter;
const ret = [];
const children = InspectorUtils.getChildrenForNode(
rawNode,
/* anonymous = */ true,
includeAssigned
);
for (const child of children) {
if (filter(child) == nodeFilterConstants.FILTER_ACCEPT) {
ret.push(child);
}
}
return ret;
}
/**
* Return chidlren of the given node. Contrary to children children(), this method only
* returns DOMNodes. Therefore it will not create NodeActor wrappers and will not
@ -914,205 +912,47 @@ class WalkerActor extends Actor {
*/
// eslint-disable-next-line complexity
_getChildren(node, options = {}) {
if (isNodeDead(node)) {
return { hasFirst: true, hasLast: true, nodes: [] };
}
if (isFrameBlockedByCSP(node.rawNode)) {
if (isNodeDead(node) || isFrameBlockedByCSP(node.rawNode)) {
return { hasFirst: true, hasLast: true, nodes: [] };
}
if (options.center && options.start) {
throw Error("Can't specify both 'center' and 'start' options.");
}
let maxNodes = options.maxNodes || -1;
if (maxNodes == -1) {
maxNodes = Number.MAX_VALUE;
}
const directShadowHostChild = isDirectShadowHostChild(node.rawNode);
const shadowHost = isShadowHost(node.rawNode);
const shadowRoot = isShadowRoot(node.rawNode);
// UA Widgets are internal Firefox widgets such as videocontrols implemented
// using shadow DOM. By default, their shadow root should be hidden for web
// developers.
const isUAWidget =
shadowHost && node.rawNode.openOrClosedShadowRoot.isUAWidget();
const hideShadowRoot = isUAWidget && !this.showAllAnonymousContent;
const showNativeAnonymousChildren =
isUAWidget && this.showAllAnonymousContent;
const templateElement = isTemplateElement(node.rawNode);
if (templateElement) {
// <template> tags should have a single child pointing to the element's template
// content.
const documentFragment = node.rawNode.content;
const nodes = [documentFragment];
return { hasFirst: true, hasLast: true, nodes };
}
// Detect special case of unslotted shadow host children that cannot rely on a
// regular anonymous walker.
let isUnslottedHostChild = false;
if (directShadowHostChild) {
try {
this.getDocumentWalker(node.rawNode, SKIP_TO_SIBLING);
} catch (e) {
isUnslottedHostChild = true;
}
}
const useNonAnonymousWalker =
shadowRoot || shadowHost || isUnslottedHostChild;
// We're going to create a few document walkers with the same filter,
// make it easier.
const getFilteredWalker = documentWalkerNode => {
// Use SKIP_TO_SIBLING to force the walker to use a sibling of the provided node
// in case this one is incompatible with the walker's filter function.
const skipTo = SKIP_TO_SIBLING;
if (useNonAnonymousWalker) {
// Do not use an anonymous walker for :
// - shadow roots: if the host element has an ::after pseudo element, a walker on
// the last child of the shadow root will jump to the ::after element, which is
// not a child of the shadow root.
// TODO: For this case, should rather use an anonymous walker with a new
// dedicated filter.
// - shadow hosts: anonymous children of host elements make up the shadow dom,
// while we want to return the direct children of the shadow host.
// - unslotted host child: if a shadow host child is not slotted, it is not part
// of any anonymous tree and cannot be used with anonymous tree walkers.
return this.getNonAnonymousDocumentWalker(documentWalkerNode, skipTo);
}
return this.getDocumentWalker(documentWalkerNode, skipTo);
};
// Need to know the first and last child.
const rawNode = node.rawNode;
const firstChild = getFilteredWalker(rawNode).firstChild();
const lastChild = getFilteredWalker(rawNode).lastChild();
if (!firstChild && !shadowHost) {
// No children, we're done.
return { hasFirst: true, hasLast: true, nodes: [] };
}
let nodes = [];
if (firstChild) {
let start;
let nodes = this._rawChildren(node.rawNode, /* includeAssigned = */ true);
let hasFirst = true;
let hasLast = true;
if (nodes.length > maxNodes) {
let startIndex;
if (options.center) {
start = options.center.rawNode;
} else if (options.start) {
start = options.start.rawNode;
} else {
start = firstChild;
}
// If we are using a non anonymous walker, we cannot start on:
// - a shadow root
// - a native anonymous node
if (
useNonAnonymousWalker &&
(isShadowRoot(start) || isNativeAnonymous(start))
) {
start = firstChild;
}
// Start by reading backward from the starting point if we're centering...
const backwardWalker = getFilteredWalker(start);
if (backwardWalker.currentNode != firstChild && options.center) {
backwardWalker.previousSibling();
const centerIndex = nodes.indexOf(options.center.rawNode);
const backwardCount = Math.floor(maxNodes / 2);
const backwardNodes = this._readBackward(backwardWalker, backwardCount);
nodes = backwardNodes;
// If centering would hit the end, just read the last maxNodes nodes.
if (centerIndex - backwardCount + maxNodes >= nodes.length) {
startIndex = nodes.length - maxNodes;
} else {
startIndex = Math.max(0, centerIndex - backwardCount);
}
} else if (options.start) {
startIndex = Math.max(0, nodes.indexOf(options.start.rawNode));
} else {
startIndex = 0;
}
// Then read forward by any slack left in the max children...
const forwardWalker = getFilteredWalker(start);
const forwardCount = maxNodes - nodes.length;
nodes = nodes.concat(this._readForward(forwardWalker, forwardCount));
// If there's any room left, it means we've run all the way to the end.
// If we're centering, check if there are more items to read at the front.
const remaining = maxNodes - nodes.length;
if (options.center && remaining > 0 && nodes[0].rawNode != firstChild) {
const firstNodes = this._readBackward(backwardWalker, remaining);
// Then put it all back together.
nodes = firstNodes.concat(nodes);
}
}
let hasFirst, hasLast;
if (nodes.length) {
// Compare first/last with expected nodes before modifying the nodes array in case
// this is a shadow host.
hasFirst = nodes[0] == firstChild;
hasLast = nodes[nodes.length - 1] == lastChild;
} else {
// If nodes is still an empty array, we are on a host element with a shadow root but
// no direct children.
hasFirst = hasLast = true;
}
if (shadowHost) {
// Use anonymous walkers to fetch ::marker / ::before / ::after pseudo
// elements
const firstChildWalker = this.getDocumentWalker(node.rawNode);
const first = firstChildWalker.firstChild();
const hasMarker =
first && first.nodeName === "_moz_generated_content_marker";
const maybeBeforeNode = hasMarker
? firstChildWalker.nextSibling()
: first;
const hasBefore =
maybeBeforeNode &&
maybeBeforeNode.nodeName === "_moz_generated_content_before";
const lastChildWalker = this.getDocumentWalker(node.rawNode);
const last = lastChildWalker.lastChild();
const hasAfter = last && last.nodeName === "_moz_generated_content_after";
nodes = [
// #shadow-root
...(hideShadowRoot ? [] : [node.rawNode.openOrClosedShadowRoot]),
// ::marker
...(hasMarker ? [first] : []),
// ::before
...(hasBefore ? [maybeBeforeNode] : []),
// shadow host direct children
...nodes,
// native anonymous content for UA widgets
...(showNativeAnonymousChildren
? this.getNativeAnonymousChildren(node.rawNode)
: []),
// ::after
...(hasAfter ? [last] : []),
];
const endIndex = Math.min(startIndex + maxNodes, nodes.length);
hasFirst = startIndex == 0;
hasLast = endIndex >= nodes.length;
nodes = nodes.slice(startIndex, endIndex);
}
return { hasFirst, hasLast, nodes };
}
getNativeAnonymousChildren(rawNode) {
// Get an anonymous walker and start on the first child.
const walker = this.getDocumentWalker(rawNode);
let node = walker.firstChild();
const nodes = [];
while (node) {
// We only want direct native anonymous children here.
if (isNativeAnonymous(node) && node.parentNode == rawNode) {
nodes.push(node);
}
node = walker.nextSibling();
}
return nodes;
}
/**
* Get the next sibling of a given node. Getting nodes one at a time
* might be inefficient, be careful.
@ -1160,26 +1000,6 @@ class WalkerActor extends Actor {
return ret;
}
/**
* Helper function for the `children` method: Read backward in the sibling
* list into an array with `count` items, including the current node.
*/
_readBackward(walker, count) {
const ret = [];
let node = walker.currentNode;
do {
if (!walker.isSkippedNode(node)) {
// The walker can be on a node that would be filtered out if it didn't find any
// other node to fallback to.
ret.push(node);
}
node = walker.previousSibling();
} while (node && --count);
ret.reverse();
return ret;
}
/**
* Return the first node in the document that matches the given selector.
* See https://developer.mozilla.org/en-US/docs/Web/API/Element.querySelector

View File

@ -56,8 +56,10 @@ class DocumentFragment : public FragmentOrElement {
Init();
}
virtual JSObject* WrapNode(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
NS_IMPL_FROMNODE_HELPER(DocumentFragment, IsDocumentFragment());
JSObject* WrapNode(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
nsresult BindToTree(BindContext&, nsINode& aParent) override {
NS_ASSERTION(false, "Trying to bind a fragment to a tree");

View File

@ -22,7 +22,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1571650
info("Test the element which became to anonymous");
const mozCustomContentContainerEl =
[...SpecialPowers.InspectorUtils.getChildrenForNode(document.documentElement, true)]
[...SpecialPowers.InspectorUtils.getChildrenForNode(document.documentElement, true, false)]
.find(n => n.classList && n.classList.contains("moz-custom-content-container"));
const targetEl = mozCustomContentContainerEl.querySelector(".set-style-test");

View File

@ -50,8 +50,9 @@ namespace InspectorUtils {
boolean isIgnorableWhitespace(CharacterData dataNode);
Node? getParentForNode(Node node, boolean showingAnonymousContent);
[NewObject] NodeList getChildrenForNode(Node node,
boolean showingAnonymousContent);
sequence<Node> getChildrenForNode(Node node,
boolean showingAnonymousContent,
boolean includeAssignedNodes);
[Throws] boolean setContentState(Element element, unsigned long long state);
[Throws] boolean removeContentState(
Element element,

View File

@ -31,7 +31,7 @@ let scrollbarThumb;
add_setup(async function() {
scrollbar = document.getElementById("scrollbar");
scrollbarThumb = null;
for (let child of SpecialPowers.InspectorUtils.getChildrenForNode(scrollbar, true)) {
for (let child of SpecialPowers.InspectorUtils.getChildrenForNode(scrollbar, true, false)) {
if (child.nodeName === "slider") {
scrollbarThumb = SpecialPowers.unwrap(child.childNodes[0]);
}

View File

@ -20,10 +20,7 @@ using namespace dom;
nsresult SVGAnimatedLengthList::SetBaseValueString(const nsAString& aValue) {
SVGLengthList newBaseValue;
nsresult rv = newBaseValue.SetValueFromString(aValue);
if (NS_FAILED(rv)) {
return rv;
}
MOZ_TRY(newBaseValue.SetValueFromString(aValue));
DOMSVGAnimatedLengthList* domWrapper =
DOMSVGAnimatedLengthList::GetDOMWrapperIfExists(this);
@ -39,14 +36,8 @@ nsresult SVGAnimatedLengthList::SetBaseValueString(const nsAString& aValue) {
// We don't need to call DidChange* here - we're only called by
// SVGElement::ParseAttribute under Element::SetAttr,
// which takes care of notifying.
rv = mBaseVal.CopyFrom(newBaseValue);
if (NS_FAILED(rv) && domWrapper) {
// Attempting to increase mBaseVal's length failed - reduce domWrapper
// back to the same length:
domWrapper->InternalBaseValListWillChangeTo(mBaseVal);
}
return rv;
mBaseVal.SwapWith(newBaseValue);
return NS_OK;
}
void SVGAnimatedLengthList::ClearBaseValue(uint32_t aAttrEnum) {

View File

@ -19,10 +19,7 @@ namespace mozilla {
nsresult SVGAnimatedNumberList::SetBaseValueString(const nsAString& aValue) {
SVGNumberList newBaseValue;
nsresult rv = newBaseValue.SetValueFromString(aValue);
if (NS_FAILED(rv)) {
return rv;
}
MOZ_TRY(newBaseValue.SetValueFromString(aValue));
DOMSVGAnimatedNumberList* domWrapper =
DOMSVGAnimatedNumberList::GetDOMWrapperIfExists(this);
@ -40,13 +37,8 @@ nsresult SVGAnimatedNumberList::SetBaseValueString(const nsAString& aValue) {
// which takes care of notifying.
mIsBaseSet = true;
rv = mBaseVal.CopyFrom(newBaseValue);
if (NS_FAILED(rv) && domWrapper) {
// Attempting to increase mBaseVal's length failed - reduce domWrapper
// back to the same length:
domWrapper->InternalBaseValListWillChangeTo(mBaseVal);
}
return rv;
mBaseVal.SwapWith(newBaseValue);
return NS_OK;
}
void SVGAnimatedNumberList::ClearBaseValue(uint32_t aAttrEnum) {

View File

@ -25,7 +25,6 @@ nsresult SVGAnimatedPathSegList::SetBaseValueString(const nsAString& aValue) {
// The spec says that the path data is parsed and accepted up to the first
// error encountered, so we don't return early if an error occurs. However,
// we do want to throw any error code from setAttribute if there's a problem.
nsresult rv = newBaseValue.SetValueFromString(aValue);
// We must send these notifications *before* changing mBaseVal! Our baseVal's
@ -56,20 +55,7 @@ nsresult SVGAnimatedPathSegList::SetBaseValueString(const nsAString& aValue) {
// SVGElement::ParseAttribute under Element::SetAttr,
// which takes care of notifying.
nsresult rv2 = mBaseVal.CopyFrom(newBaseValue);
if (NS_FAILED(rv2)) {
if (StaticPrefs::dom_svg_pathSeg_enabled()) {
// Attempting to increase mBaseVal's length failed (mBaseVal is left
// unmodified). We MUST keep any DOM wrappers in sync:
if (baseValWrapper) {
baseValWrapper->InternalListWillChangeTo(mBaseVal);
}
if (animValWrapper) {
animValWrapper->InternalListWillChangeTo(mBaseVal);
}
}
return rv2;
}
mBaseVal.SwapWith(newBaseValue);
return rv;
}
@ -177,7 +163,7 @@ SMILValue SVGAnimatedPathSegList::SMILAnimatedPathSegList::GetBaseValue()
SMILValue val;
SMILValue tmp(SVGPathSegListSMILType::Singleton());
SVGPathDataAndInfo* list = static_cast<SVGPathDataAndInfo*>(tmp.mU.mPtr);
auto* list = static_cast<SVGPathDataAndInfo*>(tmp.mU.mPtr);
nsresult rv = list->CopyFrom(mVal->mBaseVal);
if (NS_SUCCEEDED(rv)) {
list->SetElement(mElement);

View File

@ -54,18 +54,7 @@ nsresult SVGAnimatedPointList::SetBaseValueString(const nsAString& aValue) {
// SVGElement::ParseAttribute under Element::SetAttr,
// which takes care of notifying.
nsresult rv2 = mBaseVal.CopyFrom(newBaseValue);
if (NS_FAILED(rv2)) {
// Attempting to increase mBaseVal's length failed (mBaseVal is left
// unmodified). We MUST keep any DOM wrappers in sync:
if (baseValWrapper) {
baseValWrapper->InternalListWillChangeTo(mBaseVal);
}
if (animValWrapper) {
animValWrapper->InternalListWillChangeTo(mBaseVal);
}
return rv2;
}
mBaseVal.SwapWith(newBaseValue);
return rv;
}
@ -165,7 +154,7 @@ SMILValue SVGAnimatedPointList::SMILAnimatedPointList::GetBaseValue() const {
SMILValue val;
SMILValue tmp(&SVGPointListSMILType::sSingleton);
SVGPointListAndInfo* list = static_cast<SVGPointListAndInfo*>(tmp.mU.mPtr);
auto* list = static_cast<SVGPointListAndInfo*>(tmp.mU.mPtr);
nsresult rv = list->CopyFrom(mVal->mBaseVal);
if (NS_SUCCEEDED(rv)) {
list->SetInfo(mElement);

View File

@ -56,7 +56,8 @@ nsresult SVGLengthList::SetValueFromString(const nsAString& aValue) {
if (tokenizer.separatorAfterCurrentToken()) {
return NS_ERROR_DOM_SYNTAX_ERR; // trailing comma
}
return CopyFrom(temp);
mLengths = std::move(temp.mLengths);
return NS_OK;
}
bool SVGLengthList::operator==(const SVGLengthList& rhs) const {

View File

@ -85,7 +85,10 @@ class SVGLengthList {
* This may fail on OOM if the internal capacity needs to be increased, in
* which case the list will be left unmodified.
*/
nsresult CopyFrom(const SVGLengthList& rhs);
nsresult CopyFrom(const SVGLengthList&);
void SwapWith(SVGLengthList& aOther) {
mLengths.SwapElements(aOther.mLengths);
}
SVGLength& operator[](uint32_t aIndex) { return mLengths[aIndex]; }

View File

@ -58,7 +58,8 @@ nsresult SVGNumberList::SetValueFromString(const nsAString& aValue) {
if (tokenizer.separatorAfterCurrentToken()) {
return NS_ERROR_DOM_SYNTAX_ERR; // trailing comma
}
return CopyFrom(temp);
mNumbers = std::move(temp.mNumbers);
return NS_OK;
}
} // namespace mozilla

View File

@ -84,6 +84,7 @@ class SVGNumberList {
* which case the list will be left unmodified.
*/
nsresult CopyFrom(const SVGNumberList& rhs);
void SwapWith(SVGNumberList& aRhs) { mNumbers.SwapElements(aRhs.mNumbers); }
float& operator[](uint32_t aIndex) { return mNumbers[aIndex]; }

View File

@ -213,6 +213,7 @@ class SVGPathData {
* which case the list will be left unmodified.
*/
nsresult CopyFrom(const SVGPathData& rhs);
void SwapWith(SVGPathData& aRhs) { mData.SwapElements(aRhs.mData); }
float& operator[](uint32_t aIndex) { return mData[aIndex]; }

View File

@ -81,6 +81,7 @@ class SVGPointList {
* which case the list will be left unmodified.
*/
nsresult CopyFrom(const SVGPointList& rhs);
void SwapWith(SVGPointList& aRhs) { mItems.SwapElements(aRhs.mItems); }
SVGPoint& operator[](uint32_t aIndex) { return mItems[aIndex]; }

View File

@ -9,12 +9,14 @@
#include "inLayoutUtils.h"
#include "gfxTextRun.h"
#include "mozilla/dom/HTMLSlotElement.h"
#include "nsArray.h"
#include "nsContentList.h"
#include "nsString.h"
#include "nsIContentInlines.h"
#include "nsIScrollableFrame.h"
#include "mozilla/dom/Document.h"
#include "mozilla/dom/HTMLTemplateElement.h"
#include "ChildIterator.h"
#include "nsComputedDOMStyle.h"
#include "mozilla/EventStateManager.h"
@ -142,32 +144,81 @@ bool InspectorUtils::IsIgnorableWhitespace(CharacterData& aDataNode) {
/* static */
nsINode* InspectorUtils::GetParentForNode(nsINode& aNode,
bool aShowingAnonymousContent) {
if (nsINode* parent = aNode.GetParentNode()) {
return parent;
}
if (aNode.IsDocument()) {
return inLayoutUtils::GetContainerFor(*aNode.AsDocument());
}
if (aShowingAnonymousContent && aNode.IsContent()) {
return aNode.AsContent()->GetFlattenedTreeParentNode();
if (aShowingAnonymousContent) {
if (auto* frag = DocumentFragment::FromNode(aNode)) {
// This deals with shadow roots and HTMLTemplateElement.content.
return frag->GetHost();
}
}
// Ok, just get the normal DOM parent node
return aNode.GetParentNode();
return nullptr;
}
/* static */
already_AddRefed<nsINodeList> InspectorUtils::GetChildrenForNode(
nsINode& aNode, bool aShowingAnonymousContent) {
nsCOMPtr<nsINodeList> kids;
if (aShowingAnonymousContent && aNode.IsContent()) {
// XXX It's weird that `aShowingAnonymousContent` really means "show the
// flat tree", but alright.
AllChildrenIterator iter(aNode.AsContent(), nsIContent::eAllChildren);
RefPtr list = new nsSimpleContentList(&aNode);
while (nsIContent* kid = iter.GetNextChild()) {
list->AppendElement(kid);
void InspectorUtils::GetChildrenForNode(nsINode& aNode,
bool aShowingAnonymousContent,
bool aIncludeAssignedNodes,
bool aIncludeSubdocuments,
nsTArray<RefPtr<nsINode>>& aResult) {
if (aIncludeSubdocuments) {
if (auto* doc = inLayoutUtils::GetSubDocumentFor(&aNode)) {
aResult.AppendElement(doc);
// XXX Do we really want to early-return?
return;
}
return list.forget();
}
return do_AddRef(aNode.ChildNodes());
if (!aShowingAnonymousContent || !aNode.IsContent()) {
for (nsINode* child = aNode.GetFirstChild(); child;
child = child->GetNextSibling()) {
aResult.AppendElement(child);
}
return;
}
if (auto* tmpl = HTMLTemplateElement::FromNode(aNode)) {
aResult.AppendElement(tmpl->Content());
// XXX Do we really want to early-return?
return;
}
if (auto* element = Element::FromNode(aNode)) {
if (auto* shadow = element->GetShadowRoot()) {
aResult.AppendElement(shadow);
}
}
nsIContent* parent = aNode.AsContent();
if (auto* node = nsLayoutUtils::GetMarkerPseudo(parent)) {
aResult.AppendElement(node);
}
if (auto* node = nsLayoutUtils::GetBeforePseudo(parent)) {
aResult.AppendElement(node);
}
if (aIncludeAssignedNodes) {
if (auto* slot = HTMLSlotElement::FromNode(aNode)) {
for (nsINode* node : slot->AssignedNodes()) {
aResult.AppendElement(node);
}
}
}
for (nsIContent* node = parent->GetFirstChild(); node;
node = node->GetNextSibling()) {
aResult.AppendElement(node);
}
AutoTArray<nsIContent*, 4> anonKids;
nsContentUtils::AppendNativeAnonymousChildren(parent, anonKids,
nsIContent::eAllChildren);
for (nsIContent* node : anonKids) {
aResult.AppendElement(node);
}
if (auto* node = nsLayoutUtils::GetAfterPseudo(parent)) {
aResult.AppendElement(node);
}
}
/* static */

View File

@ -183,13 +183,18 @@ class InspectorUtils {
return GetParentForNode(aNode, aShowingAnonymousContent);
}
static already_AddRefed<nsINodeList> GetChildrenForNode(
GlobalObject& aGlobalObject, nsINode& aNode,
bool aShowingAnonymousContent) {
return GetChildrenForNode(aNode, aShowingAnonymousContent);
static void GetChildrenForNode(GlobalObject&, nsINode& aNode,
bool aShowingAnonymousContent,
bool aIncludeAssignedNodes,
nsTArray<RefPtr<nsINode>>& aResult) {
return GetChildrenForNode(aNode, aShowingAnonymousContent,
aIncludeAssignedNodes,
/* aIncludeSubdocuments = */ true, aResult);
}
static already_AddRefed<nsINodeList> GetChildrenForNode(
nsINode& aNode, bool aShowingAnonymousContent);
static void GetChildrenForNode(nsINode& aNode, bool aShowingAnonymousContent,
bool aIncludeAssignedNodes,
bool aIncludeSubdocuments,
nsTArray<RefPtr<nsINode>>& aResult);
/**
* Setting and removing content state on an element. Both these functions

View File

@ -27,12 +27,7 @@ using mozilla::dom::InspectorUtils;
////////////////////////////////////////////////////
inDeepTreeWalker::inDeepTreeWalker()
: mShowAnonymousContent(false),
mShowSubDocuments(false),
mShowDocumentsAsNodes(false),
mCurrentIndex(-1) {}
inDeepTreeWalker::inDeepTreeWalker() = default;
inDeepTreeWalker::~inDeepTreeWalker() = default;
NS_IMPL_ISUPPORTS(inDeepTreeWalker, inIDeepTreeWalker)
@ -113,14 +108,13 @@ already_AddRefed<nsINode> inDeepTreeWalker::GetParent() {
nsINode* parentNode =
InspectorUtils::GetParentForNode(*mCurrentNode, mShowAnonymousContent);
uint16_t nodeType = 0;
if (parentNode) {
nodeType = parentNode->NodeType();
if (!parentNode) {
return nullptr;
}
// For compatibility reasons by default we skip the document nodes
// from the walk.
if (!mShowDocumentsAsNodes && nodeType == nsINode::DOCUMENT_NODE &&
if (!mShowDocumentsAsNodes && parentNode->IsDocument() &&
parentNode != mRoot) {
parentNode =
InspectorUtils::GetParentForNode(*parentNode, mShowAnonymousContent);
@ -129,77 +123,56 @@ already_AddRefed<nsINode> inDeepTreeWalker::GetParent() {
return do_AddRef(parentNode);
}
static already_AddRefed<nsINodeList> GetChildren(nsINode* aParent,
bool aShowAnonymousContent,
bool aShowSubDocuments) {
MOZ_ASSERT(aParent);
if (aShowSubDocuments) {
if (auto* doc = inLayoutUtils::GetSubDocumentFor(aParent)) {
aParent = doc;
}
void inDeepTreeWalker::GetChildren(nsINode& aParent, ChildList& aChildList) {
aChildList.ClearAndRetainStorage();
InspectorUtils::GetChildrenForNode(aParent, mShowAnonymousContent,
/* aIncludeAssignedNodes = */ false,
mShowSubDocuments, aChildList);
if (aChildList.Length() == 1 && aChildList.ElementAt(0)->IsDocument() &&
!mShowDocumentsAsNodes) {
RefPtr parent = aChildList.ElementAt(0);
aChildList.ClearAndRetainStorage();
InspectorUtils::GetChildrenForNode(*parent, mShowAnonymousContent,
/* aIncludeAssignedNodes = */ false,
mShowSubDocuments, aChildList);
}
return InspectorUtils::GetChildrenForNode(*aParent, aShowAnonymousContent);
}
NS_IMETHODIMP
inDeepTreeWalker::SetCurrentNode(nsINode* aCurrentNode) {
// mCurrentNode can only be null if init either failed, or has not been
// called yet.
// mCurrentNode can only be null if init either failed, or has not been called
// yet.
if (!mCurrentNode || !aCurrentNode) {
return NS_ERROR_FAILURE;
}
// If Document nodes are skipped by the walk, we should not allow
// one to set one as the current node either.
// If Document nodes are skipped by the walk, we should not allow one to set
// one as the current node either.
if (!mShowDocumentsAsNodes) {
if (aCurrentNode->IsDocument()) {
return NS_ERROR_FAILURE;
}
}
return SetCurrentNode(aCurrentNode, nullptr);
}
nsresult inDeepTreeWalker::SetCurrentNode(nsINode* aCurrentNode,
nsINodeList* aSiblings) {
MOZ_ASSERT(aCurrentNode);
// We want to store the original state so in case of error
// we can restore that.
nsCOMPtr<nsINodeList> tmpSiblings = mSiblings;
nsCOMPtr<nsINode> tmpCurrent = mCurrentNode;
mSiblings = aSiblings;
ChildList oldSiblings;
mSiblings.SwapElements(oldSiblings);
nsCOMPtr<nsINode> oldCurrent = std::move(mCurrentNode);
mCurrentNode = aCurrentNode;
// If siblings were not passed in as argument we have to
// get them from the parent node of aCurrentNode.
// Note: in the mShowDoucmentsAsNodes case when a sub document
// is set as the current, we don't want to get the children
// from the iframe accidentally here, so let's just skip this
// part for document nodes, they should never have siblings.
if (!mSiblings) {
if (!aCurrentNode->IsDocument()) {
if (nsCOMPtr<nsINode> parent = GetParent()) {
mSiblings =
GetChildren(parent, mShowAnonymousContent, mShowSubDocuments);
}
}
}
if (mSiblings && mSiblings->Length()) {
if (RefPtr<nsINode> parent = GetParent()) {
GetChildren(*parent, mSiblings);
// We cached all the siblings (if there are any) of the current node, but we
// still have to set the index too, to be able to iterate over them.
nsCOMPtr<nsIContent> currentAsContent = do_QueryInterface(mCurrentNode);
MOZ_ASSERT(currentAsContent);
int32_t index = mSiblings->IndexOf(currentAsContent);
int32_t index = mSiblings.IndexOf(mCurrentNode);
if (index < 0) {
// If someone tries to set current node to some value that is not
// reachable otherwise, let's throw. (For example mShowAnonymousContent is
// false and some NAC was passed in)
// false and some NAC was passed in).
// Restore state first.
mCurrentNode = tmpCurrent;
mSiblings = tmpSiblings;
mCurrentNode = std::move(oldCurrent);
oldSiblings.SwapElements(mSiblings);
return NS_ERROR_INVALID_ARG;
}
mCurrentIndex = index;
@ -217,13 +190,11 @@ inDeepTreeWalker::ParentNode(nsINode** _retval) {
}
nsCOMPtr<nsINode> parent = GetParent();
if (!parent) {
return NS_OK;
}
nsresult rv = SetCurrentNode(parent);
NS_ENSURE_SUCCESS(rv, rv);
MOZ_TRY(SetCurrentNode(parent));
parent.forget(_retval);
return NS_OK;
@ -238,29 +209,15 @@ nsresult inDeepTreeWalker::EdgeChild(nsINode** _retval, bool aFront) {
*_retval = nullptr;
nsCOMPtr<nsINode> echild;
if (mShowSubDocuments && mShowDocumentsAsNodes) {
// GetChildren below, will skip the document node from
// the walk. But if mShowDocumentsAsNodes is set to true
// we want to include the (sub)document itself too.
echild = inLayoutUtils::GetSubDocumentFor(mCurrentNode);
ChildList children;
GetChildren(*mCurrentNode, children);
if (children.IsEmpty()) {
return NS_OK;
}
nsCOMPtr<nsINodeList> children;
if (!echild) {
children =
GetChildren(mCurrentNode, mShowAnonymousContent, mShowSubDocuments);
if (children && children->Length() > 0) {
echild = children->Item(aFront ? 0 : children->Length() - 1);
}
}
if (echild) {
nsresult rv = SetCurrentNode(echild, children);
NS_ENSURE_SUCCESS(rv, rv);
NS_ADDREF(*_retval = mCurrentNode);
}
mSiblings = std::move(children);
mCurrentIndex = aFront ? 0 : mSiblings.Length() - 1;
mCurrentNode = mSiblings.ElementAt(mCurrentIndex);
NS_ADDREF(*_retval = mCurrentNode);
return NS_OK;
}
@ -277,11 +234,11 @@ inDeepTreeWalker::LastChild(nsINode** _retval) {
NS_IMETHODIMP
inDeepTreeWalker::PreviousSibling(nsINode** _retval) {
*_retval = nullptr;
if (!mCurrentNode || !mSiblings || mCurrentIndex < 1) {
if (!mCurrentNode || mCurrentIndex < 1) {
return NS_OK;
}
nsIContent* prev = mSiblings->Item(--mCurrentIndex);
nsINode* prev = mSiblings.ElementAt(--mCurrentIndex);
mCurrentNode = prev;
NS_ADDREF(*_retval = mCurrentNode);
return NS_OK;
@ -290,12 +247,11 @@ inDeepTreeWalker::PreviousSibling(nsINode** _retval) {
NS_IMETHODIMP
inDeepTreeWalker::NextSibling(nsINode** _retval) {
*_retval = nullptr;
if (!mCurrentNode || !mSiblings ||
mCurrentIndex + 1 >= (int32_t)mSiblings->Length()) {
if (!mCurrentNode || mCurrentIndex + 1 >= (int32_t)mSiblings.Length()) {
return NS_OK;
}
nsIContent* next = mSiblings->Item(++mCurrentIndex);
nsINode* next = mSiblings.ElementAt(++mCurrentIndex);
mCurrentNode = next;
NS_ADDREF(*_retval = mCurrentNode);
return NS_OK;

View File

@ -22,7 +22,8 @@ class inDeepTreeWalker final : public inIDeepTreeWalker {
inDeepTreeWalker();
nsresult SetCurrentNode(nsINode* aCurrentNode, nsINodeList* aSiblings);
using ChildList = AutoTArray<RefPtr<nsINode>, 8>;
void GetChildren(nsINode& aParent, ChildList&);
protected:
virtual ~inDeepTreeWalker();
@ -30,9 +31,9 @@ class inDeepTreeWalker final : public inIDeepTreeWalker {
already_AddRefed<nsINode> GetParent();
nsresult EdgeChild(nsINode** _retval, bool aReverse);
bool mShowAnonymousContent;
bool mShowSubDocuments;
bool mShowDocumentsAsNodes;
bool mShowAnonymousContent = false;
bool mShowSubDocuments = false;
bool mShowDocumentsAsNodes = false;
// The root node. previousNode and parentNode will return
// null from here.
@ -43,15 +44,10 @@ class inDeepTreeWalker final : public inIDeepTreeWalker {
// Notes: normally siblings are all the children of the parent
// of mCurrentNode (that are interesting for use for the walk)
// and mCurrentIndex is the index of mCurrentNode in that list
// But if mCurrentNode is a (sub) document then instead of
// storing a list that has only one element (the document)
// and setting mCurrentIndex to null, we set mSibilings to null.
// The reason for this is purely technical, since nsINodeList is
// nsIContent based hence we cannot use it to store a document node.
nsCOMPtr<nsINodeList> mSiblings;
ChildList mSiblings;
// Index of mCurrentNode in the mSiblings list.
int32_t mCurrentIndex;
int32_t mCurrentIndex = -1;
};
// {BFCB82C2-5611-4318-90D6-BAF4A7864252}

View File

@ -20,7 +20,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=522601
<iframe id="frame1" src="file_bug522601.html">frame text</iframe>
</div>
<pre id="test">
<script type="application/javascript">
<script>
<![CDATA[
/** Test for Bug 522601 **/
@ -49,7 +49,7 @@ addLoadEvent(function() {
.createInstance(SpecialPowers.Ci.inIDeepTreeWalker);
walkerSubDocument.showAnonymousContent = false;
walkerSubDocument.showSubDocuments = true;
walkerSubDocument.init($("frame1"), NodeFilter.SHOW_ALL);
walkerSubDocument.init($("frame1"));
is(SpecialPowers.unwrap(walkerSubDocument.currentNode), $("frame1"), "Unexpected sub-doc root");
testFunc(walkerSubDocument, "firstChild", $("frame1").contentDocument.doctype,
@ -63,7 +63,7 @@ addLoadEvent(function() {
walkerSubDocument.showAnonymousContent = false;
walkerSubDocument.showSubDocuments = true;
walkerSubDocument.showDocumentsAsNodes = true;
walkerSubDocument.init($("frame1"), NodeFilter.SHOW_ALL);
walkerSubDocument.init($("frame1"));
is(SpecialPowers.unwrap(walkerSubDocument.currentNode), $("frame1"), "Unexpected sub-doc root");
testFunc(walkerSubDocument, "firstChild", $("frame1").contentDocument,
@ -84,7 +84,7 @@ addLoadEvent(function() {
.createInstance(SpecialPowers.Ci.inIDeepTreeWalker);
walkerFrameChild.showAnonymousContent = false;
walkerFrameChild.showSubDocuments = false;
walkerFrameChild.init($("frame1"), NodeFilter.SHOW_ALL);
walkerFrameChild.init($("frame1"));
is(SpecialPowers.unwrap(walkerFrameChild.currentNode), $("frame1"), "Unexpected sub-doc root");
testFunc(walkerFrameChild, "firstChild", $("frame1").firstChild,
@ -93,7 +93,7 @@ addLoadEvent(function() {
var walkerNonAnon =
SpecialPowers.Cc["@mozilla.org/inspector/deep-tree-walker;1"]
.createInstance(SpecialPowers.Ci.inIDeepTreeWalker);
walkerNonAnon.init($("display"), NodeFilter.SHOW_ALL);
walkerNonAnon.init($("display"));
walkerNonAnon.showAnonymousContent = false;
is(SpecialPowers.unwrap(walkerNonAnon.currentNode), $("display"), "Unexpected non-anon root");
@ -138,6 +138,7 @@ addLoadEvent(function() {
// Move the walker over to the end
while (walkerNonAnon.nextNode()) { /* do nothing */ }
is(SpecialPowers.unwrap(walkerNonAnon.currentNode), $("i2").firstChild, "unexpected last node");
testFunc(walkerNonAnon, "previousNode", $("i2"), "step back to second italic");
testFunc(walkerNonAnon, "previousNode", $("i1").nextSibling,
@ -184,14 +185,18 @@ addLoadEvent(function() {
SpecialPowers.Cc["@mozilla.org/inspector/deep-tree-walker;1"]
.createInstance(SpecialPowers.Ci.inIDeepTreeWalker);
walkerAnon.showAnonymousContent = true;
walkerAnon.init($("display"), NodeFilter.SHOW_ALL);
walkerAnon.init($("display"));
is(SpecialPowers.unwrap(walkerAnon.currentNode), $("display"), "Unexpected anon root");
testFunc(walkerAnon, "nextNode", $("display").shadowRoot,
"step to shadow root");
testFunc(walkerAnon, "nextNode", anonDiv,
"step to anonymous div");
testFunc(walkerAnon, "nextNode", slot, "step into slot");
testFunc(walkerAnon, "nextNode", $("s").previousSibling,
"step to some text (anon)");
testFunc(walkerAnon, "nextNode", namedSlot, "step into named slot");
testFunc(walkerAnon, "nextNode", $("s").previousSibling, "step to light dom text (out of shadow tree)");
testFunc(walkerAnon, "nextNode", $("s"), "step to span (anon)");
testFunc(walkerAnon, "nextNode", $("s").firstChild, "step to span text (anon)");
testFunc(walkerAnon, "nextNode", $("s").nextSibling, "step to more text (anon)");
testFunc(walkerAnon, "nextNode", $("b"), "step to bold (anon)");
testFunc(walkerAnon, "nextNode", $("b").firstChild, "step to bold text (anon)");
@ -203,32 +208,38 @@ addLoadEvent(function() {
testFunc(walkerAnon, "nextNode", $("i2"), "step to second italic (anon)");
testFunc(walkerAnon, "nextNode", $("i2").firstChild,
"step to second italic text (anon)");
testFunc(walkerAnon, "nextNode", namedSlot, "step into named slot");
testFunc(walkerAnon, "nextNode", $("s"), "step to span (anon)");
testFunc(walkerAnon, "nextNode", $("s").firstChild, "step to span text (anon)");
testFunc(walkerAnon, "nextNode", null, "step past end (anon)");
testFunc(walkerAnon, "parentNode", $("s"), "step up to span (anon)");
testFunc(walkerAnon, "parentNode", namedSlot, "step up to named slot");
testFunc(walkerAnon, "parentNode", $("i2"), "step up to italic (anon)");
testFunc(walkerAnon, "parentNode", $("b"), "step up to bold (anon)");
testFunc(walkerAnon, "parentNode", $("display"), "step up to display (anon)");
testFunc(walkerAnon, "nextNode", anonDiv, "step to anonymous div again");
testFunc(walkerAnon, "nextNode", $("display").shadowRoot, "step to shadow root again");
testFunc(walkerAnon, "parentNode", $("display"),
"step up to display again (anon)");
"step up to display again (anon)")
testFunc(walkerAnon, "parentNode", null, "step up past root (anon)");
testFunc(walkerAnon, "firstChild", anonDiv,
testFunc(walkerAnon, "firstChild", $("display").shadowRoot,
"step firstChild to display first child (anon)");
testFunc(walkerAnon, "nextSibling", namedSlot,
"step nextSibling named slot");
testFunc(walkerAnon, "nextSibling", $("s").previousSibling,
"step nextSibling text (anon)");
testFunc(walkerAnon, "nextSibling", $("s"),
"step nextSibling span (anon)");
testFunc(walkerAnon, "nextSibling", $("s").nextSibling,
"step nextSibling more text (anon)");
testFunc(walkerAnon, "nextSibling", $("b"),
"step nextSibling bold (anon)");
testFunc(walkerAnon, "nextSibling", null, "step nextSibling past end (anon)");
testFunc(walkerAnon, "previousSibling", anonDiv,
"step previousSibling to anonymous div");
testFunc(walkerAnon, "previousSibling", $("s").nextSibling,
"step previousSibling to more text");
testFunc(walkerAnon, "previousSibling", $("s"),
"step previousSibling to span");
testFunc(walkerAnon, "previousSibling", $("s").previousSibling,
"step previousSibling to prev text");
testFunc(walkerAnon, "previousSibling", $("display").shadowRoot,
"step shadowRoot");
testFunc(walkerAnon, "previousSibling", null, "step previousSibling past end (anon)");
// Move the walker over to the end
while (walkerAnon.nextNode()) { /* do nothing */ }
testFunc(walkerAnon, "previousNode", $("s"), "step back to span (anon)");
testFunc(walkerAnon, "previousNode", namedSlot, "step back to named slot");
testFunc(walkerAnon, "previousNode", $("i2").firstChild,
"step back to second italic text (anon)");
testFunc(walkerAnon, "previousNode", $("i2"), "step back to second italic (anon)");
testFunc(walkerAnon, "previousNode", $("i1").nextSibling,
"step back to more bold text (anon)");
@ -238,11 +249,17 @@ addLoadEvent(function() {
testFunc(walkerAnon, "previousNode", $("b").firstChild, "step back to bold text (anon)");
testFunc(walkerAnon, "previousNode", $("b"), "step back to bold (anon)");
testFunc(walkerAnon, "previousNode", $("s").nextSibling, "step back to more text (anon)");
testFunc(walkerAnon, "previousNode", $("s").firstChild,
"step back to span text (anon)");
testFunc(walkerAnon, "previousNode", $("s"),
"step back to span (anon)");
testFunc(walkerAnon, "previousNode", $("s").previousSibling,
"step back to some text (anon)");
testFunc(walkerAnon, "previousNode", slot, "steb back to slot");
testFunc(walkerAnon, "previousNode", namedSlot, "step back to named slot");
testFunc(walkerAnon, "previousNode", slot, "step back to slot");
testFunc(walkerAnon, "previousNode", anonDiv,
"step back to anonymous div");
testFunc(walkerAnon, "previousNode", $("display").shadowRoot, "step back to shadow root (anon)");
testFunc(walkerAnon, "previousNode", $("display"), "step back to root (anon)");
testFunc(walkerAnon, "previousNode", null, "step back past root (anon)");

View File

@ -19,7 +19,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=609549
</div>
<pre id="test">
<script type="application/javascript">
<script>
<![CDATA[
/** Test for Bug 609549 **/
@ -39,16 +39,22 @@ const InspectorUtils = SpecialPowers.InspectorUtils;
addLoadEvent(function() {
ok("getChildrenForNode" in InspectorUtils, "InspectorUtils has no getChildrenForNode");
var withoutAnons =
SpecialPowers.unwrap(InspectorUtils.getChildrenForNode($("bound"), false));
InspectorUtils.getChildrenForNode($("bound"), false, false);
is(withoutAnons.length, $("bound").childNodes.length,
"withoutAnons should be the same length as childNodes");
is(withoutAnons[0], $("p"), "didn't get paragraph - without anons");
is(withoutAnons[1], $("sandwiched"),
is(SpecialPowers.unwrap(withoutAnons[0]), $("p"), "didn't get paragraph - without anons");
is(SpecialPowers.unwrap(withoutAnons[1]), $("sandwiched"),
"didn't get sandwiched span - without anons");
var withAnons = InspectorUtils.getChildrenForNode($("bound"), true);
var withAnons = InspectorUtils.getChildrenForNode($("bound"), true, false);
is(withAnons.length, 3, "bad withAnons.length");
ok(SpecialPowers.unwrap(withAnons[0]) instanceof ShadowRoot, "First one is shadow");
is(SpecialPowers.unwrap(withAnons[1]), $("p"), "didn't get paragraph - without anons");
is(SpecialPowers.unwrap(withAnons[2]), $("sandwiched"),
"didn't get sandwiched span - without anons");
withAnons = InspectorUtils.getChildrenForNode(withAnons[0], true, false);
is(withAnons.length, 4, "bad withAnons.length");
is(withAnons[0].getAttribute("anonid"), "box-A",
"didn't get anonymous box-A");
@ -58,7 +64,7 @@ addLoadEvent(function() {
"didn't get anonymous box-C");
is(withAnons[3].assignedNodes()[0].id, "p", "didn't get paragraph - with anons");
var bKids = InspectorUtils.getChildrenForNode(withAnons[1], true)[0].assignedNodes();
var bKids = InspectorUtils.getChildrenForNode(withAnons[1], true, false)[0].assignedNodes();
is(bKids.length, 1, "bKids.length is bad");
is(SpecialPowers.unwrap(bKids[0]), $("sandwiched"),
"didn't get sandwiched span inserted into box-B");

View File

@ -25,7 +25,7 @@ domWinUtils.loadSheetUsingURIString('data:text/css,@namespace url("http://www.mo
function init()
{
downButton = SpecialPowers.unwrap(
SpecialPowers.InspectorUtils.getChildrenForNode(scrollbar, true)[4]);
SpecialPowers.InspectorUtils.getChildrenForNode(scrollbar, true, false)[4]);
if (!downButton) {
ok(navigator.userAgent.indexOf("Linux") !== -1 ||
navigator.userAgent.indexOf("Mac") !== -1, "Theme doesn't support scrollbar buttons");

View File

@ -19,7 +19,7 @@ function doTest()
{
var scrollbar = document.getElementById("scrollbar");
var scrollbarThumb = null;
for (let child of SpecialPowers.InspectorUtils.getChildrenForNode(scrollbar, true)) {
for (let child of SpecialPowers.InspectorUtils.getChildrenForNode(scrollbar, true, false)) {
if (child.nodeName === "slider") {
scrollbarThumb = SpecialPowers.unwrap(child.childNodes[0]);
}

View File

@ -1106,4 +1106,4 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
static const int32_t kUnknownId = -1;
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1689247960566000);
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1689593716618000);

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,20 @@
{
"data": [
{
"stash": {
"blocked": [
"{0dc0c627-1368-446f-96e6-4ce8b5dc54da}:6.9",
"ydkivntjdknvladlvnalrfvn@zsltzt:0.5",
"{fac9de72-6e06-4b01-9bc1-2190875a78e8}:1.0"
],
"unblocked": []
},
"schema": 1680714898769,
"key_format": "{guid}:{version}",
"stash_time": 1680784508884,
"id": "9fc5a0ed-0200-45c8-b50c-3285ddb6b818",
"last_modified": 1680784649216
},
{
"stash": {
"blocked": [],
@ -1330,5 +1345,5 @@
"last_modified": 1673354326131
}
],
"timestamp": 1680201445669
"timestamp": 1680784649216
}

View File

@ -132,9 +132,6 @@ where
visited_handling: VisitedHandlingMode,
/// The current nesting level of selectors that we're matching.
///
/// FIXME(emilio): Consider putting the mutable stuff in a Cell, then make
/// MatchingContext immutable again.
nesting_level: usize,
/// Whether we're inside a negation or not.

View File

@ -1,2 +0,0 @@
[inheritance.html.ini]
expected: CRASH

View File

@ -2,6 +2,7 @@
// META: script=/common/get-host-info.sub.js
// META: script=resources/webtransport-test-helpers.sub.js
// META: script=/common/utils.js
// META: timeout=long
promise_test(async t => {
const id = token();

View File

@ -1,6 +1,7 @@
// META: global=window,worker
// META: script=/common/get-host-info.sub.js
// META: script=resources/webtransport-test-helpers.sub.js
// META: timeout=long
promise_test(async t => {
const wt = new WebTransport(webtransport_url('custom-response.py?:status=200'));

View File

@ -32,6 +32,10 @@ XPCOMUtils.defineLazyGetter(lazy, "logConsole", () => {
export class AddonSearchEngine extends SearchEngine {
// Whether the engine is provided by the application.
#isAppProvided = false;
// The extension ID if added by an extension.
_extensionID = null;
// The locale, or "DEFAULT", if required.
_locale = null;
/**
* Creates a AddonSearchEngine.
@ -65,6 +69,12 @@ export class AddonSearchEngine extends SearchEngine {
}
}
_initWithJSON(json) {
super._initWithJSON(json);
this._extensionID = json.extensionID || json._extensionID || null;
this._locale = json.extensionLocale || json._locale || null;
}
/**
* Call to initalise an instance with extension details. Does not need to be
* called if json has been passed to the constructor.
@ -179,6 +189,13 @@ export class AddonSearchEngine extends SearchEngine {
return this.#isAppProvided;
}
get isGeneralPurposeEngine() {
return !!(
this._extensionID &&
lazy.SearchUtils.GENERAL_SEARCH_ENGINE_IDS.has(this._extensionID)
);
}
/**
* Creates a JavaScript object that represents this engine.
*
@ -196,7 +213,10 @@ export class AddonSearchEngine extends SearchEngine {
_metaData: this._metaData,
};
}
return super.toJSON();
let json = super.toJSON();
json._extensionID = this._extensionID;
json._locale = this._locale;
return json;
}
/**

View File

@ -579,10 +579,6 @@ export class SearchEngine {
#cachedSearchForm = null;
// Whether or not to send an attribution request to the server.
_sendAttributionRequest = false;
// The extension ID if added by an extension.
_extensionID = null;
// The locale, or "DEFAULT", if required.
_locale = null;
// The order hint from the configuration (if any).
_orderHint = null;
// The telemetry id from the configuration (if any).
@ -1120,8 +1116,6 @@ export class SearchEngine {
this._definedAliases.push(json._definedAlias);
}
this._filePath = json.filePath || json._filePath || null;
this._extensionID = json.extensionID || json._extensionID || null;
this._locale = json.extensionLocale || json._locale || null;
for (let i = 0; i < json._urls.length; ++i) {
let url = json._urls[i];
@ -1154,8 +1148,6 @@ export class SearchEngine {
"_orderHint",
"_telemetryId",
"_filePath",
"_extensionID",
"_locale",
"_definedAliases",
];
@ -1334,10 +1326,7 @@ export class SearchEngine {
}
get isGeneralPurposeEngine() {
return !!(
this._extensionID &&
lazy.SearchUtils.GENERAL_SEARCH_ENGINE_IDS.has(this._extensionID)
);
return false;
}
get _hasUpdates() {

View File

@ -4,8 +4,8 @@
<title>Video controls with Audio file test</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script src="/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="head.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script src="head.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
@ -15,31 +15,12 @@
</div>
<pre id="test">
<script class="testbody" type="application/javascript">
<script>
const video = document.getElementById("video");
function findElementByAttribute(element, aName, aValue) {
if (!("getAttribute" in element)) {
return false;
}
if (element.getAttribute(aName) === aValue) {
return element;
}
let children =
InspectorUtils.getChildrenForNode(element, true);
for (let child of children) {
const result = findElementByAttribute(child, aName, aValue);
if (result) {
return result;
}
}
return false;
}
function loadedmetadata(event) {
SimpleTest.executeSoon(function() {
const controlBar = findElementByAttribute(video, "class", "controlBar");
const controlBar = SpecialPowers.wrap(video).openOrClosedShadowRoot.querySelector(".controlBar");
is(controlBar.getAttribute("fullscreen-unavailable"), "true", "Fullscreen button is hidden");
SimpleTest.finish();
});

View File

@ -36,7 +36,8 @@ button {
width: 100%;
}
button:dir(rtl) {
button:dir(rtl),
button:-moz-locale-dir(rtl) {
background-position-x: right 8px;
}

View File

@ -54,7 +54,7 @@ function runTest() {
["", "Small"].forEach(function (size) {
var elem = document.getElementById(orient + size);
var thumbRect = SpecialPowers.unwrap(
SpecialPowers.InspectorUtils.getChildrenForNode(elem, true)[0])
SpecialPowers.InspectorUtils.getChildrenForNode(elem, true, false)[0])
.childNodes[0].getBoundingClientRect();
var sizeToCheck = orient == "horizontal" ? "width" : "height";
// var expectedSize = size == "Small" ? 19 : 26;