MCPcopy Index your code
hub / github.com/microsoft/playwright / cssFallback

Function cssFallback

packages/injected/src/selectorGenerator.ts:391–461  ·  view source on GitHub ↗
(injectedScript: InjectedScript, targetElement: Element, options: InternalOptions)

Source from the content-addressed store, hash-verified

389}
390
391function cssFallback(injectedScript: InjectedScript, targetElement: Element, options: InternalOptions): SelectorToken[] {
392 const root: Node = options.root ?? targetElement.ownerDocument;
393 const tokens: string[] = [];
394
395 function uniqueCSSSelector(prefix?: string): string | undefined {
396 const path = tokens.slice();
397 if (prefix)
398 path.unshift(prefix);
399 const selector = path.join(' > ');
400 const parsedSelector = injectedScript.parseSelector(selector);
401 const node = injectedScript.querySelector(parsedSelector, root, false);
402 return node === targetElement ? selector : undefined;
403 }
404
405 function makeStrict(selector: string): SelectorToken[] {
406 const token = { engine: 'css', selector, score: kCSSFallbackScore };
407 const parsedSelector = injectedScript.parseSelector(selector);
408 const elements = injectedScript.querySelectorAll(parsedSelector, root);
409 if (elements.length === 1)
410 return [token];
411 const nth = { engine: 'nth', selector: String(elements.indexOf(targetElement)), score: kNthScore };
412 return [token, nth];
413 }
414
415 for (let element: Element | undefined = targetElement; element && element !== root; element = parentElementOrShadowHost(element)) {
416 let bestTokenForLevel: string = '';
417
418 // Element ID is the strongest signal, use it.
419 if (element.id && !options.noCSSId) {
420 const token = makeSelectorForId(element.id);
421 const selector = uniqueCSSSelector(token);
422 if (selector)
423 return makeStrict(selector);
424 bestTokenForLevel = token;
425 }
426
427 const parent = element.parentNode as (Element | ShadowRoot);
428
429 // Combine class names until unique.
430 const classes = [...element.classList].map(escapeClassName);
431 for (let i = 0; i < classes.length; ++i) {
432 const token = '.' + classes.slice(0, i + 1).join('.');
433 const selector = uniqueCSSSelector(token);
434 if (selector)
435 return makeStrict(selector);
436 // Even if not unique, does this subset of classes uniquely identify node as a child?
437 if (!bestTokenForLevel && parent) {
438 const sameClassSiblings = parent.querySelectorAll(token);
439 if (sameClassSiblings.length === 1)
440 bestTokenForLevel = token;
441 }
442 }
443
444 // Ordinal is the weakest signal.
445 if (parent) {
446 const siblings = [...parent.children];
447 const nodeName = element.nodeName;
448 const sameTagSiblings = siblings.filter(sibling => sibling.nodeName === nodeName);

Callers 2

generateSelectorFunction · 0.85
generateSelectorForFunction · 0.85

Calls 7

makeSelectorForIdFunction · 0.85
uniqueCSSSelectorFunction · 0.85
makeStrictFunction · 0.85
escapeNodeNameFunction · 0.85
querySelectorAllMethod · 0.65
filterMethod · 0.65

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…