chore: cache normalized whitespaces in recorder (#31349)

Reference: https://github.com/microsoft/playwright/issues/31254

On the web page from the bug it reduces time to compute selectors by 8x:

**Before:**
<img width="549" alt="before"
src="https://github.com/microsoft/playwright/assets/9798949/f4482860-29d5-4643-92ab-b360a702f232">

**After:**
<img width="580" alt="after"
src="https://github.com/microsoft/playwright/assets/9798949/b6aca6a1-9306-4041-9042-d504dce1c33a">
This commit is contained in:
Yury Semikhatsky 2024-06-17 18:20:15 -07:00 committed by GitHub
parent 5443b66636
commit 9e6772818e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 15 additions and 4 deletions

View File

@ -33,7 +33,7 @@ import { getChecked, getAriaDisabled, getAriaRole, getElementAccessibleName, get
import { kLayoutSelectorNames, type LayoutSelectorName, layoutSelectorScore } from './layoutSelectorUtils';
import { asLocator } from '../../utils/isomorphic/locatorGenerators';
import type { Language } from '../../utils/isomorphic/locatorGenerators';
import { normalizeWhiteSpace, trimStringWithEllipsis } from '../../utils/isomorphic/stringUtils';
import { cacheNormalizedWhitespaces, normalizeWhiteSpace, trimStringWithEllipsis } from '../../utils/isomorphic/stringUtils';
export type FrameExpectParams = Omit<channels.FrameExpectParams, 'expectedValue'> & { expectedValue?: any };
@ -66,7 +66,7 @@ export class InjectedScript {
// eslint-disable-next-line no-restricted-globals
readonly window: Window & typeof globalThis;
readonly document: Document;
readonly utils = { isInsideScope, elementText, asLocator, normalizeWhiteSpace };
readonly utils = { isInsideScope, elementText, asLocator, normalizeWhiteSpace, cacheNormalizedWhitespaces };
// eslint-disable-next-line no-restricted-globals
constructor(window: Window & typeof globalThis, isUnderTest: boolean, sdkLanguage: Language, testIdAttributeNameForStrictErrorAndConsoleCodegen: string, stableRafCount: number, browserName: string, customEngines: { name: string, engine: SelectorEngine }[]) {

View File

@ -973,7 +973,7 @@ export class Recorder {
body[data-pw-cursor=text] *, body[data-pw-cursor=text] *::after { cursor: text !important; }
`);
this.installListeners();
injectedScript.utils.cacheNormalizedWhitespaces();
if (injectedScript.isUnderTest)
console.error('Recorder script ready for test'); // eslint-disable-line no-console
}

View File

@ -67,8 +67,19 @@ function cssEscapeOne(s: string, i: number): string {
return '\\' + s.charAt(i);
}
let normalizedWhitespaceCache: Map<string, string> | undefined;
export function cacheNormalizedWhitespaces() {
normalizedWhitespaceCache = new Map();
}
export function normalizeWhiteSpace(text: string): string {
return text.replace(/\u200b/g, '').trim().replace(/\s+/g, ' ');
let result = normalizedWhitespaceCache?.get(text);
if (result === undefined) {
result = text.replace(/\u200b/g, '').trim().replace(/\s+/g, ' ');
normalizedWhitespaceCache?.set(text, result);
}
return result;
}
export function normalizeEscapedRegexQuotes(source: string) {