mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 10:44:56 +00:00
Merge autoland to mozilla-central. a=merge
This commit is contained in:
commit
2ce39261ea
@ -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 {
|
||||
|
@ -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.
|
||||
|
@ -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 {
|
||||
|
@ -168,6 +168,7 @@ const TEST_DATA = [
|
||||
slot
|
||||
::before
|
||||
div!slotted
|
||||
default content
|
||||
::after
|
||||
::before
|
||||
class="light-dom"
|
||||
|
@ -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();
|
||||
|
@ -65,6 +65,7 @@ const TEST_DATA = [
|
||||
#shadow-root
|
||||
slot
|
||||
div!slotted
|
||||
default content
|
||||
::marker
|
||||
::before
|
||||
class="light-dom"`,
|
||||
|
@ -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"),
|
||||
|
@ -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"
|
||||
);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
@ -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");
|
||||
|
@ -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,
|
||||
|
@ -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]);
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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]; }
|
||||
|
||||
|
@ -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
|
||||
|
@ -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]; }
|
||||
|
||||
|
@ -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]; }
|
||||
|
||||
|
@ -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]; }
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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}
|
||||
|
@ -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)");
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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");
|
||||
|
@ -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]);
|
||||
}
|
||||
|
@ -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
@ -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
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -1,2 +0,0 @@
|
||||
[inheritance.html.ini]
|
||||
expected: CRASH
|
@ -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();
|
||||
|
@ -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'));
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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() {
|
||||
|
@ -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();
|
||||
});
|
||||
|
@ -36,7 +36,8 @@ button {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
button:dir(rtl) {
|
||||
button:dir(rtl),
|
||||
button:-moz-locale-dir(rtl) {
|
||||
background-position-x: right 8px;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user