Skip to content

Commit d4482f3

Browse files
authored
chore: do not use Array.from in injected script (#6876)
This method is most often overridden by some bad polyfill that does not work correctly and breaks `$eval` and `$$eval` methods. As a best-effort fix, use a `[...iterable]` throughout the code.
1 parent f2cc439 commit d4482f3

File tree

4 files changed

+15
-6
lines changed

4 files changed

+15
-6
lines changed

src/server/injected/injectedScript.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ export class InjectedScript {
124124
}
125125
set = newSet;
126126
}
127-
let result = Array.from(set) as Element[];
127+
let result = [...set] as Element[];
128128
if (partsToCheckOne.length) {
129129
const partial = { parts: partsToCheckOne };
130130
result = result.filter(e => !!this._querySelectorRecursively(e, partial, 0));
@@ -448,7 +448,7 @@ export class InjectedScript {
448448
if (element.nodeName.toLowerCase() !== 'select')
449449
return 'error:notselect';
450450
const select = element as HTMLSelectElement;
451-
const options = Array.from(select.options);
451+
const options = [...select.options];
452452
const selectedOptions = [];
453453
let remainingOptionsToSelect = optionsToSelect.slice();
454454
for (let index = 0; index < options.length; index++) {

src/server/injected/selectorEvaluator.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,9 @@ export class SelectorEvaluatorImpl implements SelectorEvaluator {
6868
this._engines.set('near', createPositionEngine('near', boxNear));
6969
this._engines.set('nth-match', nthMatchEngine);
7070

71-
const allNames = Array.from(this._engines.keys());
71+
const allNames = [...this._engines.keys()];
7272
allNames.sort();
73-
const parserNames = Array.from(customCSSNames).slice();
73+
const parserNames = [...customCSSNames];
7474
parserNames.sort();
7575
if (allNames.join('|') !== parserNames.join('|'))
7676
throw new Error(`Please keep customCSSNames in sync with evaluator engines: ${allNames.join('|')} vs ${parserNames.join('|')}`);

src/server/supplements/injected/selectorGenerator.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ function cssFallback(injectedScript: InjectedScript, targetElement: Element): Se
245245
const parent = element.parentNode as (Element | ShadowRoot);
246246

247247
// Combine class names until unique.
248-
const classes = Array.from(element.classList);
248+
const classes = [...element.classList];
249249
for (let i = 0; i < classes.length; ++i) {
250250
const token = '.' + classes.slice(0, i + 1).join('.');
251251
const selector = uniqueCSSSelector(token);
@@ -261,7 +261,7 @@ function cssFallback(injectedScript: InjectedScript, targetElement: Element): Se
261261

262262
// Ordinal is the weakest signal.
263263
if (parent) {
264-
const siblings = Array.from(parent.children);
264+
const siblings = [...parent.children];
265265
const sameTagSiblings = siblings.filter(sibling => (sibling).nodeName.toLowerCase() === nodeName);
266266
const token = sameTagSiblings.indexOf(element) === 0 ? nodeName : `${nodeName}:nth-child(${1 + siblings.indexOf(element)})`;
267267
const selector = uniqueCSSSelector(token);

tests/page/eval-on-selector-all.spec.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,12 @@ it('should return complex values', async ({page, server}) => {
7474
const texts = await page.$$eval('css=div', divs => divs.map(div => div.textContent));
7575
expect(texts).toEqual(['hello', 'beautiful', 'world!']);
7676
});
77+
78+
it('should work with bogus Array.from', async ({page, server}) => {
79+
await page.setContent('<div>hello</div><div>beautiful</div><div>world!</div>');
80+
await page.evaluate(() => {
81+
Array.from = () => [];
82+
});
83+
const divsCount = await page.$$eval('css=div', divs => divs.length);
84+
expect(divsCount).toBe(3);
85+
});

0 commit comments

Comments
 (0)