@nativescript/core 9.1.0-rc.0 → 9.1.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/ui/core/properties/index.d.ts +24 -1
- package/ui/core/properties/index.js +96 -10
- package/ui/core/properties/index.js.map +1 -1
- package/ui/styling/css-selector.d.ts +38 -9
- package/ui/styling/css-selector.js +149 -26
- package/ui/styling/css-selector.js.map +1 -1
- package/ui/styling/style-scope.d.ts +6 -2
- package/ui/styling/style-scope.js +262 -52
- package/ui/styling/style-scope.js.map +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getNativeScriptGlobals } from '../../globals/global-utils';
|
|
2
|
-
import { _evaluateCssVariableExpression, _evaluateCssCalcExpression, isCssVariable, isCssVariableExpression, isCssCalcExpression } from '../core/properties';
|
|
2
|
+
import { _evaluateCssVariableExpression, _evaluateCssCalcExpression, _expandCssShorthand, _isCssPendingSubstitution, isCssVariable, isCssVariableExpression, isCssCalcExpression } from '../core/properties';
|
|
3
3
|
import { unsetValue } from '../core/properties/property-shared';
|
|
4
|
-
import { StyleSheetSelectorScope, SelectorsMatch, fromAstNode, matchMediaQueryString } from './css-selector';
|
|
4
|
+
import { StyleSheetSelectorScope, SelectorsMatch, fromAstNode, matchMediaQueryString, matchSelectorCandidates } from './css-selector';
|
|
5
5
|
import { Trace } from './styling-shared';
|
|
6
6
|
import { File, knownFolders, path } from '../../file-system';
|
|
7
7
|
import { Application } from '../../application';
|
|
@@ -10,7 +10,6 @@ import { KeyframeAnimationInfo, KeyframeAnimation } from '../animation/keyframe-
|
|
|
10
10
|
import { CssAnimationParser } from './css-animation-parser';
|
|
11
11
|
import { sanitizeModuleName } from '../../utils/common';
|
|
12
12
|
import { resolveModuleName } from '../../module-name-resolver';
|
|
13
|
-
import { cleanupImportantFlags } from './css-utils';
|
|
14
13
|
import { cssTreeParse } from '../../css/css-tree-parser';
|
|
15
14
|
import { CSS3Parser } from '../../css/CSS3Parser';
|
|
16
15
|
import { CSSNativeScript } from '../../css/CSSNativeScript';
|
|
@@ -34,16 +33,49 @@ catch (e) {
|
|
|
34
33
|
let mergedApplicationCssSelectors = [];
|
|
35
34
|
let applicationCssSelectors = [];
|
|
36
35
|
const applicationAdditionalSelectors = [];
|
|
36
|
+
let mergedApplicationCssSelectorsInvalid = false;
|
|
37
37
|
let mergedApplicationCssKeyframes = [];
|
|
38
38
|
let applicationCssKeyframes = [];
|
|
39
39
|
const applicationAdditionalKeyframes = [];
|
|
40
|
+
let mergedApplicationCssKeyframesInvalid = false;
|
|
40
41
|
let applicationCssSelectorVersion = 0;
|
|
42
|
+
/**
|
|
43
|
+
* Shared index over the application stylesheets, built once for all style scopes.
|
|
44
|
+
* Tagged rules stay in it and are filtered out at match time - see `matchSelectorCandidates`.
|
|
45
|
+
*/
|
|
46
|
+
let applicationSelectorScope = null;
|
|
47
|
+
let applicationSelectorScopeVersion = -1;
|
|
48
|
+
let applicationSelectorScopeRuleCount = 0;
|
|
49
|
+
let applicationSelectorsHaveScopedTags = false;
|
|
50
|
+
/** Bumped when the application rules change in a way an append cannot express. */
|
|
51
|
+
let applicationSelectorsResetVersion = 0;
|
|
52
|
+
let applicationSelectorScopeResetVersion = -1;
|
|
41
53
|
const tagToScopeTag = new Map();
|
|
42
54
|
let currentScopeTag = null;
|
|
43
55
|
const animationsSymbol = Symbol('animations');
|
|
44
56
|
const kebabCasePattern = /-([a-z])/g;
|
|
45
57
|
const kebabCaseReplacementFunc = (g) => g[1].toUpperCase();
|
|
46
58
|
const pattern = /('|")(.*?)\1/;
|
|
59
|
+
/**
|
|
60
|
+
* Parse a pending-substitution shorthand once its expression has been evaluated
|
|
61
|
+
* against the view; a value that does not survive evaluation leaves its longhands unset.
|
|
62
|
+
*/
|
|
63
|
+
function resolvePendingSubstitution(view, pending) {
|
|
64
|
+
const value = evaluateCssExpressions(view, pending.shorthand, pending.value);
|
|
65
|
+
if (value === unsetValue) {
|
|
66
|
+
return CssState.emptyPropertyBag;
|
|
67
|
+
}
|
|
68
|
+
const expanded = _expandCssShorthand(pending.shorthand, value);
|
|
69
|
+
if (!expanded) {
|
|
70
|
+
Trace.write(`Failed to expand shorthand [${pending.shorthand}] resolved to [${value}] for ${view}.`, Trace.categories.Style, Trace.messageType.warn);
|
|
71
|
+
return CssState.emptyPropertyBag;
|
|
72
|
+
}
|
|
73
|
+
const resolved = {};
|
|
74
|
+
for (let i = 0, length = expanded.length; i < length; i++) {
|
|
75
|
+
resolved[expanded[i][0]] = expanded[i][1];
|
|
76
|
+
}
|
|
77
|
+
return resolved;
|
|
78
|
+
}
|
|
47
79
|
/**
|
|
48
80
|
* Evaluate css-variable and css-calc expressions
|
|
49
81
|
*/
|
|
@@ -62,13 +94,66 @@ function evaluateCssExpressions(view, property, value) {
|
|
|
62
94
|
}
|
|
63
95
|
return value;
|
|
64
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* Only marks the merged list dirty - it is rebuilt on next read, since frameworks
|
|
99
|
+
* register stylesheets one call at a time.
|
|
100
|
+
*/
|
|
65
101
|
export function mergeCssSelectors() {
|
|
66
|
-
|
|
67
|
-
mergedApplicationCssSelectors.push(...applicationAdditionalSelectors);
|
|
102
|
+
mergedApplicationCssSelectorsInvalid = true;
|
|
68
103
|
}
|
|
69
104
|
export function mergeCssKeyframes() {
|
|
70
|
-
|
|
71
|
-
|
|
105
|
+
mergedApplicationCssKeyframesInvalid = true;
|
|
106
|
+
}
|
|
107
|
+
function getMergedApplicationCssSelectors() {
|
|
108
|
+
if (mergedApplicationCssSelectorsInvalid) {
|
|
109
|
+
mergedApplicationCssSelectorsInvalid = false;
|
|
110
|
+
mergedApplicationCssSelectors = concatRuleSets(applicationCssSelectors, applicationAdditionalSelectors);
|
|
111
|
+
}
|
|
112
|
+
return mergedApplicationCssSelectors;
|
|
113
|
+
}
|
|
114
|
+
function getMergedApplicationCssKeyframes() {
|
|
115
|
+
if (mergedApplicationCssKeyframesInvalid) {
|
|
116
|
+
mergedApplicationCssKeyframesInvalid = false;
|
|
117
|
+
mergedApplicationCssKeyframes = concatRuleSets(applicationCssKeyframes, applicationAdditionalKeyframes);
|
|
118
|
+
}
|
|
119
|
+
return mergedApplicationCssKeyframes;
|
|
120
|
+
}
|
|
121
|
+
function getApplicationSelectorScope() {
|
|
122
|
+
if (applicationSelectorScopeVersion === applicationCssSelectorVersion) {
|
|
123
|
+
return applicationSelectorScope;
|
|
124
|
+
}
|
|
125
|
+
const rulesets = getMergedApplicationCssSelectors();
|
|
126
|
+
const canAppend = applicationSelectorScope && applicationSelectorScopeResetVersion === applicationSelectorsResetVersion && rulesets.length >= applicationSelectorScopeRuleCount;
|
|
127
|
+
if (canAppend) {
|
|
128
|
+
applicationSelectorScope.appendRulesets(rulesets, applicationSelectorScopeRuleCount);
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
applicationSelectorScope = rulesets.length > 0 ? new StyleSheetSelectorScope(rulesets, 0 /* SelectorTier.Application */) : null;
|
|
132
|
+
applicationSelectorsHaveScopedTags = false;
|
|
133
|
+
applicationSelectorScopeRuleCount = 0;
|
|
134
|
+
}
|
|
135
|
+
for (let i = applicationSelectorScopeRuleCount, length = rulesets.length; i < length; i++) {
|
|
136
|
+
if (rulesets[i].scopedTag) {
|
|
137
|
+
applicationSelectorsHaveScopedTags = true;
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
applicationSelectorScopeRuleCount = rulesets.length;
|
|
142
|
+
applicationSelectorScopeVersion = applicationCssSelectorVersion;
|
|
143
|
+
applicationSelectorScopeResetVersion = applicationSelectorsResetVersion;
|
|
144
|
+
return applicationSelectorScope;
|
|
145
|
+
}
|
|
146
|
+
/** Avoids `push(...arr)`, which blows the stack past the engine's argument limit. */
|
|
147
|
+
function concatRuleSets(base, additional) {
|
|
148
|
+
const baseLength = base.length;
|
|
149
|
+
const merged = new Array(baseLength + additional.length);
|
|
150
|
+
for (let i = 0; i < baseLength; i++) {
|
|
151
|
+
merged[i] = base[i];
|
|
152
|
+
}
|
|
153
|
+
for (let i = 0, length = additional.length; i < length; i++) {
|
|
154
|
+
merged[baseLength + i] = additional[i];
|
|
155
|
+
}
|
|
156
|
+
return merged;
|
|
72
157
|
}
|
|
73
158
|
class CSSSource {
|
|
74
159
|
constructor(_ast, _url, _file, _source) {
|
|
@@ -192,7 +277,7 @@ class CSSSource {
|
|
|
192
277
|
this._selectors = [];
|
|
193
278
|
}
|
|
194
279
|
}
|
|
195
|
-
|
|
280
|
+
parseCSSAst() {
|
|
196
281
|
if (this._source) {
|
|
197
282
|
if (__CSS_PARSER__ === 'css-tree') {
|
|
198
283
|
this._ast = cssTreeParse(this._source, this._file);
|
|
@@ -245,7 +330,7 @@ __decorate([
|
|
|
245
330
|
profile,
|
|
246
331
|
__metadata("design:type", Function),
|
|
247
332
|
__metadata("design:paramtypes", []),
|
|
248
|
-
__metadata("design:returntype",
|
|
333
|
+
__metadata("design:returntype", void 0)
|
|
249
334
|
], CSSSource.prototype, "parseCSSAst", null);
|
|
250
335
|
__decorate([
|
|
251
336
|
profile,
|
|
@@ -339,6 +424,8 @@ export function removeTaggedAdditionalCSS(tag) {
|
|
|
339
424
|
}
|
|
340
425
|
}
|
|
341
426
|
if (selectorsChanged) {
|
|
427
|
+
// Rules were dropped from the middle of the list, so the index has to be rebuilt.
|
|
428
|
+
applicationSelectorsResetVersion++;
|
|
342
429
|
mergeCssSelectors();
|
|
343
430
|
updated = true;
|
|
344
431
|
}
|
|
@@ -426,6 +513,8 @@ const loadCss = profile(`"style-scope".loadCss`, (cssModule) => {
|
|
|
426
513
|
let updated = false;
|
|
427
514
|
// Check for existing application css selectors too in case the app is undergoing a live-sync
|
|
428
515
|
if (selectors.length > 0 || applicationCssSelectors.length > 0) {
|
|
516
|
+
// The base stylesheet is replaced rather than appended to.
|
|
517
|
+
applicationSelectorsResetVersion++;
|
|
429
518
|
applicationCssSelectors = selectors;
|
|
430
519
|
mergeCssSelectors();
|
|
431
520
|
updated = true;
|
|
@@ -461,6 +550,36 @@ if (Application.hasLaunched()) {
|
|
|
461
550
|
else {
|
|
462
551
|
getNativeScriptGlobals().events.on('loadAppCss', loadAppCSS);
|
|
463
552
|
}
|
|
553
|
+
function trackedNamesEqual(a, b) {
|
|
554
|
+
if (a === b) {
|
|
555
|
+
return true;
|
|
556
|
+
}
|
|
557
|
+
if (!a || !b || a.size !== b.size) {
|
|
558
|
+
return false;
|
|
559
|
+
}
|
|
560
|
+
for (const name of a) {
|
|
561
|
+
if (!b.has(name)) {
|
|
562
|
+
return false;
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
return true;
|
|
566
|
+
}
|
|
567
|
+
/** Two empty maps compare equal even when they are different objects. */
|
|
568
|
+
function changeMapsEqual(applied, current) {
|
|
569
|
+
if (applied === current) {
|
|
570
|
+
return true;
|
|
571
|
+
}
|
|
572
|
+
if (applied.size !== current.size) {
|
|
573
|
+
return false;
|
|
574
|
+
}
|
|
575
|
+
for (const [view, changes] of applied) {
|
|
576
|
+
const currentChanges = current.get(view);
|
|
577
|
+
if (!currentChanges || !trackedNamesEqual(changes.attributes, currentChanges.attributes) || !trackedNamesEqual(changes.pseudoClasses, currentChanges.pseudoClasses)) {
|
|
578
|
+
return false;
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
return true;
|
|
582
|
+
}
|
|
464
583
|
export class CssState {
|
|
465
584
|
constructor(viewRef) {
|
|
466
585
|
this.viewRef = viewRef;
|
|
@@ -474,9 +593,13 @@ export class CssState {
|
|
|
474
593
|
onChange() {
|
|
475
594
|
const view = this.viewRef.get();
|
|
476
595
|
if (view && view.isLoaded) {
|
|
477
|
-
|
|
596
|
+
// Matching does not read the subscriptions, so re-subscribe only when the
|
|
597
|
+
// dependencies actually changed - they are usually identical.
|
|
478
598
|
this.updateMatch();
|
|
479
|
-
this.
|
|
599
|
+
if (!changeMapsEqual(this._appliedChangeMap, this._match.changeMap)) {
|
|
600
|
+
this.unsubscribeFromDynamicUpdates();
|
|
601
|
+
this.subscribeForDynamicUpdates();
|
|
602
|
+
}
|
|
480
603
|
this.updateDynamicState();
|
|
481
604
|
}
|
|
482
605
|
else {
|
|
@@ -606,46 +729,111 @@ export class CssState {
|
|
|
606
729
|
const oldProperties = this._appliedPropertyValues;
|
|
607
730
|
// Update values for the scope's css-variables
|
|
608
731
|
view.style.resetScopedCssVariables();
|
|
609
|
-
|
|
610
|
-
|
|
732
|
+
let valuesToApply;
|
|
733
|
+
let cssExpsProperties;
|
|
734
|
+
let pendingProperties;
|
|
611
735
|
for (const property in newPropertyValues) {
|
|
612
|
-
const value =
|
|
613
|
-
|
|
736
|
+
const value = newPropertyValues[property];
|
|
737
|
+
if (_isCssPendingSubstitution(value)) {
|
|
738
|
+
// Resolvable only after the css variables below are up to date.
|
|
739
|
+
if (!pendingProperties) {
|
|
740
|
+
pendingProperties = {};
|
|
741
|
+
}
|
|
742
|
+
pendingProperties[property] = value;
|
|
743
|
+
continue;
|
|
744
|
+
}
|
|
745
|
+
// Expanded shorthand values are already converted and may not be strings.
|
|
746
|
+
const isCssExp = typeof value === 'string' && (isCssVariableExpression(value) || isCssCalcExpression(value));
|
|
614
747
|
if (isCssExp) {
|
|
615
748
|
// we handle css exp separately because css vars must be evaluated first
|
|
749
|
+
if (!cssExpsProperties) {
|
|
750
|
+
cssExpsProperties = {};
|
|
751
|
+
}
|
|
616
752
|
cssExpsProperties[property] = value;
|
|
617
753
|
continue;
|
|
618
754
|
}
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
755
|
+
// Whatever is left in oldProperties after these loops was removed and gets unset.
|
|
756
|
+
const hadOldValue = property in oldProperties;
|
|
757
|
+
const unchanged = hadOldValue && oldProperties[property] === value;
|
|
758
|
+
if (hadOldValue) {
|
|
759
|
+
delete oldProperties[property];
|
|
623
760
|
}
|
|
624
761
|
if (isCssVariable(property)) {
|
|
762
|
+
// The scoped css-variables were just reset, so they always have to be re-registered.
|
|
625
763
|
view.style.setScopedCssVariable(property, value);
|
|
626
764
|
delete newPropertyValues[property];
|
|
627
765
|
continue;
|
|
628
766
|
}
|
|
767
|
+
if (unchanged) {
|
|
768
|
+
continue;
|
|
769
|
+
}
|
|
770
|
+
if (!valuesToApply) {
|
|
771
|
+
valuesToApply = {};
|
|
772
|
+
}
|
|
629
773
|
valuesToApply[property] = value;
|
|
630
774
|
}
|
|
631
775
|
//we need to parse CSS vars first before evaluating css expressions
|
|
632
776
|
for (const property in cssExpsProperties) {
|
|
633
|
-
|
|
777
|
+
const hadOldValue = property in oldProperties;
|
|
778
|
+
const oldValue = hadOldValue ? oldProperties[property] : undefined;
|
|
779
|
+
if (hadOldValue) {
|
|
780
|
+
delete oldProperties[property];
|
|
781
|
+
}
|
|
634
782
|
const value = evaluateCssExpressions(view, property, cssExpsProperties[property]);
|
|
635
|
-
if (property
|
|
636
|
-
|
|
783
|
+
if (isCssVariable(property)) {
|
|
784
|
+
view.style.setScopedCssVariable(property, value);
|
|
785
|
+
delete newPropertyValues[property];
|
|
637
786
|
continue;
|
|
638
787
|
}
|
|
639
788
|
if (value === unsetValue) {
|
|
640
789
|
delete newPropertyValues[property];
|
|
641
790
|
}
|
|
642
|
-
|
|
643
|
-
|
|
791
|
+
else {
|
|
792
|
+
// Record the evaluated value - the next diff compares against it.
|
|
793
|
+
newPropertyValues[property] = value;
|
|
794
|
+
}
|
|
795
|
+
if (hadOldValue && oldValue === value) {
|
|
796
|
+
continue;
|
|
797
|
+
}
|
|
798
|
+
if (!valuesToApply) {
|
|
799
|
+
valuesToApply = {};
|
|
800
|
+
}
|
|
801
|
+
valuesToApply[property] = value;
|
|
802
|
+
}
|
|
803
|
+
// Each shorthand is resolved once, however many longhands point at it.
|
|
804
|
+
let resolvedShorthands;
|
|
805
|
+
for (const property in pendingProperties) {
|
|
806
|
+
const pending = pendingProperties[property];
|
|
807
|
+
if (!resolvedShorthands) {
|
|
808
|
+
resolvedShorthands = new Map();
|
|
809
|
+
}
|
|
810
|
+
let resolved = resolvedShorthands.get(pending);
|
|
811
|
+
if (!resolved) {
|
|
812
|
+
resolved = resolvePendingSubstitution(view, pending);
|
|
813
|
+
resolvedShorthands.set(pending, resolved);
|
|
814
|
+
}
|
|
815
|
+
const value = property in resolved ? resolved[property] : unsetValue;
|
|
816
|
+
const hadOldValue = property in oldProperties;
|
|
817
|
+
const oldValue = hadOldValue ? oldProperties[property] : undefined;
|
|
818
|
+
if (hadOldValue) {
|
|
819
|
+
delete oldProperties[property];
|
|
820
|
+
}
|
|
821
|
+
if (value === unsetValue) {
|
|
644
822
|
delete newPropertyValues[property];
|
|
645
823
|
}
|
|
824
|
+
else {
|
|
825
|
+
newPropertyValues[property] = value;
|
|
826
|
+
}
|
|
827
|
+
if (hadOldValue && oldValue === value) {
|
|
828
|
+
continue;
|
|
829
|
+
}
|
|
830
|
+
if (!valuesToApply) {
|
|
831
|
+
valuesToApply = {};
|
|
832
|
+
}
|
|
646
833
|
valuesToApply[property] = value;
|
|
647
834
|
}
|
|
648
|
-
// Unset removed values
|
|
835
|
+
// Unset removed values - the bag is keyed by longhands only, so unsetting
|
|
836
|
+
// one entry cannot clear a value another one set.
|
|
649
837
|
for (const property in oldProperties) {
|
|
650
838
|
if (property in view.style) {
|
|
651
839
|
view.style[`css:${property}`] = unsetValue;
|
|
@@ -749,12 +937,13 @@ CssState.prototype._matchInvalid = true;
|
|
|
749
937
|
export class StyleScope {
|
|
750
938
|
constructor() {
|
|
751
939
|
this._css = '';
|
|
940
|
+
this._hasSelectors = false;
|
|
752
941
|
this._localCssSelectors = [];
|
|
753
942
|
this._localCssKeyframes = [];
|
|
754
943
|
this._localCssSelectorVersion = 0;
|
|
755
944
|
this._localCssSelectorsAppliedVersion = 0;
|
|
756
945
|
this._applicationCssSelectorsAppliedVersion = 0;
|
|
757
|
-
this._cssFiles =
|
|
946
|
+
this._cssFiles = new Set();
|
|
758
947
|
}
|
|
759
948
|
get css() {
|
|
760
949
|
return this._css;
|
|
@@ -772,7 +961,7 @@ export class StyleScope {
|
|
|
772
961
|
if (!cssFileName) {
|
|
773
962
|
return;
|
|
774
963
|
}
|
|
775
|
-
this._cssFiles.
|
|
964
|
+
this._cssFiles.add(cssFileName);
|
|
776
965
|
currentScopeTag = cssFileName;
|
|
777
966
|
const cssFile = CSSSource.fromURI(cssFileName);
|
|
778
967
|
currentScopeTag = null;
|
|
@@ -795,7 +984,7 @@ export class StyleScope {
|
|
|
795
984
|
return;
|
|
796
985
|
}
|
|
797
986
|
if (cssFileName) {
|
|
798
|
-
this._cssFiles.
|
|
987
|
+
this._cssFiles.add(cssFileName);
|
|
799
988
|
currentScopeTag = cssFileName;
|
|
800
989
|
}
|
|
801
990
|
const cssFile = cssString ? CSSSource.fromSource(cssString, cssFileName) : CSSSource.fromURI(cssFileName);
|
|
@@ -816,7 +1005,7 @@ export class StyleScope {
|
|
|
816
1005
|
return animation;
|
|
817
1006
|
}
|
|
818
1007
|
ensureSelectors() {
|
|
819
|
-
if (!this.isApplicationCssSelectorsLatestVersionApplied() || !this.isLocalCssSelectorsLatestVersionApplied()
|
|
1008
|
+
if (!this.isApplicationCssSelectorsLatestVersionApplied() || !this.isLocalCssSelectorsLatestVersionApplied()) {
|
|
820
1009
|
this._createSelectors();
|
|
821
1010
|
}
|
|
822
1011
|
return this.getSelectorsVersion();
|
|
@@ -826,14 +1015,14 @@ export class StyleScope {
|
|
|
826
1015
|
*/
|
|
827
1016
|
get hasAdjacentCombinatorSelectors() {
|
|
828
1017
|
this.ensureSelectors();
|
|
829
|
-
return
|
|
1018
|
+
return !!applicationSelectorScope?.hasAdjacentCombinatorSelectors || !!this._localSelectorScope?.hasAdjacentCombinatorSelectors;
|
|
830
1019
|
}
|
|
831
1020
|
/**
|
|
832
1021
|
* True when any selector in the scope contains a general sibling ('~') combinator.
|
|
833
1022
|
*/
|
|
834
1023
|
get hasSiblingCombinatorSelectors() {
|
|
835
1024
|
this.ensureSelectors();
|
|
836
|
-
return
|
|
1025
|
+
return !!applicationSelectorScope?.hasSiblingCombinatorSelectors || !!this._localSelectorScope?.hasSiblingCombinatorSelectors;
|
|
837
1026
|
}
|
|
838
1027
|
/**
|
|
839
1028
|
* Increase the application CSS selector version.
|
|
@@ -848,38 +1037,43 @@ export class StyleScope {
|
|
|
848
1037
|
return this._localCssSelectorsAppliedVersion === this._localCssSelectorVersion;
|
|
849
1038
|
}
|
|
850
1039
|
_createSelectors() {
|
|
851
|
-
const
|
|
852
|
-
const
|
|
853
|
-
toMerge.push(...mergedApplicationCssSelectors.filter((v) => !v.scopedTag || this._cssFiles.indexOf(v.scopedTag) >= 0));
|
|
854
|
-
toMergeKeyframes.push(...mergedApplicationCssKeyframes.filter((v) => !v.scopedTag || this._cssFiles.indexOf(v.scopedTag) >= 0));
|
|
1040
|
+
const cssFiles = this._cssFiles;
|
|
1041
|
+
const applicationScope = getApplicationSelectorScope();
|
|
855
1042
|
this._applicationCssSelectorsAppliedVersion = applicationCssSelectorVersion;
|
|
856
|
-
|
|
857
|
-
|
|
1043
|
+
if (!this.isLocalCssSelectorsLatestVersionApplied() || (!this._localSelectorScope && this._localCssSelectors.length > 0)) {
|
|
1044
|
+
this._localSelectorScope = this._localCssSelectors.length > 0 ? new StyleSheetSelectorScope(this._localCssSelectors, 1 /* SelectorTier.Local */) : null;
|
|
1045
|
+
}
|
|
858
1046
|
this._localCssSelectorsAppliedVersion = this._localCssSelectorVersion;
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
1047
|
+
this._hasSelectors = !!applicationScope || !!this._localSelectorScope;
|
|
1048
|
+
const toMergeKeyframes = [];
|
|
1049
|
+
const applicationKeyframes = getMergedApplicationCssKeyframes();
|
|
1050
|
+
for (let i = 0, length = applicationKeyframes.length; i < length; i++) {
|
|
1051
|
+
const keyframe = applicationKeyframes[i];
|
|
1052
|
+
if (!keyframe.scopedTag || cssFiles.has(keyframe.scopedTag)) {
|
|
1053
|
+
toMergeKeyframes.push(keyframe);
|
|
1054
|
+
}
|
|
862
1055
|
}
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
1056
|
+
const localKeyframes = this._localCssKeyframes;
|
|
1057
|
+
for (let i = 0, length = localKeyframes.length; i < length; i++) {
|
|
1058
|
+
toMergeKeyframes.push(localKeyframes[i]);
|
|
866
1059
|
}
|
|
867
1060
|
this._mergedCssKeyframes = toMergeKeyframes.length > 0 ? toMergeKeyframes : null;
|
|
868
1061
|
}
|
|
869
1062
|
// HACK: This @profile decorator creates a circular dependency
|
|
870
1063
|
// HACK: because the function parameter type is evaluated with 'typeof'
|
|
871
1064
|
matchSelectors(view) {
|
|
872
|
-
let match;
|
|
873
1065
|
// should be (view: ViewBase): SelectorsMatch<ViewBase>
|
|
874
1066
|
this.ensureSelectors();
|
|
875
|
-
if (this.
|
|
876
|
-
|
|
877
|
-
// Make sure to re-apply keyframes to matching selectors as a media query keyframe might be applicable at this point
|
|
878
|
-
this._applyKeyframesToSelectors(match.selectors);
|
|
879
|
-
}
|
|
880
|
-
else {
|
|
881
|
-
match = null;
|
|
1067
|
+
if (!this._hasSelectors) {
|
|
1068
|
+
return null;
|
|
882
1069
|
}
|
|
1070
|
+
// The cascade has to see the application and local candidates as a single ordered set.
|
|
1071
|
+
const candidates = [];
|
|
1072
|
+
applicationSelectorScope?.collectCandidates(view, candidates);
|
|
1073
|
+
this._localSelectorScope?.collectCandidates(view, candidates);
|
|
1074
|
+
const match = matchSelectorCandidates(view, candidates, applicationSelectorsHaveScopedTags ? this._cssFiles : undefined);
|
|
1075
|
+
// Make sure to re-apply keyframes to matching selectors as a media query keyframe might be applicable at this point
|
|
1076
|
+
this._applyKeyframesToSelectors(match.selectors);
|
|
883
1077
|
return match;
|
|
884
1078
|
}
|
|
885
1079
|
query(node) {
|
|
@@ -1012,6 +1206,8 @@ export const applyInlineStyle = profile('applyInlineStyle', function applyInline
|
|
|
1012
1206
|
view.style.setUnscopedCssVariable(property, d.value);
|
|
1013
1207
|
}
|
|
1014
1208
|
});
|
|
1209
|
+
// Pending-substitution longhands share one placeholder - resolve it once.
|
|
1210
|
+
let resolvedShorthands;
|
|
1015
1211
|
inlineRuleSet[0].declarations.forEach((d) => {
|
|
1016
1212
|
// Use the actual property name so that a local value is set.
|
|
1017
1213
|
const property = d.property;
|
|
@@ -1020,7 +1216,21 @@ export const applyInlineStyle = profile('applyInlineStyle', function applyInline
|
|
|
1020
1216
|
// Skip css-variables, they have been handled
|
|
1021
1217
|
return;
|
|
1022
1218
|
}
|
|
1023
|
-
|
|
1219
|
+
let value;
|
|
1220
|
+
if (_isCssPendingSubstitution(d.value)) {
|
|
1221
|
+
if (!resolvedShorthands) {
|
|
1222
|
+
resolvedShorthands = new Map();
|
|
1223
|
+
}
|
|
1224
|
+
let resolved = resolvedShorthands.get(d.value);
|
|
1225
|
+
if (!resolved) {
|
|
1226
|
+
resolved = resolvePendingSubstitution(view, d.value);
|
|
1227
|
+
resolvedShorthands.set(d.value, resolved);
|
|
1228
|
+
}
|
|
1229
|
+
value = property in resolved ? resolved[property] : unsetValue;
|
|
1230
|
+
}
|
|
1231
|
+
else {
|
|
1232
|
+
value = evaluateCssExpressions(view, property, d.value);
|
|
1233
|
+
}
|
|
1024
1234
|
if (property in view.style) {
|
|
1025
1235
|
view.style[property] = value;
|
|
1026
1236
|
}
|