chore: move query selectors to injection script (#8980)

This commit is contained in:
jrandolf 2022-09-19 13:22:10 +02:00 committed by GitHub
parent dda85944b8
commit 5a4eb38083
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 136 additions and 82 deletions

View File

@ -197,91 +197,29 @@ const defaultHandler = createPuppeteerQueryHandler({
});
const pierceHandler = createPuppeteerQueryHandler({
queryOne: (element, selector) => {
let found: Node | null = null;
const search = (root: Node) => {
const iter = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);
do {
const currentNode = iter.currentNode as HTMLElement;
if (currentNode.shadowRoot) {
search(currentNode.shadowRoot);
}
if (currentNode instanceof ShadowRoot) {
continue;
}
if (currentNode !== root && !found && currentNode.matches(selector)) {
found = currentNode;
}
} while (!found && iter.nextNode());
};
if (element instanceof Document) {
element = element.documentElement;
}
search(element);
return found;
queryOne: (element, selector, {pierceQuerySelector}) => {
return pierceQuerySelector(element, selector);
},
queryAll: (element, selector) => {
const result: Node[] = [];
const collect = (root: Node) => {
const iter = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);
do {
const currentNode = iter.currentNode as HTMLElement;
if (currentNode.shadowRoot) {
collect(currentNode.shadowRoot);
}
if (currentNode instanceof ShadowRoot) {
continue;
}
if (currentNode !== root && currentNode.matches(selector)) {
result.push(currentNode);
}
} while (iter.nextNode());
};
if (element instanceof Document) {
element = element.documentElement;
}
collect(element);
return result;
queryAll: (element, selector, {pierceQuerySelectorAll}) => {
return pierceQuerySelectorAll(element, selector);
},
});
const xpathHandler = createPuppeteerQueryHandler({
queryOne: (element, selector) => {
const doc = element.ownerDocument || document;
const result = doc.evaluate(
selector,
element,
null,
XPathResult.FIRST_ORDERED_NODE_TYPE
);
return result.singleNodeValue;
queryOne: (element, selector, {xpathQuerySelector}) => {
return xpathQuerySelector(element, selector);
},
queryAll: (element, selector) => {
const doc = element.ownerDocument || document;
const iterator = doc.evaluate(
selector,
element,
null,
XPathResult.ORDERED_NODE_ITERATOR_TYPE
);
const array: Node[] = [];
let item;
while ((item = iterator.iterateNext())) {
array.push(item);
}
return array;
queryAll: (element, selector, {xpathQuerySelectorAll}) => {
return xpathQuerySelectorAll(element, selector);
},
});
const textQueryHandler = createPuppeteerQueryHandler({
queryOne: (element, selector, {textQuerySelector}) => {
return textQuerySelector(selector, element);
return textQuerySelector(element, selector);
},
queryAll: (element, selector, {textQuerySelectorAll}) => {
return textQuerySelectorAll(selector, element);
return textQuerySelectorAll(element, selector);
},
});

View File

@ -0,0 +1,67 @@
// Copyright 2022 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
export const pierceQuerySelector = (
root: Node,
selector: string
): Element | null => {
let found: Node | null = null;
const search = (root: Node) => {
const iter = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);
do {
const currentNode = iter.currentNode as Element;
if (currentNode.shadowRoot) {
search(currentNode.shadowRoot);
}
if (currentNode instanceof ShadowRoot) {
continue;
}
if (currentNode !== root && !found && currentNode.matches(selector)) {
found = currentNode;
}
} while (!found && iter.nextNode());
};
if (root instanceof Document) {
root = root.documentElement;
}
search(root);
return found;
};
export const pierceQuerySelectorAll = (
element: Node,
selector: string
): Element[] => {
const result: Element[] = [];
const collect = (root: Node) => {
const iter = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);
do {
const currentNode = iter.currentNode as Element;
if (currentNode.shadowRoot) {
collect(currentNode.shadowRoot);
}
if (currentNode instanceof ShadowRoot) {
continue;
}
if (currentNode !== root && currentNode.matches(selector)) {
result.push(currentNode);
}
} while (iter.nextNode());
};
if (element instanceof Document) {
element = element.documentElement;
}
collect(element);
return result;
};

View File

@ -25,16 +25,16 @@ import {
* @internal
*/
export const textQuerySelector = (
selector: string,
root: Node
root: Node,
selector: string
): Element | null => {
for (const node of root.childNodes) {
if (node instanceof Element && isSuitableNodeForTextMatching(node)) {
let matchedNode: Element | null;
if (node.shadowRoot) {
matchedNode = textQuerySelector(selector, node.shadowRoot);
matchedNode = textQuerySelector(node.shadowRoot, selector);
} else {
matchedNode = textQuerySelector(selector, node);
matchedNode = textQuerySelector(node, selector);
}
if (matchedNode) {
return matchedNode;
@ -57,17 +57,17 @@ export const textQuerySelector = (
* @internal
*/
export const textQuerySelectorAll = (
selector: string,
root: Node
root: Node,
selector: string
): Element[] => {
let results: Element[] = [];
for (const node of root.childNodes) {
if (node instanceof Element) {
let matchedNodes: Element[];
if (node.shadowRoot) {
matchedNodes = textQuerySelectorAll(selector, node.shadowRoot);
matchedNodes = textQuerySelectorAll(node.shadowRoot, selector);
} else {
matchedNodes = textQuerySelectorAll(selector, node);
matchedNodes = textQuerySelectorAll(node, selector);
}
results = results.concat(matchedNodes);
}

View File

@ -0,0 +1,45 @@
/**
* Copyright 2022 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export const xpathQuerySelector = (
root: Node,
selector: string
): Node | null => {
const doc = root.ownerDocument || document;
const result = doc.evaluate(
selector,
root,
null,
XPathResult.FIRST_ORDERED_NODE_TYPE
);
return result.singleNodeValue;
};
export const xpathQuerySelectorAll = (root: Node, selector: string): Node[] => {
const doc = root.ownerDocument || document;
const iterator = doc.evaluate(
selector,
root,
null,
XPathResult.ORDERED_NODE_ITERATOR_TYPE
);
const array: Node[] = [];
let item;
while ((item = iterator.iterateNext())) {
array.push(item);
}
return array;
};

View File

@ -17,14 +17,18 @@
import {createDeferredPromise} from '../util/DeferredPromise.js';
import * as Poller from './Poller.js';
import * as TextContent from './TextContent.js';
import * as TextSelector from './TextSelector.js';
import * as TextQuerySelector from './TextQuerySelector.js';
import * as XPathQuerySelector from './XPathQuerySelector.js';
import * as PierceQuerySelector from './PierceQuerySelector.js';
import * as util from './util.js';
const PuppeteerUtil = Object.freeze({
...util,
...Poller,
...TextContent,
...TextSelector,
...TextQuerySelector,
...XPathQuerySelector,
...PierceQuerySelector,
createDeferredPromise,
});