Skip to content

Commit

Permalink
fix: xpath queries should be atomic (#11101)
Browse files Browse the repository at this point in the history
  • Loading branch information
OrKoN committed Oct 9, 2023
1 parent 8324c16 commit 6098bab
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 3 deletions.
17 changes: 16 additions & 1 deletion packages/puppeteer-core/src/common/XPathQueryHandler.ts
Expand Up @@ -14,7 +14,11 @@
* limitations under the License.
*/

import {QueryHandler, type QuerySelectorAll} from './QueryHandler.js';
import {
QueryHandler,
type QuerySelectorAll,
type QuerySelector,
} from './QueryHandler.js';

/**
* @internal
Expand All @@ -27,4 +31,15 @@ export class XPathQueryHandler extends QueryHandler {
) => {
return xpathQuerySelectorAll(element, selector);
};

static override querySelector: QuerySelector = (
element: Node,
selector: string,
{xpathQuerySelectorAll}
) => {
for (const result of xpathQuerySelectorAll(element, selector, 1)) {
return result;
}
return null;
};
}
18 changes: 16 additions & 2 deletions packages/puppeteer-core/src/injected/XPathQuerySelector.ts
Expand Up @@ -19,7 +19,8 @@
*/
export const xpathQuerySelectorAll = function* (
root: Node,
selector: string
selector: string,
maxResults = -1
): Iterable<Node> {
const doc = root.ownerDocument || document;
const iterator = doc.evaluate(
Expand All @@ -28,8 +29,21 @@ export const xpathQuerySelectorAll = function* (
null,
XPathResult.ORDERED_NODE_ITERATOR_TYPE
);
const items = [];
let item;

// Read all results upfront to avoid
// https://stackoverflow.com/questions/48235278/xpath-error-the-document-has-mutated-since-the-result-was-returned.
while ((item = iterator.iterateNext())) {
yield item;
items.push(item);
if (maxResults && items.length === maxResults) {
break;
}
}

for (let i = 0; i < items.length; i++) {
item = items[i];
yield item as Node;
delete items[i];
}
};

0 comments on commit 6098bab

Please sign in to comment.