mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
chore: move query selectors to injection script (#8980)
This commit is contained in:
parent
dda85944b8
commit
5a4eb38083
@ -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);
|
||||
},
|
||||
});
|
||||
|
||||
|
67
src/injected/PierceQuerySelector.ts
Normal file
67
src/injected/PierceQuerySelector.ts
Normal 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;
|
||||
};
|
@ -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);
|
||||
}
|
45
src/injected/XPathQuerySelector.ts
Normal file
45
src/injected/XPathQuerySelector.ts
Normal 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;
|
||||
};
|
@ -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,
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user