fix: stop leaking style scopes (#9444)

fixes #9311

* fix: stop leaking style scopes

* fix: don't leak scoped styles in production
This commit is contained in:
Eduardo Speroni
2021-06-15 18:00:07 -03:00
committed by GitHub
parent 9f582ba168
commit b8d8110994
2 changed files with 19 additions and 2 deletions

View File

@@ -501,6 +501,7 @@ export namespace Selector {
export class RuleSet {
tag: string | number;
scopedTag: string;
constructor(public selectors: SelectorCore[], public declarations: Declaration[]) {
this.selectors.forEach((sel) => (sel.ruleset = this));
}

View File

@@ -76,6 +76,8 @@ export function mergeCssSelectors(): void {
let applicationCssSelectors: RuleSet[] = [];
let applicationCssSelectorVersion = 0;
let applicationSelectors: RuleSet[] = [];
let tagToScopeTag: Map<string | number, string> = new Map();
let currentScopeTag: string = null;
const applicationAdditionalSelectors: RuleSet[] = [];
const applicationKeyframes: any = {};
const animationsSymbol = Symbol('animations');
@@ -312,12 +314,17 @@ export function removeTaggedAdditionalCSS(tag: string | number): boolean {
export function addTaggedAdditionalCSS(cssText: string, tag?: string | number): boolean {
const parsed: RuleSet[] = CSSSource.fromDetect(cssText, applicationKeyframes, undefined).selectors;
let tagScope = currentScopeTag || (tag && tagToScopeTag.has(tag) && tagToScopeTag.get(tag)) || null;
if (tagScope && tag) {
tagToScopeTag.set(tag, tagScope);
}
let changed = false;
if (parsed && parsed.length) {
changed = true;
if (tag != null) {
if (tag != null || tagScope != null) {
for (let i = 0; i < parsed.length; i++) {
parsed[i].tag = tag;
parsed[i].scopedTag = tagScope;
}
}
applicationAdditionalSelectors.push(...parsed);
@@ -699,6 +706,7 @@ export class StyleScope {
private _localCssSelectorsAppliedVersion = 0;
private _applicationCssSelectorsAppliedVersion = 0;
private _keyframes = new Map<string, Keyframes>();
private _cssFiles: string[] = [];
get css(): string {
return this._css;
@@ -720,8 +728,11 @@ export class StyleScope {
if (!cssFileName) {
return;
}
this._cssFiles.push(cssFileName);
currentScopeTag = cssFileName;
const cssSelectors = CSSSource.fromURI(cssFileName, this._keyframes);
currentScopeTag = null;
this._css = cssSelectors.source;
this._localCssSelectors = cssSelectors.selectors;
this._localCssSelectorVersion++;
@@ -743,8 +754,13 @@ export class StyleScope {
if (!cssString && !cssFileName) {
return;
}
if (cssFileName) {
this._cssFiles.push(cssFileName);
currentScopeTag = cssFileName;
}
const parsedCssSelectors = cssString ? CSSSource.fromSource(cssString, this._keyframes, cssFileName) : CSSSource.fromURI(cssFileName, this._keyframes);
currentScopeTag = null;
this._css = this._css + parsedCssSelectors.source;
this._localCssSelectors.push(...parsedCssSelectors.selectors);
this._localCssSelectorVersion++;
@@ -788,7 +804,7 @@ export class StyleScope {
@profile
private _createSelectors() {
const toMerge: RuleSet[][] = [];
toMerge.push(applicationCssSelectors);
toMerge.push(applicationCssSelectors.filter((v) => !v.scopedTag || this._cssFiles.indexOf(v.scopedTag) >= 0));
this._applicationCssSelectorsAppliedVersion = applicationCssSelectorVersion;
toMerge.push(this._localCssSelectors);
this._localCssSelectorsAppliedVersion = this._localCssSelectorVersion;