feat(selectors): optimize old->new selectors conversion for text (#4671)

This commit is contained in:
Dmitry Gozman 2020-12-10 13:53:19 -08:00 committed by GitHub
parent c8e9b0542b
commit 12dc04a304
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 19 additions and 19 deletions

View file

@ -16,7 +16,8 @@
import * as css from './cssTokenizer';
type ClauseCombinator = '' | '>' | '+' | '~';
// Note: '>=' is used internally for text engine to preserve backwards compatibility.
type ClauseCombinator = '' | '>' | '+' | '~' | '>=';
// TODO: consider
// - key=value
// - operators like `=`, `|=`, `~=`, `*=`, `/`

View file

@ -55,7 +55,7 @@ export function parseSelector(selector: string, customNames: Set<string>): Parse
}
const chain = (from: number, to: number): CSSComplexSelector => {
let result: CSSComplexSelector = { simples: [] };
const result: CSSComplexSelector = { simples: [] };
for (const part of v1.parts.slice(from, to)) {
let name = part.name;
let wrapInLight = false;
@ -70,24 +70,14 @@ export function parseSelector(selector: string, customNames: Set<string>): Parse
simple = callWith('is', parsed.selector);
} else if (name === 'text') {
simple = textSelectorToSimple(part.body);
if (result.simples.length)
result.simples[result.simples.length - 1].combinator = '>=';
} else {
simple = callWith(name, [part.body]);
}
if (wrapInLight)
simple = callWith('light', [simpleToComplex(simple)]);
if (name === 'text') {
const copy = result.simples.map(one => {
return { selector: copySimple(one.selector), combinator: one.combinator };
});
copy.push({ selector: simple, combinator: '' });
if (!result.simples.length)
result.simples.push({ selector: callWith('scope', []), combinator: '' });
const last = result.simples[result.simples.length - 1];
last.selector.functions.push({ name: 'is', args: [simpleToComplex(simple)] });
result = simpleToComplex(callWith('is', [{ simples: copy }, result]));
} else {
result.simples.push({ selector: simple, combinator: '' });
}
result.simples.push({ selector: simple, combinator: '' });
}
return result;
};
@ -110,10 +100,6 @@ function simpleToComplex(simple: CSSSimpleSelector): CSSComplexSelector {
return { simples: [{ selector: simple, combinator: '' }]};
}
function copySimple(simple: CSSSimpleSelector): CSSSimpleSelector {
return { css: simple.css, functions: simple.functions.slice() };
}
function textSelectorToSimple(selector: string): CSSSimpleSelector {
function unescape(s: string): string {
if (!s.includes('\\'))

View file

@ -214,6 +214,19 @@ export class SelectorEvaluatorImpl implements SelectorEvaluator {
}
return false;
}
if (combinator === '>=') {
let parent: Element | undefined = element;
while (parent) {
if (this._matchesSimple(parent, simple, context)) {
if (this._matchesParents(parent, complex, index - 1, context))
return true;
if (complex.simples[index - 1].combinator === '')
break;
}
parent = parentElementOrShadowHostInContext(parent, context);
}
return false;
}
throw new Error(`Unsupported combinator "${combinator}"`);
});
}