@nativescript/core 9.1.0-alpha.9 → 9.1.0-next.0

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.
Files changed (234) hide show
  1. package/accessibility/accessibility-common.d.ts +8 -0
  2. package/accessibility/accessibility-common.js +28 -0
  3. package/accessibility/accessibility-common.js.map +1 -1
  4. package/application/application-common.d.ts +187 -4
  5. package/application/application-common.js +402 -94
  6. package/application/application-common.js.map +1 -1
  7. package/application/application-interfaces.d.ts +59 -1
  8. package/application/application.android.d.ts +22 -1
  9. package/application/application.android.js +193 -15
  10. package/application/application.android.js.map +1 -1
  11. package/application/application.d.ts +121 -66
  12. package/application/application.ios.d.ts +104 -27
  13. package/application/application.ios.js +549 -352
  14. package/application/application.ios.js.map +1 -1
  15. package/application/helpers-common.d.ts +5 -0
  16. package/application/helpers-common.js +23 -1
  17. package/application/helpers-common.js.map +1 -1
  18. package/application/scene-delegate-bridge.d.ts +55 -0
  19. package/application/scene-delegate-bridge.js +122 -0
  20. package/application/scene-delegate-bridge.js.map +1 -0
  21. package/config/config.interface.d.ts +44 -2
  22. package/core-types/index.d.ts +9 -2
  23. package/core-types/index.js +7 -0
  24. package/core-types/index.js.map +1 -1
  25. package/css/CSS3Parser.js +3 -2
  26. package/css/CSS3Parser.js.map +1 -1
  27. package/css/system-classes.d.ts +9 -0
  28. package/css/system-classes.js +23 -0
  29. package/css/system-classes.js.map +1 -1
  30. package/data/observable/index.d.ts +5 -0
  31. package/data/observable/index.js +46 -9
  32. package/data/observable/index.js.map +1 -1
  33. package/debugger/dom-types.js +31 -1
  34. package/debugger/dom-types.js.map +1 -1
  35. package/fetch/index.mjs +2 -2
  36. package/file-system/file-system-access.ios.js +18 -10
  37. package/file-system/file-system-access.ios.js.map +1 -1
  38. package/file-system/index.d.ts +3 -3
  39. package/global-types.d.ts +39 -33
  40. package/globals/global-utils.d.ts +6 -1
  41. package/globals/global-utils.js +10 -5
  42. package/globals/global-utils.js.map +1 -1
  43. package/globals/index.js +14 -4
  44. package/globals/index.js.map +1 -1
  45. package/globals/polyfills/utils.js +2 -0
  46. package/globals/polyfills/utils.js.map +1 -1
  47. package/index.d.ts +2 -0
  48. package/index.js +1 -0
  49. package/index.js.map +1 -1
  50. package/inspector_modules.js +1 -1
  51. package/inspector_modules.js.map +1 -1
  52. package/native-window/index.d.ts +426 -0
  53. package/native-window/index.js +4 -0
  54. package/native-window/index.js.map +1 -0
  55. package/native-window/native-window-common.d.ts +153 -0
  56. package/native-window/native-window-common.js +340 -0
  57. package/native-window/native-window-common.js.map +1 -0
  58. package/native-window/native-window-interfaces.d.ts +186 -0
  59. package/native-window/native-window-interfaces.js +90 -0
  60. package/native-window/native-window-interfaces.js.map +1 -0
  61. package/native-window/native-window.android.d.ts +59 -0
  62. package/native-window/native-window.android.js +175 -0
  63. package/native-window/native-window.android.js.map +1 -0
  64. package/native-window/native-window.ios.d.ts +57 -0
  65. package/native-window/native-window.ios.js +208 -0
  66. package/native-window/native-window.ios.js.map +1 -0
  67. package/native-window/window-base.d.ts +103 -0
  68. package/native-window/window-base.js +78 -0
  69. package/native-window/window-base.js.map +1 -0
  70. package/package.json +1 -1
  71. package/platforms/android/widgets-release.aar +0 -0
  72. package/platforms/ios/TNSWidgets.xcframework/Info.plist +14 -14
  73. package/platforms/ios/TNSWidgets.xcframework/ios-arm64/TNSWidgets.framework/Info.plist +0 -0
  74. package/platforms/ios/TNSWidgets.xcframework/ios-arm64/TNSWidgets.framework/TNSWidgets +0 -0
  75. package/platforms/ios/TNSWidgets.xcframework/ios-arm64/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/DWARF/TNSWidgets +0 -0
  76. package/platforms/ios/TNSWidgets.xcframework/ios-arm64/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/Relocations/aarch64/TNSWidgets.yml +78 -78
  77. package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Resources/Info.plist +7 -7
  78. package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Versions/A/Resources/Info.plist +7 -7
  79. package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Versions/A/TNSWidgets +0 -0
  80. package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Versions/Current/Resources/Info.plist +7 -7
  81. package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Versions/Current/TNSWidgets +0 -0
  82. package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/DWARF/TNSWidgets +0 -0
  83. package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/Relocations/aarch64/TNSWidgets.yml +78 -78
  84. package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/Relocations/x86_64/TNSWidgets.yml +78 -78
  85. package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-simulator/TNSWidgets.framework/Info.plist +0 -0
  86. package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-simulator/TNSWidgets.framework/TNSWidgets +0 -0
  87. package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-simulator/TNSWidgets.framework/_CodeSignature/CodeResources +1 -1
  88. package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-simulator/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/DWARF/TNSWidgets +0 -0
  89. package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-simulator/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/Relocations/aarch64/TNSWidgets.yml +78 -78
  90. package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-simulator/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/Relocations/x86_64/TNSWidgets.yml +78 -78
  91. package/platforms/ios/TNSWidgets.xcframework/xros-arm64/TNSWidgets.framework/Info.plist +0 -0
  92. package/platforms/ios/TNSWidgets.xcframework/xros-arm64/TNSWidgets.framework/TNSWidgets +0 -0
  93. package/platforms/ios/TNSWidgets.xcframework/xros-arm64/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/DWARF/TNSWidgets +0 -0
  94. package/platforms/ios/TNSWidgets.xcframework/xros-arm64/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/Relocations/aarch64/TNSWidgets.yml +78 -78
  95. package/platforms/ios/TNSWidgets.xcframework/xros-arm64_x86_64-simulator/TNSWidgets.framework/Info.plist +0 -0
  96. package/platforms/ios/TNSWidgets.xcframework/xros-arm64_x86_64-simulator/TNSWidgets.framework/TNSWidgets +0 -0
  97. package/platforms/ios/TNSWidgets.xcframework/xros-arm64_x86_64-simulator/TNSWidgets.framework/_CodeSignature/CodeResources +1 -1
  98. package/platforms/ios/TNSWidgets.xcframework/xros-arm64_x86_64-simulator/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/DWARF/TNSWidgets +0 -0
  99. package/platforms/ios/TNSWidgets.xcframework/xros-arm64_x86_64-simulator/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/Relocations/aarch64/TNSWidgets.yml +78 -78
  100. package/platforms/ios/TNSWidgets.xcframework/xros-arm64_x86_64-simulator/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/Relocations/x86_64/TNSWidgets.yml +78 -78
  101. package/platforms/ios/src/NativeScriptMainWindow.swift +72 -39
  102. package/trace/index.d.ts +2 -2
  103. package/ui/action-bar/action-bar-common.js +0 -1
  104. package/ui/action-bar/action-bar-common.js.map +1 -1
  105. package/ui/animation/keyframe-animation.d.ts +1 -1
  106. package/ui/builder/index.js +9 -1
  107. package/ui/builder/index.js.map +1 -1
  108. package/ui/core/properties/index.d.ts +24 -1
  109. package/ui/core/properties/index.js +96 -10
  110. package/ui/core/properties/index.js.map +1 -1
  111. package/ui/core/properties/property-shared.js +11 -2
  112. package/ui/core/properties/property-shared.js.map +1 -1
  113. package/ui/core/view/index.android.js +29 -7
  114. package/ui/core/view/index.android.js.map +1 -1
  115. package/ui/core/view/index.d.ts +58 -1
  116. package/ui/core/view/index.ios.js +11 -2
  117. package/ui/core/view/index.ios.js.map +1 -1
  118. package/ui/core/view/view-common.d.ts +37 -0
  119. package/ui/core/view/view-common.js +81 -0
  120. package/ui/core/view/view-common.js.map +1 -1
  121. package/ui/core/view/view-helper/index.ios.d.ts +6 -20
  122. package/ui/core/view/view-helper/index.ios.js +10 -31
  123. package/ui/core/view/view-helper/index.ios.js.map +1 -1
  124. package/ui/core/view/view-helper/view-helper-common.js +21 -3
  125. package/ui/core/view/view-helper/view-helper-common.js.map +1 -1
  126. package/ui/core/view-base/index.d.ts +13 -8
  127. package/ui/core/view-base/index.js +54 -33
  128. package/ui/core/view-base/index.js.map +1 -1
  129. package/ui/frame/frame-common.d.ts +14 -2
  130. package/ui/frame/frame-common.js +19 -17
  131. package/ui/frame/frame-common.js.map +1 -1
  132. package/ui/frame/frame-constants.d.ts +9 -0
  133. package/ui/frame/frame-constants.js +10 -0
  134. package/ui/frame/frame-constants.js.map +1 -0
  135. package/ui/frame/frame-helper-for-android.d.ts +2 -2
  136. package/ui/frame/frame-helper-for-android.js +14 -5
  137. package/ui/frame/frame-helper-for-android.js.map +1 -1
  138. package/ui/frame/frame-interfaces.d.ts +1 -1
  139. package/ui/frame/frame-stack.d.ts +17 -1
  140. package/ui/frame/frame-stack.js +32 -5
  141. package/ui/frame/frame-stack.js.map +1 -1
  142. package/ui/frame/index.android.d.ts +1 -1
  143. package/ui/frame/index.android.js +139 -38
  144. package/ui/frame/index.android.js.map +1 -1
  145. package/ui/frame/index.d.ts +15 -5
  146. package/ui/image/image-common.js +1 -1
  147. package/ui/image/image-common.js.map +1 -1
  148. package/ui/image/index.android.js +13 -1
  149. package/ui/image/index.android.js.map +1 -1
  150. package/ui/layouts/absolute-layout/index.ios.js +4 -5
  151. package/ui/layouts/absolute-layout/index.ios.js.map +1 -1
  152. package/ui/layouts/dock-layout/index.ios.js +4 -5
  153. package/ui/layouts/dock-layout/index.ios.js.map +1 -1
  154. package/ui/layouts/flexbox-layout/flexbox-layout-common.d.ts +7 -0
  155. package/ui/layouts/flexbox-layout/flexbox-layout-common.js +18 -0
  156. package/ui/layouts/flexbox-layout/flexbox-layout-common.js.map +1 -1
  157. package/ui/layouts/flexbox-layout/index.android.d.ts +5 -0
  158. package/ui/layouts/flexbox-layout/index.android.js +15 -0
  159. package/ui/layouts/flexbox-layout/index.android.js.map +1 -1
  160. package/ui/layouts/flexbox-layout/index.d.ts +19 -1
  161. package/ui/layouts/flexbox-layout/index.ios.d.ts +2 -0
  162. package/ui/layouts/flexbox-layout/index.ios.js +245 -198
  163. package/ui/layouts/flexbox-layout/index.ios.js.map +1 -1
  164. package/ui/layouts/grid-layout/index.ios.js +4 -5
  165. package/ui/layouts/grid-layout/index.ios.js.map +1 -1
  166. package/ui/layouts/layout-base-common.d.ts +1 -0
  167. package/ui/layouts/layout-base-common.js +21 -0
  168. package/ui/layouts/layout-base-common.js.map +1 -1
  169. package/ui/layouts/stack-layout/index.ios.js +4 -5
  170. package/ui/layouts/stack-layout/index.ios.js.map +1 -1
  171. package/ui/layouts/wrap-layout/index.ios.js +4 -5
  172. package/ui/layouts/wrap-layout/index.ios.js.map +1 -1
  173. package/ui/list-view/index.android.js +3 -2
  174. package/ui/list-view/index.android.js.map +1 -1
  175. package/ui/list-view/index.ios.d.ts +2 -2
  176. package/ui/list-view/index.ios.js +15 -17
  177. package/ui/list-view/index.ios.js.map +1 -1
  178. package/ui/list-view/list-view-common.d.ts +1 -0
  179. package/ui/list-view/list-view-common.js +15 -0
  180. package/ui/list-view/list-view-common.js.map +1 -1
  181. package/ui/page/index.android.d.ts +1 -0
  182. package/ui/page/index.android.js +4 -0
  183. package/ui/page/index.android.js.map +1 -1
  184. package/ui/page/index.ios.d.ts +2 -1
  185. package/ui/page/index.ios.js +8 -5
  186. package/ui/page/index.ios.js.map +1 -1
  187. package/ui/scroll-view/index.d.ts +3 -5
  188. package/ui/scroll-view/index.ios.d.ts +3 -1
  189. package/ui/scroll-view/index.ios.js +26 -20
  190. package/ui/scroll-view/index.ios.js.map +1 -1
  191. package/ui/scroll-view/scroll-view-common.js +1 -1
  192. package/ui/scroll-view/scroll-view-common.js.map +1 -1
  193. package/ui/segmented-bar/segmented-bar-common.js +6 -1
  194. package/ui/segmented-bar/segmented-bar-common.js.map +1 -1
  195. package/ui/styling/background-common.d.ts +2 -0
  196. package/ui/styling/background-common.js +9 -0
  197. package/ui/styling/background-common.js.map +1 -1
  198. package/ui/styling/background.ios.js +2 -0
  199. package/ui/styling/background.ios.js.map +1 -1
  200. package/ui/styling/css-selector.d.ts +57 -13
  201. package/ui/styling/css-selector.js +280 -51
  202. package/ui/styling/css-selector.js.map +1 -1
  203. package/ui/styling/css-utils.d.ts +16 -0
  204. package/ui/styling/css-utils.js +121 -7
  205. package/ui/styling/css-utils.js.map +1 -1
  206. package/ui/styling/style/index.d.ts +11 -0
  207. package/ui/styling/style/index.js.map +1 -1
  208. package/ui/styling/style-properties.d.ts +5 -0
  209. package/ui/styling/style-properties.js +134 -74
  210. package/ui/styling/style-properties.js.map +1 -1
  211. package/ui/styling/style-scope.d.ts +15 -3
  212. package/ui/styling/style-scope.js +299 -56
  213. package/ui/styling/style-scope.js.map +1 -1
  214. package/ui/switch/index.ios.js +2 -1
  215. package/ui/switch/index.ios.js.map +1 -1
  216. package/ui/tab-view/index.android.d.ts +3 -1
  217. package/ui/tab-view/index.android.js +56 -46
  218. package/ui/tab-view/index.android.js.map +1 -1
  219. package/ui/tab-view/index.ios.js +1 -0
  220. package/ui/tab-view/index.ios.js.map +1 -1
  221. package/ui/tab-view/tab-view-common.d.ts +1 -0
  222. package/ui/tab-view/tab-view-common.js +16 -3
  223. package/ui/tab-view/tab-view-common.js.map +1 -1
  224. package/ui/text-base/index.android.d.ts +1 -1
  225. package/ui/text-base/index.android.js +8 -8
  226. package/ui/text-base/index.android.js.map +1 -1
  227. package/ui/text-base/index.ios.js +5 -3
  228. package/ui/text-base/index.ios.js.map +1 -1
  229. package/ui/transition/shared-transition.d.ts +1 -0
  230. package/ui/transition/shared-transition.js +13 -8
  231. package/ui/transition/shared-transition.js.map +1 -1
  232. package/utils/layout-helper/index.ios.js +11 -3
  233. package/utils/layout-helper/index.ios.js.map +1 -1
  234. package/utils/native-helper.d.ts +2 -2
@@ -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, MEDIA_QUERY_SEPARATOR, 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,15 +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;
57
+ const kebabCaseReplacementFunc = (g) => g[1].toUpperCase();
45
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
+ }
46
79
  /**
47
80
  * Evaluate css-variable and css-calc expressions
48
81
  */
@@ -61,13 +94,66 @@ function evaluateCssExpressions(view, property, value) {
61
94
  }
62
95
  return value;
63
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
+ */
64
101
  export function mergeCssSelectors() {
65
- mergedApplicationCssSelectors = applicationCssSelectors.slice();
66
- mergedApplicationCssSelectors.push(...applicationAdditionalSelectors);
102
+ mergedApplicationCssSelectorsInvalid = true;
67
103
  }
68
104
  export function mergeCssKeyframes() {
69
- mergedApplicationCssKeyframes = applicationCssKeyframes.slice();
70
- mergedApplicationCssKeyframes.push(...applicationAdditionalKeyframes);
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;
71
157
  }
72
158
  class CSSSource {
73
159
  constructor(_ast, _url, _file, _source) {
@@ -191,7 +277,7 @@ class CSSSource {
191
277
  this._selectors = [];
192
278
  }
193
279
  }
194
- async parseCSSAst() {
280
+ parseCSSAst() {
195
281
  if (this._source) {
196
282
  if (__CSS_PARSER__ === 'css-tree') {
197
283
  this._ast = cssTreeParse(this._source, this._file);
@@ -244,7 +330,7 @@ __decorate([
244
330
  profile,
245
331
  __metadata("design:type", Function),
246
332
  __metadata("design:paramtypes", []),
247
- __metadata("design:returntype", Promise)
333
+ __metadata("design:returntype", void 0)
248
334
  ], CSSSource.prototype, "parseCSSAst", null);
249
335
  __decorate([
250
336
  profile,
@@ -296,8 +382,20 @@ export function _populateRules(nodes, rulesets, keyframes, mediaQueryString) {
296
382
  keyframes.push(keyframeRule);
297
383
  }
298
384
  else if (isMedia(node)) {
299
- // Media query is composite in the case of nested media queries
300
- const compositeMediaQuery = mediaQueryString ? mediaQueryString + MEDIA_QUERY_SEPARATOR + node.media : node.media;
385
+ // Media query can be an array of strings in case of nested queries
386
+ let compositeMediaQuery;
387
+ if (mediaQueryString) {
388
+ if (typeof mediaQueryString === 'string') {
389
+ compositeMediaQuery = [mediaQueryString, node.media];
390
+ }
391
+ else {
392
+ mediaQueryString.push(node.media);
393
+ compositeMediaQuery = mediaQueryString;
394
+ }
395
+ }
396
+ else {
397
+ compositeMediaQuery = node.media;
398
+ }
301
399
  _populateRules(node.rules, rulesets, keyframes, compositeMediaQuery);
302
400
  }
303
401
  else if (isRule(node)) {
@@ -326,6 +424,8 @@ export function removeTaggedAdditionalCSS(tag) {
326
424
  }
327
425
  }
328
426
  if (selectorsChanged) {
427
+ // Rules were dropped from the middle of the list, so the index has to be rebuilt.
428
+ applicationSelectorsResetVersion++;
329
429
  mergeCssSelectors();
330
430
  updated = true;
331
431
  }
@@ -413,6 +513,8 @@ const loadCss = profile(`"style-scope".loadCss`, (cssModule) => {
413
513
  let updated = false;
414
514
  // Check for existing application css selectors too in case the app is undergoing a live-sync
415
515
  if (selectors.length > 0 || applicationCssSelectors.length > 0) {
516
+ // The base stylesheet is replaced rather than appended to.
517
+ applicationSelectorsResetVersion++;
416
518
  applicationCssSelectors = selectors;
417
519
  mergeCssSelectors();
418
520
  updated = true;
@@ -448,6 +550,36 @@ if (Application.hasLaunched()) {
448
550
  else {
449
551
  getNativeScriptGlobals().events.on('loadAppCss', loadAppCSS);
450
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
+ }
451
583
  export class CssState {
452
584
  constructor(viewRef) {
453
585
  this.viewRef = viewRef;
@@ -461,9 +593,13 @@ export class CssState {
461
593
  onChange() {
462
594
  const view = this.viewRef.get();
463
595
  if (view && view.isLoaded) {
464
- this.unsubscribeFromDynamicUpdates();
596
+ // Matching does not read the subscriptions, so re-subscribe only when the
597
+ // dependencies actually changed - they are usually identical.
465
598
  this.updateMatch();
466
- this.subscribeForDynamicUpdates();
599
+ if (!changeMapsEqual(this._appliedChangeMap, this._match.changeMap)) {
600
+ this.unsubscribeFromDynamicUpdates();
601
+ this.subscribeForDynamicUpdates();
602
+ }
467
603
  this.updateDynamicState();
468
604
  }
469
605
  else {
@@ -509,7 +645,14 @@ export class CssState {
509
645
  Trace.write(`updateDynamicState not executed to view because ".viewRef" is cleared`, Trace.categories.Style, Trace.messageType.warn);
510
646
  return;
511
647
  }
512
- const matchingSelectors = this._match.selectors.filter((sel) => (sel.dynamic ? sel.match(view) : true));
648
+ const selectors = this._match.selectors;
649
+ const matchingSelectors = [];
650
+ for (let i = 0, length = selectors.length; i < length; i++) {
651
+ const sel = selectors[i];
652
+ if (!sel.dynamic || sel.match(view)) {
653
+ matchingSelectors.push(sel);
654
+ }
655
+ }
513
656
  // Ideally we should return here if there are no matching selectors, however
514
657
  // if there are property removals, returning here would not remove them
515
658
  // this is seen in STYLE test in automated.
@@ -586,53 +729,117 @@ export class CssState {
586
729
  const oldProperties = this._appliedPropertyValues;
587
730
  // Update values for the scope's css-variables
588
731
  view.style.resetScopedCssVariables();
589
- const valuesToApply = {};
590
- const cssExpsProperties = {};
591
- const replacementFunc = (g) => g[1].toUpperCase();
732
+ let valuesToApply;
733
+ let cssExpsProperties;
734
+ let pendingProperties;
592
735
  for (const property in newPropertyValues) {
593
- const value = cleanupImportantFlags(newPropertyValues[property], property);
594
- const isCssExp = isCssVariableExpression(value) || isCssCalcExpression(value);
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));
595
747
  if (isCssExp) {
596
748
  // we handle css exp separately because css vars must be evaluated first
749
+ if (!cssExpsProperties) {
750
+ cssExpsProperties = {};
751
+ }
597
752
  cssExpsProperties[property] = value;
598
753
  continue;
599
754
  }
600
- delete oldProperties[property];
601
- if (property in oldProperties && oldProperties[property] === value) {
602
- // Skip unchanged values
603
- continue;
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];
604
760
  }
605
761
  if (isCssVariable(property)) {
762
+ // The scoped css-variables were just reset, so they always have to be re-registered.
606
763
  view.style.setScopedCssVariable(property, value);
607
764
  delete newPropertyValues[property];
608
765
  continue;
609
766
  }
767
+ if (unchanged) {
768
+ continue;
769
+ }
770
+ if (!valuesToApply) {
771
+ valuesToApply = {};
772
+ }
610
773
  valuesToApply[property] = value;
611
774
  }
612
775
  //we need to parse CSS vars first before evaluating css expressions
613
776
  for (const property in cssExpsProperties) {
614
- delete oldProperties[property];
777
+ const hadOldValue = property in oldProperties;
778
+ const oldValue = hadOldValue ? oldProperties[property] : undefined;
779
+ if (hadOldValue) {
780
+ delete oldProperties[property];
781
+ }
615
782
  const value = evaluateCssExpressions(view, property, cssExpsProperties[property]);
616
- if (property in oldProperties && oldProperties[property] === value) {
617
- // Skip unchanged values
783
+ if (isCssVariable(property)) {
784
+ view.style.setScopedCssVariable(property, value);
785
+ delete newPropertyValues[property];
618
786
  continue;
619
787
  }
620
788
  if (value === unsetValue) {
621
789
  delete newPropertyValues[property];
622
790
  }
623
- if (isCssVariable(property)) {
624
- view.style.setScopedCssVariable(property, value);
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) {
625
822
  delete newPropertyValues[property];
626
823
  }
824
+ else {
825
+ newPropertyValues[property] = value;
826
+ }
827
+ if (hadOldValue && oldValue === value) {
828
+ continue;
829
+ }
830
+ if (!valuesToApply) {
831
+ valuesToApply = {};
832
+ }
627
833
  valuesToApply[property] = value;
628
834
  }
629
- // 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.
630
837
  for (const property in oldProperties) {
631
838
  if (property in view.style) {
632
839
  view.style[`css:${property}`] = unsetValue;
633
840
  }
634
841
  else {
635
- const camelCasedProperty = property.replace(kebabCasePattern, replacementFunc);
842
+ const camelCasedProperty = property.replace(kebabCasePattern, kebabCaseReplacementFunc);
636
843
  view[camelCasedProperty] = unsetValue;
637
844
  }
638
845
  }
@@ -644,7 +851,7 @@ export class CssState {
644
851
  view.style[`css:${property}`] = value;
645
852
  }
646
853
  else {
647
- const camelCasedProperty = property.replace(kebabCasePattern, replacementFunc);
854
+ const camelCasedProperty = property.replace(kebabCasePattern, kebabCaseReplacementFunc);
648
855
  view[camelCasedProperty] = value;
649
856
  }
650
857
  }
@@ -730,12 +937,13 @@ CssState.prototype._matchInvalid = true;
730
937
  export class StyleScope {
731
938
  constructor() {
732
939
  this._css = '';
940
+ this._hasSelectors = false;
733
941
  this._localCssSelectors = [];
734
942
  this._localCssKeyframes = [];
735
943
  this._localCssSelectorVersion = 0;
736
944
  this._localCssSelectorsAppliedVersion = 0;
737
945
  this._applicationCssSelectorsAppliedVersion = 0;
738
- this._cssFiles = [];
946
+ this._cssFiles = new Set();
739
947
  }
740
948
  get css() {
741
949
  return this._css;
@@ -753,7 +961,7 @@ export class StyleScope {
753
961
  if (!cssFileName) {
754
962
  return;
755
963
  }
756
- this._cssFiles.push(cssFileName);
964
+ this._cssFiles.add(cssFileName);
757
965
  currentScopeTag = cssFileName;
758
966
  const cssFile = CSSSource.fromURI(cssFileName);
759
967
  currentScopeTag = null;
@@ -776,7 +984,7 @@ export class StyleScope {
776
984
  return;
777
985
  }
778
986
  if (cssFileName) {
779
- this._cssFiles.push(cssFileName);
987
+ this._cssFiles.add(cssFileName);
780
988
  currentScopeTag = cssFileName;
781
989
  }
782
990
  const cssFile = cssString ? CSSSource.fromSource(cssString, cssFileName) : CSSSource.fromURI(cssFileName);
@@ -797,11 +1005,25 @@ export class StyleScope {
797
1005
  return animation;
798
1006
  }
799
1007
  ensureSelectors() {
800
- if (!this.isApplicationCssSelectorsLatestVersionApplied() || !this.isLocalCssSelectorsLatestVersionApplied() || !this._mergedCssSelectors) {
1008
+ if (!this.isApplicationCssSelectorsLatestVersionApplied() || !this.isLocalCssSelectorsLatestVersionApplied()) {
801
1009
  this._createSelectors();
802
1010
  }
803
1011
  return this.getSelectorsVersion();
804
1012
  }
1013
+ /**
1014
+ * True when any selector in the scope contains an adjacent sibling ('+') combinator.
1015
+ */
1016
+ get hasAdjacentCombinatorSelectors() {
1017
+ this.ensureSelectors();
1018
+ return !!applicationSelectorScope?.hasAdjacentCombinatorSelectors || !!this._localSelectorScope?.hasAdjacentCombinatorSelectors;
1019
+ }
1020
+ /**
1021
+ * True when any selector in the scope contains a general sibling ('~') combinator.
1022
+ */
1023
+ get hasSiblingCombinatorSelectors() {
1024
+ this.ensureSelectors();
1025
+ return !!applicationSelectorScope?.hasSiblingCombinatorSelectors || !!this._localSelectorScope?.hasSiblingCombinatorSelectors;
1026
+ }
805
1027
  /**
806
1028
  * Increase the application CSS selector version.
807
1029
  */
@@ -815,38 +1037,43 @@ export class StyleScope {
815
1037
  return this._localCssSelectorsAppliedVersion === this._localCssSelectorVersion;
816
1038
  }
817
1039
  _createSelectors() {
818
- const toMerge = [];
819
- const toMergeKeyframes = [];
820
- toMerge.push(...mergedApplicationCssSelectors.filter((v) => !v.scopedTag || this._cssFiles.indexOf(v.scopedTag) >= 0));
821
- toMergeKeyframes.push(...mergedApplicationCssKeyframes.filter((v) => !v.scopedTag || this._cssFiles.indexOf(v.scopedTag) >= 0));
1040
+ const cssFiles = this._cssFiles;
1041
+ const applicationScope = getApplicationSelectorScope();
822
1042
  this._applicationCssSelectorsAppliedVersion = applicationCssSelectorVersion;
823
- toMerge.push(...this._localCssSelectors);
824
- toMergeKeyframes.push(...this._localCssKeyframes);
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
+ }
825
1046
  this._localCssSelectorsAppliedVersion = this._localCssSelectorVersion;
826
- if (toMerge.length > 0) {
827
- this._mergedCssSelectors = toMerge;
828
- this._selectorScope = new StyleSheetSelectorScope(this._mergedCssSelectors);
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
+ }
829
1055
  }
830
- else {
831
- this._mergedCssSelectors = null;
832
- this._selectorScope = null;
1056
+ const localKeyframes = this._localCssKeyframes;
1057
+ for (let i = 0, length = localKeyframes.length; i < length; i++) {
1058
+ toMergeKeyframes.push(localKeyframes[i]);
833
1059
  }
834
1060
  this._mergedCssKeyframes = toMergeKeyframes.length > 0 ? toMergeKeyframes : null;
835
1061
  }
836
1062
  // HACK: This @profile decorator creates a circular dependency
837
1063
  // HACK: because the function parameter type is evaluated with 'typeof'
838
1064
  matchSelectors(view) {
839
- let match;
840
1065
  // should be (view: ViewBase): SelectorsMatch<ViewBase>
841
1066
  this.ensureSelectors();
842
- if (this._selectorScope) {
843
- match = this._selectorScope.query(view);
844
- // Make sure to re-apply keyframes to matching selectors as a media query keyframe might be applicable at this point
845
- this._applyKeyframesToSelectors(match.selectors);
846
- }
847
- else {
848
- match = null;
1067
+ if (!this._hasSelectors) {
1068
+ return null;
849
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);
850
1077
  return match;
851
1078
  }
852
1079
  query(node) {
@@ -979,6 +1206,8 @@ export const applyInlineStyle = profile('applyInlineStyle', function applyInline
979
1206
  view.style.setUnscopedCssVariable(property, d.value);
980
1207
  }
981
1208
  });
1209
+ // Pending-substitution longhands share one placeholder - resolve it once.
1210
+ let resolvedShorthands;
982
1211
  inlineRuleSet[0].declarations.forEach((d) => {
983
1212
  // Use the actual property name so that a local value is set.
984
1213
  const property = d.property;
@@ -987,7 +1216,21 @@ export const applyInlineStyle = profile('applyInlineStyle', function applyInline
987
1216
  // Skip css-variables, they have been handled
988
1217
  return;
989
1218
  }
990
- const value = evaluateCssExpressions(view, property, d.value);
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
+ }
991
1234
  if (property in view.style) {
992
1235
  view.style[property] = value;
993
1236
  }