@jesscss/core 2.0.0-alpha.4 → 2.0.0-alpha.6

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 (637) hide show
  1. package/lib/index.cjs +20159 -0
  2. package/lib/index.d.cts +5993 -0
  3. package/lib/index.d.cts.map +1 -0
  4. package/lib/index.d.ts +5992 -21
  5. package/lib/index.d.ts.map +1 -1
  6. package/lib/index.js +19926 -22
  7. package/lib/index.js.map +1 -1
  8. package/package.json +15 -14
  9. package/src/__tests__/define-function-record.test.ts +58 -0
  10. package/src/__tests__/define-function-simple.test.ts +55 -0
  11. package/src/__tests__/define-function-split-sequence.test.ts +547 -0
  12. package/src/__tests__/define-function-type-parity.test.ts +9 -0
  13. package/src/__tests__/define-function.test.ts +763 -0
  14. package/src/__tests__/num-operations.test.ts +91 -0
  15. package/src/__tests__/safe-parse.test.ts +374 -0
  16. package/src/context.ts +896 -0
  17. package/src/conversions.ts +282 -0
  18. package/src/debug-log.ts +29 -0
  19. package/src/define-function.ts +1006 -0
  20. package/src/deprecation.ts +67 -0
  21. package/src/globals.d.ts +26 -0
  22. package/src/index.ts +31 -0
  23. package/src/jess-error.ts +773 -0
  24. package/src/logger/deprecation-processing.ts +109 -0
  25. package/src/logger.ts +31 -0
  26. package/src/plugin.ts +292 -0
  27. package/src/tree/LOOKUP_CHAINS.md +35 -0
  28. package/src/tree/README.md +18 -0
  29. package/src/tree/__tests__/__snapshots__/extend-eval-integration.test.ts.snap +1455 -0
  30. package/src/tree/__tests__/ampersand.test.ts +382 -0
  31. package/src/tree/__tests__/at-rule.test.ts +2047 -0
  32. package/src/tree/__tests__/basic-render.test.ts +212 -0
  33. package/src/tree/__tests__/block.test.ts +40 -0
  34. package/src/tree/__tests__/call.test.ts +346 -0
  35. package/src/tree/__tests__/color.test.ts +537 -0
  36. package/src/tree/__tests__/condition.test.ts +186 -0
  37. package/src/tree/__tests__/control.test.ts +564 -0
  38. package/src/tree/__tests__/declaration.test.ts +253 -0
  39. package/src/tree/__tests__/dependency-graph.test.ts +177 -0
  40. package/src/tree/__tests__/detached-rulesets.test.ts +213 -0
  41. package/src/tree/__tests__/dimension.test.ts +236 -0
  42. package/src/tree/__tests__/expression.test.ts +73 -0
  43. package/src/tree/__tests__/ext-node.test.ts +31 -0
  44. package/src/tree/__tests__/extend-eval-integration.test.ts +1033 -0
  45. package/src/tree/__tests__/extend-import-style.test.ts +929 -0
  46. package/src/tree/__tests__/extend-less-fixtures.test.ts +851 -0
  47. package/src/tree/__tests__/extend-list.test.ts +31 -0
  48. package/src/tree/__tests__/extend-roots.test.ts +1045 -0
  49. package/src/tree/__tests__/extend-rules.test.ts +740 -0
  50. package/src/tree/__tests__/func.test.ts +171 -0
  51. package/src/tree/__tests__/import-js.test.ts +33 -0
  52. package/src/tree/__tests__/import-style-test-helpers.ts +56 -0
  53. package/src/tree/__tests__/import-style.test.ts +1967 -0
  54. package/src/tree/__tests__/interpolated-reference.test.ts +44 -0
  55. package/src/tree/__tests__/interpolated.test.ts +41 -0
  56. package/src/tree/__tests__/list.test.ts +177 -0
  57. package/src/tree/__tests__/log.test.ts +83 -0
  58. package/src/tree/__tests__/mixin-recursion.test.ts +639 -0
  59. package/src/tree/__tests__/mixin.test.ts +2171 -0
  60. package/src/tree/__tests__/negative.test.ts +45 -0
  61. package/src/tree/__tests__/nesting-collapse.test.ts +519 -0
  62. package/src/tree/__tests__/node-flags-perf.test.ts +195 -0
  63. package/src/tree/__tests__/node-flags.test.ts +410 -0
  64. package/src/tree/__tests__/node-graph.test.ts +598 -0
  65. package/src/tree/__tests__/node-mutation.test.ts +182 -0
  66. package/src/tree/__tests__/operation.test.ts +18 -0
  67. package/src/tree/__tests__/paren.test.ts +90 -0
  68. package/src/tree/__tests__/preserve-mode-output.test.ts +50 -0
  69. package/src/tree/__tests__/quoted.test.ts +72 -0
  70. package/src/tree/__tests__/range.test.ts +59 -0
  71. package/src/tree/__tests__/reference.test.ts +743 -0
  72. package/src/tree/__tests__/rest.test.ts +29 -0
  73. package/src/tree/__tests__/rules-raw.test.ts +14 -0
  74. package/src/tree/__tests__/rules.test.ts +1271 -0
  75. package/src/tree/__tests__/ruleset.test.ts +597 -0
  76. package/src/tree/__tests__/selector-attr.test.ts +50 -0
  77. package/src/tree/__tests__/selector-basic.test.ts +44 -0
  78. package/src/tree/__tests__/selector-capture.test.ts +22 -0
  79. package/src/tree/__tests__/selector-complex.test.ts +120 -0
  80. package/src/tree/__tests__/selector-compound.test.ts +74 -0
  81. package/src/tree/__tests__/selector-interpolated.test.ts +50 -0
  82. package/src/tree/__tests__/selector-list.test.ts +59 -0
  83. package/src/tree/__tests__/selector-pseudo.test.ts +23 -0
  84. package/src/tree/__tests__/selector.test.ts +182 -0
  85. package/src/tree/__tests__/sequence.test.ts +226 -0
  86. package/src/tree/__tests__/serialize-types.test.ts +529 -0
  87. package/src/tree/__tests__/spaced.test.ts +8 -0
  88. package/src/tree/__tests__/url.test.ts +72 -0
  89. package/src/tree/__tests__/var-declaration.test.ts +90 -0
  90. package/src/tree/ampersand.ts +538 -0
  91. package/src/tree/any.ts +169 -0
  92. package/src/tree/at-rule.ts +760 -0
  93. package/src/tree/block.ts +72 -0
  94. package/src/tree/bool.ts +46 -0
  95. package/src/tree/call.ts +593 -0
  96. package/src/tree/collection.ts +52 -0
  97. package/src/tree/color.ts +629 -0
  98. package/src/tree/combinator.ts +30 -0
  99. package/src/tree/comment.ts +36 -0
  100. package/src/tree/condition.ts +194 -0
  101. package/src/tree/control.ts +452 -0
  102. package/src/tree/declaration-custom.ts +56 -0
  103. package/src/tree/declaration-var.ts +87 -0
  104. package/src/tree/declaration.ts +742 -0
  105. package/src/tree/default-guard.ts +35 -0
  106. package/src/tree/dimension.ts +392 -0
  107. package/src/tree/expression.ts +97 -0
  108. package/src/tree/extend-list.ts +51 -0
  109. package/src/tree/extend.ts +391 -0
  110. package/src/tree/function.ts +254 -0
  111. package/src/tree/import-js.ts +130 -0
  112. package/src/tree/import-style.ts +875 -0
  113. package/{lib/tree/index.js → src/tree/index.ts} +49 -22
  114. package/src/tree/interpolated.ts +346 -0
  115. package/src/tree/js-array.ts +21 -0
  116. package/src/tree/js-expr.ts +50 -0
  117. package/src/tree/js-function.ts +31 -0
  118. package/src/tree/js-object.ts +22 -0
  119. package/src/tree/list.ts +415 -0
  120. package/src/tree/log.ts +89 -0
  121. package/src/tree/mixin.ts +331 -0
  122. package/src/tree/negative.ts +58 -0
  123. package/src/tree/nil.ts +57 -0
  124. package/src/tree/node-base.ts +1716 -0
  125. package/src/tree/node-type.ts +122 -0
  126. package/src/tree/node.ts +118 -0
  127. package/src/tree/number.ts +54 -0
  128. package/src/tree/operation.ts +187 -0
  129. package/src/tree/paren.ts +132 -0
  130. package/src/tree/query-condition.ts +47 -0
  131. package/src/tree/quoted.ts +119 -0
  132. package/src/tree/range.ts +101 -0
  133. package/src/tree/reference.ts +1099 -0
  134. package/src/tree/rest.ts +55 -0
  135. package/src/tree/rules-raw.ts +52 -0
  136. package/src/tree/rules.ts +2896 -0
  137. package/src/tree/ruleset.ts +1217 -0
  138. package/src/tree/selector-attr.ts +172 -0
  139. package/src/tree/selector-basic.ts +75 -0
  140. package/src/tree/selector-capture.ts +85 -0
  141. package/src/tree/selector-complex.ts +189 -0
  142. package/src/tree/selector-compound.ts +205 -0
  143. package/src/tree/selector-interpolated.ts +95 -0
  144. package/src/tree/selector-list.ts +245 -0
  145. package/src/tree/selector-pseudo.ts +173 -0
  146. package/src/tree/selector-simple.ts +10 -0
  147. package/src/tree/selector.ts +152 -0
  148. package/src/tree/sequence.ts +463 -0
  149. package/src/tree/tree.ts +130 -0
  150. package/src/tree/url.ts +95 -0
  151. package/src/tree/util/EXTEND_ARCHITECTURE_ANALYSIS.md +215 -0
  152. package/src/tree/util/EXTEND_AUDIT.md +233 -0
  153. package/src/tree/util/EXTEND_BASELINE.md +64 -0
  154. package/src/tree/util/EXTEND_CALL_GRAPH_ANALYSIS.md +244 -0
  155. package/src/tree/util/EXTEND_DOCS.md +24 -0
  156. package/src/tree/util/EXTEND_FINAL_SUMMARY.md +95 -0
  157. package/src/tree/util/EXTEND_FUNCTION_AUDIT.md +1433 -0
  158. package/src/tree/util/EXTEND_OPTIMIZATION_PLAN.md +114 -0
  159. package/src/tree/util/EXTEND_REFACTORING_SUMMARY.md +152 -0
  160. package/src/tree/util/EXTEND_RULES.md +74 -0
  161. package/src/tree/util/EXTEND_UNUSED_FUNCTIONS.md +127 -0
  162. package/src/tree/util/EXTEND_UNUSED_FUNCTIONS_ANALYSIS.md +227 -0
  163. package/src/tree/util/NODE_COPY_REDUCTION_PLAN.md +12 -0
  164. package/src/tree/util/__tests__/EXTEND_TEST_INDEX.md +59 -0
  165. package/src/tree/util/__tests__/OPTIMIZATION-ANALYSIS.md +130 -0
  166. package/src/tree/util/__tests__/WALK_AND_CONSUME_DESIGN.md +138 -0
  167. package/src/tree/util/__tests__/_archive/2026-02-09__OPTIMIZATION-ANALYSIS.md +9 -0
  168. package/src/tree/util/__tests__/_archive/README.md +4 -0
  169. package/src/tree/util/__tests__/bitset.test.ts +142 -0
  170. package/src/tree/util/__tests__/debug-log.ts +50 -0
  171. package/src/tree/util/__tests__/extend-comment-handling.test.ts +187 -0
  172. package/src/tree/util/__tests__/extend-core-unit.test.ts +941 -0
  173. package/src/tree/util/__tests__/extend-pipeline-bench.test.ts +154 -0
  174. package/src/tree/util/__tests__/extend-pipeline-bench.ts +190 -0
  175. package/src/tree/util/__tests__/fast-reject.test.ts +377 -0
  176. package/src/tree/util/__tests__/is-node.test.ts +63 -0
  177. package/src/tree/util/__tests__/list-like.test.ts +63 -0
  178. package/src/tree/util/__tests__/outputwriter.test.ts +523 -0
  179. package/src/tree/util/__tests__/print.test.ts +183 -0
  180. package/src/tree/util/__tests__/process-extends.test.ts +226 -0
  181. package/src/tree/util/__tests__/process-leading-is.test.ts +205 -0
  182. package/src/tree/util/__tests__/recursion-helper.test.ts +184 -0
  183. package/src/tree/util/__tests__/selector-match-unit.test.ts +1427 -0
  184. package/src/tree/util/__tests__/sourcemap.test.ts +117 -0
  185. package/src/tree/util/ampersand-template.ts +9 -0
  186. package/src/tree/util/bitset.ts +194 -0
  187. package/src/tree/util/calculate.ts +11 -0
  188. package/src/tree/util/cast.ts +89 -0
  189. package/src/tree/util/cloning.ts +8 -0
  190. package/src/tree/util/collections.ts +299 -0
  191. package/src/tree/util/compare.ts +90 -0
  192. package/src/tree/util/cursor.ts +171 -0
  193. package/src/tree/util/extend-core.ts +2139 -0
  194. package/src/tree/util/extend-roots.ts +1108 -0
  195. package/src/tree/util/field-helpers.ts +354 -0
  196. package/src/tree/util/is-node.ts +43 -0
  197. package/src/tree/util/list-like.ts +93 -0
  198. package/src/tree/util/mixin-instance-primitives.ts +2020 -0
  199. package/src/tree/util/print.ts +303 -0
  200. package/src/tree/util/process-leading-is.ts +421 -0
  201. package/src/tree/util/recursion-helper.ts +54 -0
  202. package/src/tree/util/regex.ts +2 -0
  203. package/src/tree/util/registry-utils.ts +1953 -0
  204. package/src/tree/util/ruleset-trace.ts +17 -0
  205. package/src/tree/util/scoped-body-eval.ts +320 -0
  206. package/src/tree/util/selector-match-core.ts +2005 -0
  207. package/src/tree/util/selector-utils.ts +757 -0
  208. package/src/tree/util/serialize-helper.ts +535 -0
  209. package/src/tree/util/serialize-types.ts +318 -0
  210. package/src/tree/util/should-operate.ts +78 -0
  211. package/src/tree/util/sourcemap.ts +37 -0
  212. package/src/types/config.ts +247 -0
  213. package/src/types/index.ts +12 -0
  214. package/{lib/types/modes.d.ts → src/types/modes.ts} +2 -1
  215. package/src/types.d.ts +9 -0
  216. package/src/types.ts +68 -0
  217. package/src/use-webpack-resolver.ts +56 -0
  218. package/src/visitor/__tests__/visitor.test.ts +136 -0
  219. package/src/visitor/index.ts +263 -0
  220. package/{lib/visitor/less-visitor.js → src/visitor/less-visitor.ts} +3 -2
  221. package/lib/context.d.ts +0 -352
  222. package/lib/context.d.ts.map +0 -1
  223. package/lib/context.js +0 -636
  224. package/lib/context.js.map +0 -1
  225. package/lib/conversions.d.ts +0 -73
  226. package/lib/conversions.d.ts.map +0 -1
  227. package/lib/conversions.js +0 -253
  228. package/lib/conversions.js.map +0 -1
  229. package/lib/debug-log.d.ts +0 -2
  230. package/lib/debug-log.d.ts.map +0 -1
  231. package/lib/debug-log.js +0 -27
  232. package/lib/debug-log.js.map +0 -1
  233. package/lib/define-function.d.ts +0 -587
  234. package/lib/define-function.d.ts.map +0 -1
  235. package/lib/define-function.js +0 -726
  236. package/lib/define-function.js.map +0 -1
  237. package/lib/deprecation.d.ts +0 -34
  238. package/lib/deprecation.d.ts.map +0 -1
  239. package/lib/deprecation.js +0 -57
  240. package/lib/deprecation.js.map +0 -1
  241. package/lib/jess-error.d.ts +0 -343
  242. package/lib/jess-error.d.ts.map +0 -1
  243. package/lib/jess-error.js +0 -508
  244. package/lib/jess-error.js.map +0 -1
  245. package/lib/logger/deprecation-processing.d.ts +0 -41
  246. package/lib/logger/deprecation-processing.d.ts.map +0 -1
  247. package/lib/logger/deprecation-processing.js +0 -81
  248. package/lib/logger/deprecation-processing.js.map +0 -1
  249. package/lib/logger.d.ts +0 -10
  250. package/lib/logger.d.ts.map +0 -1
  251. package/lib/logger.js +0 -20
  252. package/lib/logger.js.map +0 -1
  253. package/lib/plugin.d.ts +0 -94
  254. package/lib/plugin.d.ts.map +0 -1
  255. package/lib/plugin.js +0 -174
  256. package/lib/plugin.js.map +0 -1
  257. package/lib/tree/ampersand.d.ts +0 -94
  258. package/lib/tree/ampersand.d.ts.map +0 -1
  259. package/lib/tree/ampersand.js +0 -269
  260. package/lib/tree/ampersand.js.map +0 -1
  261. package/lib/tree/any.d.ts +0 -58
  262. package/lib/tree/any.d.ts.map +0 -1
  263. package/lib/tree/any.js +0 -104
  264. package/lib/tree/any.js.map +0 -1
  265. package/lib/tree/at-rule.d.ts +0 -53
  266. package/lib/tree/at-rule.d.ts.map +0 -1
  267. package/lib/tree/at-rule.js +0 -503
  268. package/lib/tree/at-rule.js.map +0 -1
  269. package/lib/tree/block.d.ts +0 -22
  270. package/lib/tree/block.d.ts.map +0 -1
  271. package/lib/tree/block.js +0 -24
  272. package/lib/tree/block.js.map +0 -1
  273. package/lib/tree/bool.d.ts +0 -18
  274. package/lib/tree/bool.d.ts.map +0 -1
  275. package/lib/tree/bool.js +0 -28
  276. package/lib/tree/bool.js.map +0 -1
  277. package/lib/tree/call.d.ts +0 -66
  278. package/lib/tree/call.d.ts.map +0 -1
  279. package/lib/tree/call.js +0 -306
  280. package/lib/tree/call.js.map +0 -1
  281. package/lib/tree/collection.d.ts +0 -30
  282. package/lib/tree/collection.d.ts.map +0 -1
  283. package/lib/tree/collection.js +0 -37
  284. package/lib/tree/collection.js.map +0 -1
  285. package/lib/tree/color.d.ts +0 -101
  286. package/lib/tree/color.d.ts.map +0 -1
  287. package/lib/tree/color.js +0 -513
  288. package/lib/tree/color.js.map +0 -1
  289. package/lib/tree/combinator.d.ts +0 -13
  290. package/lib/tree/combinator.d.ts.map +0 -1
  291. package/lib/tree/combinator.js +0 -12
  292. package/lib/tree/combinator.js.map +0 -1
  293. package/lib/tree/comment.d.ts +0 -20
  294. package/lib/tree/comment.d.ts.map +0 -1
  295. package/lib/tree/comment.js +0 -19
  296. package/lib/tree/comment.js.map +0 -1
  297. package/lib/tree/condition.d.ts +0 -31
  298. package/lib/tree/condition.d.ts.map +0 -1
  299. package/lib/tree/condition.js +0 -103
  300. package/lib/tree/condition.js.map +0 -1
  301. package/lib/tree/control.d.ts +0 -104
  302. package/lib/tree/control.d.ts.map +0 -1
  303. package/lib/tree/control.js +0 -430
  304. package/lib/tree/control.js.map +0 -1
  305. package/lib/tree/declaration-custom.d.ts +0 -18
  306. package/lib/tree/declaration-custom.d.ts.map +0 -1
  307. package/lib/tree/declaration-custom.js +0 -24
  308. package/lib/tree/declaration-custom.js.map +0 -1
  309. package/lib/tree/declaration-var.d.ts +0 -35
  310. package/lib/tree/declaration-var.d.ts.map +0 -1
  311. package/lib/tree/declaration-var.js +0 -63
  312. package/lib/tree/declaration-var.js.map +0 -1
  313. package/lib/tree/declaration.d.ts +0 -78
  314. package/lib/tree/declaration.d.ts.map +0 -1
  315. package/lib/tree/declaration.js +0 -286
  316. package/lib/tree/declaration.js.map +0 -1
  317. package/lib/tree/default-guard.d.ts +0 -15
  318. package/lib/tree/default-guard.d.ts.map +0 -1
  319. package/lib/tree/default-guard.js +0 -19
  320. package/lib/tree/default-guard.js.map +0 -1
  321. package/lib/tree/dimension.d.ts +0 -34
  322. package/lib/tree/dimension.d.ts.map +0 -1
  323. package/lib/tree/dimension.js +0 -294
  324. package/lib/tree/dimension.js.map +0 -1
  325. package/lib/tree/expression.d.ts +0 -25
  326. package/lib/tree/expression.d.ts.map +0 -1
  327. package/lib/tree/expression.js +0 -32
  328. package/lib/tree/expression.js.map +0 -1
  329. package/lib/tree/extend-list.d.ts +0 -23
  330. package/lib/tree/extend-list.d.ts.map +0 -1
  331. package/lib/tree/extend-list.js +0 -23
  332. package/lib/tree/extend-list.js.map +0 -1
  333. package/lib/tree/extend.d.ts +0 -47
  334. package/lib/tree/extend.d.ts.map +0 -1
  335. package/lib/tree/extend.js +0 -296
  336. package/lib/tree/extend.js.map +0 -1
  337. package/lib/tree/function.d.ts +0 -48
  338. package/lib/tree/function.d.ts.map +0 -1
  339. package/lib/tree/function.js +0 -74
  340. package/lib/tree/function.js.map +0 -1
  341. package/lib/tree/import-js.d.ts +0 -35
  342. package/lib/tree/import-js.d.ts.map +0 -1
  343. package/lib/tree/import-js.js +0 -45
  344. package/lib/tree/import-js.js.map +0 -1
  345. package/lib/tree/import-style.d.ts +0 -156
  346. package/lib/tree/import-style.d.ts.map +0 -1
  347. package/lib/tree/import-style.js +0 -566
  348. package/lib/tree/import-style.js.map +0 -1
  349. package/lib/tree/index.d.ts +0 -71
  350. package/lib/tree/index.d.ts.map +0 -1
  351. package/lib/tree/index.js.map +0 -1
  352. package/lib/tree/interpolated-reference.d.ts +0 -24
  353. package/lib/tree/interpolated-reference.d.ts.map +0 -1
  354. package/lib/tree/interpolated-reference.js +0 -37
  355. package/lib/tree/interpolated-reference.js.map +0 -1
  356. package/lib/tree/interpolated.d.ts +0 -62
  357. package/lib/tree/interpolated.d.ts.map +0 -1
  358. package/lib/tree/interpolated.js +0 -204
  359. package/lib/tree/interpolated.js.map +0 -1
  360. package/lib/tree/js-array.d.ts +0 -10
  361. package/lib/tree/js-array.d.ts.map +0 -1
  362. package/lib/tree/js-array.js +0 -10
  363. package/lib/tree/js-array.js.map +0 -1
  364. package/lib/tree/js-expr.d.ts +0 -23
  365. package/lib/tree/js-expr.d.ts.map +0 -1
  366. package/lib/tree/js-expr.js +0 -28
  367. package/lib/tree/js-expr.js.map +0 -1
  368. package/lib/tree/js-function.d.ts +0 -20
  369. package/lib/tree/js-function.d.ts.map +0 -1
  370. package/lib/tree/js-function.js +0 -16
  371. package/lib/tree/js-function.js.map +0 -1
  372. package/lib/tree/js-object.d.ts +0 -10
  373. package/lib/tree/js-object.d.ts.map +0 -1
  374. package/lib/tree/js-object.js +0 -10
  375. package/lib/tree/js-object.js.map +0 -1
  376. package/lib/tree/list.d.ts +0 -38
  377. package/lib/tree/list.d.ts.map +0 -1
  378. package/lib/tree/list.js +0 -83
  379. package/lib/tree/list.js.map +0 -1
  380. package/lib/tree/log.d.ts +0 -29
  381. package/lib/tree/log.d.ts.map +0 -1
  382. package/lib/tree/log.js +0 -56
  383. package/lib/tree/log.js.map +0 -1
  384. package/lib/tree/mixin.d.ts +0 -87
  385. package/lib/tree/mixin.d.ts.map +0 -1
  386. package/lib/tree/mixin.js +0 -112
  387. package/lib/tree/mixin.js.map +0 -1
  388. package/lib/tree/negative.d.ts +0 -17
  389. package/lib/tree/negative.d.ts.map +0 -1
  390. package/lib/tree/negative.js +0 -22
  391. package/lib/tree/negative.js.map +0 -1
  392. package/lib/tree/nil.d.ts +0 -30
  393. package/lib/tree/nil.d.ts.map +0 -1
  394. package/lib/tree/nil.js +0 -35
  395. package/lib/tree/nil.js.map +0 -1
  396. package/lib/tree/node-base.d.ts +0 -361
  397. package/lib/tree/node-base.d.ts.map +0 -1
  398. package/lib/tree/node-base.js +0 -930
  399. package/lib/tree/node-base.js.map +0 -1
  400. package/lib/tree/node.d.ts +0 -10
  401. package/lib/tree/node.d.ts.map +0 -1
  402. package/lib/tree/node.js +0 -45
  403. package/lib/tree/node.js.map +0 -1
  404. package/lib/tree/number.d.ts +0 -21
  405. package/lib/tree/number.d.ts.map +0 -1
  406. package/lib/tree/number.js +0 -27
  407. package/lib/tree/number.js.map +0 -1
  408. package/lib/tree/operation.d.ts +0 -26
  409. package/lib/tree/operation.d.ts.map +0 -1
  410. package/lib/tree/operation.js +0 -103
  411. package/lib/tree/operation.js.map +0 -1
  412. package/lib/tree/paren.d.ts +0 -19
  413. package/lib/tree/paren.d.ts.map +0 -1
  414. package/lib/tree/paren.js +0 -92
  415. package/lib/tree/paren.js.map +0 -1
  416. package/lib/tree/query-condition.d.ts +0 -17
  417. package/lib/tree/query-condition.d.ts.map +0 -1
  418. package/lib/tree/query-condition.js +0 -39
  419. package/lib/tree/query-condition.js.map +0 -1
  420. package/lib/tree/quoted.d.ts +0 -28
  421. package/lib/tree/quoted.d.ts.map +0 -1
  422. package/lib/tree/quoted.js +0 -75
  423. package/lib/tree/quoted.js.map +0 -1
  424. package/lib/tree/range.d.ts +0 -33
  425. package/lib/tree/range.d.ts.map +0 -1
  426. package/lib/tree/range.js +0 -47
  427. package/lib/tree/range.js.map +0 -1
  428. package/lib/tree/reference.d.ts +0 -76
  429. package/lib/tree/reference.d.ts.map +0 -1
  430. package/lib/tree/reference.js +0 -521
  431. package/lib/tree/reference.js.map +0 -1
  432. package/lib/tree/rest.d.ts +0 -15
  433. package/lib/tree/rest.d.ts.map +0 -1
  434. package/lib/tree/rest.js +0 -32
  435. package/lib/tree/rest.js.map +0 -1
  436. package/lib/tree/rules-raw.d.ts +0 -17
  437. package/lib/tree/rules-raw.d.ts.map +0 -1
  438. package/lib/tree/rules-raw.js +0 -37
  439. package/lib/tree/rules-raw.js.map +0 -1
  440. package/lib/tree/rules.d.ts +0 -262
  441. package/lib/tree/rules.d.ts.map +0 -1
  442. package/lib/tree/rules.js +0 -2359
  443. package/lib/tree/rules.js.map +0 -1
  444. package/lib/tree/ruleset.d.ts +0 -92
  445. package/lib/tree/ruleset.d.ts.map +0 -1
  446. package/lib/tree/ruleset.js +0 -528
  447. package/lib/tree/ruleset.js.map +0 -1
  448. package/lib/tree/selector-attr.d.ts +0 -31
  449. package/lib/tree/selector-attr.d.ts.map +0 -1
  450. package/lib/tree/selector-attr.js +0 -99
  451. package/lib/tree/selector-attr.js.map +0 -1
  452. package/lib/tree/selector-basic.d.ts +0 -24
  453. package/lib/tree/selector-basic.d.ts.map +0 -1
  454. package/lib/tree/selector-basic.js +0 -38
  455. package/lib/tree/selector-basic.js.map +0 -1
  456. package/lib/tree/selector-capture.d.ts +0 -23
  457. package/lib/tree/selector-capture.d.ts.map +0 -1
  458. package/lib/tree/selector-capture.js +0 -34
  459. package/lib/tree/selector-capture.js.map +0 -1
  460. package/lib/tree/selector-complex.d.ts +0 -40
  461. package/lib/tree/selector-complex.d.ts.map +0 -1
  462. package/lib/tree/selector-complex.js +0 -143
  463. package/lib/tree/selector-complex.js.map +0 -1
  464. package/lib/tree/selector-compound.d.ts +0 -16
  465. package/lib/tree/selector-compound.d.ts.map +0 -1
  466. package/lib/tree/selector-compound.js +0 -114
  467. package/lib/tree/selector-compound.js.map +0 -1
  468. package/lib/tree/selector-interpolated.d.ts +0 -23
  469. package/lib/tree/selector-interpolated.d.ts.map +0 -1
  470. package/lib/tree/selector-interpolated.js +0 -27
  471. package/lib/tree/selector-interpolated.js.map +0 -1
  472. package/lib/tree/selector-list.d.ts +0 -17
  473. package/lib/tree/selector-list.d.ts.map +0 -1
  474. package/lib/tree/selector-list.js +0 -174
  475. package/lib/tree/selector-list.js.map +0 -1
  476. package/lib/tree/selector-pseudo.d.ts +0 -42
  477. package/lib/tree/selector-pseudo.d.ts.map +0 -1
  478. package/lib/tree/selector-pseudo.js +0 -204
  479. package/lib/tree/selector-pseudo.js.map +0 -1
  480. package/lib/tree/selector-simple.d.ts +0 -5
  481. package/lib/tree/selector-simple.d.ts.map +0 -1
  482. package/lib/tree/selector-simple.js +0 -6
  483. package/lib/tree/selector-simple.js.map +0 -1
  484. package/lib/tree/selector.d.ts +0 -43
  485. package/lib/tree/selector.d.ts.map +0 -1
  486. package/lib/tree/selector.js +0 -56
  487. package/lib/tree/selector.js.map +0 -1
  488. package/lib/tree/sequence.d.ts +0 -43
  489. package/lib/tree/sequence.d.ts.map +0 -1
  490. package/lib/tree/sequence.js +0 -151
  491. package/lib/tree/sequence.js.map +0 -1
  492. package/lib/tree/tree.d.ts +0 -87
  493. package/lib/tree/tree.d.ts.map +0 -1
  494. package/lib/tree/tree.js +0 -2
  495. package/lib/tree/tree.js.map +0 -1
  496. package/lib/tree/url.d.ts +0 -18
  497. package/lib/tree/url.d.ts.map +0 -1
  498. package/lib/tree/url.js +0 -35
  499. package/lib/tree/url.js.map +0 -1
  500. package/lib/tree/util/__tests__/debug-log.d.ts +0 -1
  501. package/lib/tree/util/__tests__/debug-log.d.ts.map +0 -1
  502. package/lib/tree/util/__tests__/debug-log.js +0 -36
  503. package/lib/tree/util/__tests__/debug-log.js.map +0 -1
  504. package/lib/tree/util/calculate.d.ts +0 -3
  505. package/lib/tree/util/calculate.d.ts.map +0 -1
  506. package/lib/tree/util/calculate.js +0 -10
  507. package/lib/tree/util/calculate.js.map +0 -1
  508. package/lib/tree/util/cast.d.ts +0 -10
  509. package/lib/tree/util/cast.d.ts.map +0 -1
  510. package/lib/tree/util/cast.js +0 -87
  511. package/lib/tree/util/cast.js.map +0 -1
  512. package/lib/tree/util/cloning.d.ts +0 -4
  513. package/lib/tree/util/cloning.d.ts.map +0 -1
  514. package/lib/tree/util/cloning.js +0 -8
  515. package/lib/tree/util/cloning.js.map +0 -1
  516. package/lib/tree/util/collections.d.ts +0 -57
  517. package/lib/tree/util/collections.d.ts.map +0 -1
  518. package/lib/tree/util/collections.js +0 -136
  519. package/lib/tree/util/collections.js.map +0 -1
  520. package/lib/tree/util/compare.d.ts +0 -11
  521. package/lib/tree/util/compare.d.ts.map +0 -1
  522. package/lib/tree/util/compare.js +0 -89
  523. package/lib/tree/util/compare.js.map +0 -1
  524. package/lib/tree/util/extend-helpers.d.ts +0 -2
  525. package/lib/tree/util/extend-helpers.d.ts.map +0 -1
  526. package/lib/tree/util/extend-helpers.js +0 -2
  527. package/lib/tree/util/extend-helpers.js.map +0 -1
  528. package/lib/tree/util/extend-roots.d.ts +0 -37
  529. package/lib/tree/util/extend-roots.d.ts.map +0 -1
  530. package/lib/tree/util/extend-roots.js +0 -700
  531. package/lib/tree/util/extend-roots.js.map +0 -1
  532. package/lib/tree/util/extend-roots.old.d.ts +0 -132
  533. package/lib/tree/util/extend-roots.old.d.ts.map +0 -1
  534. package/lib/tree/util/extend-roots.old.js +0 -2272
  535. package/lib/tree/util/extend-roots.old.js.map +0 -1
  536. package/lib/tree/util/extend-trace-debug.d.ts +0 -13
  537. package/lib/tree/util/extend-trace-debug.d.ts.map +0 -1
  538. package/lib/tree/util/extend-trace-debug.js +0 -34
  539. package/lib/tree/util/extend-trace-debug.js.map +0 -1
  540. package/lib/tree/util/extend-walk.d.ts +0 -53
  541. package/lib/tree/util/extend-walk.d.ts.map +0 -1
  542. package/lib/tree/util/extend-walk.js +0 -881
  543. package/lib/tree/util/extend-walk.js.map +0 -1
  544. package/lib/tree/util/extend.d.ts +0 -218
  545. package/lib/tree/util/extend.d.ts.map +0 -1
  546. package/lib/tree/util/extend.js +0 -3182
  547. package/lib/tree/util/extend.js.map +0 -1
  548. package/lib/tree/util/find-extendable-locations.d.ts +0 -2
  549. package/lib/tree/util/find-extendable-locations.d.ts.map +0 -1
  550. package/lib/tree/util/find-extendable-locations.js +0 -2
  551. package/lib/tree/util/find-extendable-locations.js.map +0 -1
  552. package/lib/tree/util/format.d.ts +0 -20
  553. package/lib/tree/util/format.d.ts.map +0 -1
  554. package/lib/tree/util/format.js +0 -67
  555. package/lib/tree/util/format.js.map +0 -1
  556. package/lib/tree/util/is-node.d.ts +0 -13
  557. package/lib/tree/util/is-node.d.ts.map +0 -1
  558. package/lib/tree/util/is-node.js +0 -43
  559. package/lib/tree/util/is-node.js.map +0 -1
  560. package/lib/tree/util/print.d.ts +0 -80
  561. package/lib/tree/util/print.d.ts.map +0 -1
  562. package/lib/tree/util/print.js +0 -205
  563. package/lib/tree/util/print.js.map +0 -1
  564. package/lib/tree/util/process-leading-is.d.ts +0 -25
  565. package/lib/tree/util/process-leading-is.d.ts.map +0 -1
  566. package/lib/tree/util/process-leading-is.js +0 -364
  567. package/lib/tree/util/process-leading-is.js.map +0 -1
  568. package/lib/tree/util/recursion-helper.d.ts +0 -15
  569. package/lib/tree/util/recursion-helper.d.ts.map +0 -1
  570. package/lib/tree/util/recursion-helper.js +0 -43
  571. package/lib/tree/util/recursion-helper.js.map +0 -1
  572. package/lib/tree/util/regex.d.ts +0 -4
  573. package/lib/tree/util/regex.d.ts.map +0 -1
  574. package/lib/tree/util/regex.js +0 -4
  575. package/lib/tree/util/regex.js.map +0 -1
  576. package/lib/tree/util/registry-utils.d.ts +0 -192
  577. package/lib/tree/util/registry-utils.d.ts.map +0 -1
  578. package/lib/tree/util/registry-utils.js +0 -1214
  579. package/lib/tree/util/registry-utils.js.map +0 -1
  580. package/lib/tree/util/ruleset-trace.d.ts +0 -4
  581. package/lib/tree/util/ruleset-trace.d.ts.map +0 -1
  582. package/lib/tree/util/ruleset-trace.js +0 -14
  583. package/lib/tree/util/ruleset-trace.js.map +0 -1
  584. package/lib/tree/util/selector-compare.d.ts +0 -2
  585. package/lib/tree/util/selector-compare.d.ts.map +0 -1
  586. package/lib/tree/util/selector-compare.js +0 -2
  587. package/lib/tree/util/selector-compare.js.map +0 -1
  588. package/lib/tree/util/selector-match-core.d.ts +0 -184
  589. package/lib/tree/util/selector-match-core.d.ts.map +0 -1
  590. package/lib/tree/util/selector-match-core.js +0 -1603
  591. package/lib/tree/util/selector-match-core.js.map +0 -1
  592. package/lib/tree/util/selector-utils.d.ts +0 -30
  593. package/lib/tree/util/selector-utils.d.ts.map +0 -1
  594. package/lib/tree/util/selector-utils.js +0 -100
  595. package/lib/tree/util/selector-utils.js.map +0 -1
  596. package/lib/tree/util/serialize-helper.d.ts +0 -13
  597. package/lib/tree/util/serialize-helper.d.ts.map +0 -1
  598. package/lib/tree/util/serialize-helper.js +0 -387
  599. package/lib/tree/util/serialize-helper.js.map +0 -1
  600. package/lib/tree/util/serialize-types.d.ts +0 -9
  601. package/lib/tree/util/serialize-types.d.ts.map +0 -1
  602. package/lib/tree/util/serialize-types.js +0 -216
  603. package/lib/tree/util/serialize-types.js.map +0 -1
  604. package/lib/tree/util/should-operate.d.ts +0 -23
  605. package/lib/tree/util/should-operate.d.ts.map +0 -1
  606. package/lib/tree/util/should-operate.js +0 -46
  607. package/lib/tree/util/should-operate.js.map +0 -1
  608. package/lib/tree/util/sourcemap.d.ts +0 -7
  609. package/lib/tree/util/sourcemap.d.ts.map +0 -1
  610. package/lib/tree/util/sourcemap.js +0 -25
  611. package/lib/tree/util/sourcemap.js.map +0 -1
  612. package/lib/types/config.d.ts +0 -205
  613. package/lib/types/config.d.ts.map +0 -1
  614. package/lib/types/config.js +0 -2
  615. package/lib/types/config.js.map +0 -1
  616. package/lib/types/index.d.ts +0 -15
  617. package/lib/types/index.d.ts.map +0 -1
  618. package/lib/types/index.js +0 -3
  619. package/lib/types/index.js.map +0 -1
  620. package/lib/types/modes.d.ts.map +0 -1
  621. package/lib/types/modes.js +0 -2
  622. package/lib/types/modes.js.map +0 -1
  623. package/lib/types.d.ts +0 -61
  624. package/lib/types.d.ts.map +0 -1
  625. package/lib/types.js +0 -2
  626. package/lib/types.js.map +0 -1
  627. package/lib/use-webpack-resolver.d.ts +0 -9
  628. package/lib/use-webpack-resolver.d.ts.map +0 -1
  629. package/lib/use-webpack-resolver.js +0 -41
  630. package/lib/use-webpack-resolver.js.map +0 -1
  631. package/lib/visitor/index.d.ts +0 -136
  632. package/lib/visitor/index.d.ts.map +0 -1
  633. package/lib/visitor/index.js +0 -135
  634. package/lib/visitor/index.js.map +0 -1
  635. package/lib/visitor/less-visitor.d.ts +0 -7
  636. package/lib/visitor/less-visitor.d.ts.map +0 -1
  637. package/lib/visitor/less-visitor.js.map +0 -1
@@ -0,0 +1,1108 @@
1
+ import type { Context } from '../../context.js';
2
+ import { WARN, toDiagnostic } from '../../jess-error.js';
3
+ import type { AtRule } from '../at-rule.js';
4
+ import type { Node } from '../node.js';
5
+ import type { Rules } from '../rules.js';
6
+ import type { Ruleset } from '../ruleset.js';
7
+ import type { Selector } from '../selector.js';
8
+ import { CompoundSelector } from '../selector-compound.js';
9
+ import { ComplexSelector, type ComplexSelectorComponent } from '../selector-complex.js';
10
+ import { SelectorList } from '../selector-list.js';
11
+ import { PseudoSelector } from '../selector-pseudo.js';
12
+
13
+ import { isNode } from './is-node.js';
14
+ import { N } from '../node-type.js';
15
+ import { Nil } from '../nil.js';
16
+ import { F_EXTENDED, F_VISIBLE } from '../node.js';
17
+ import { selectorMatch } from './selector-match-core.js';
18
+ import { tryExtendSelector } from './extend-core.js';
19
+ import { getCurrentParentNode, getImplicitSelector, localizeSelectorAgainstParent, getParentRuleset, hasSourceExtendWrapperParent, isBareAmpersandOwnSelector, selectorHasAuthoredAmpersand } from './selector-utils.js';
20
+
21
+ /**
22
+ * Extend-root orchestration is intentionally record-driven:
23
+ *
24
+ * 1. During eval, qualifying scopes register themselves as extend roots.
25
+ * 2. Rulesets register directly against the current extend root.
26
+ * 3. Extend processing consumes only recorded roots/rulesets/instructions.
27
+ *
28
+ * This file should not discover roots or child roots by walking the node tree.
29
+ * Extend support must stay close to zero-cost when no extends are present, so
30
+ * all expensive work is deferred until we have both recorded rulesets and
31
+ * recorded extend instructions to apply.
32
+ *
33
+ * @todo Once the extend test matrix is green, do a dedicated performance review
34
+ * of extend-root orchestration. Re-check:
35
+ * - zero-work behavior when no extends are present
36
+ * - repeat-pass behavior and termination characteristics under load
37
+ * - cache invalidation costs
38
+ * - whether any remaining selector rewrites can be deferred to serialization
39
+ */
40
+
41
+ function invalidateSelectorCache(selector?: Selector | Nil): void {
42
+ if (!selector || isNode(selector, N.Nil)) {
43
+ return;
44
+ }
45
+ selector.invalidateCache();
46
+ }
47
+
48
+ function invalidateRulesetSelectorCaches(ruleset: Ruleset, context?: Context): void {
49
+ ruleset.invalidateSelectorValueCache();
50
+ invalidateSelectorCache(ruleset.get('selector', context));
51
+ invalidateSelectorCache(context ? ruleset.get('_extendedSelector', context) : ruleset.getExtendedSelector());
52
+ invalidateSelectorCache(ruleset.getOwnSelector(context));
53
+ invalidateSelectorCache(context ? ruleset.get('selectorBeforeExtend', context) : ruleset.getSelectorBeforeExtend());
54
+ const rules = ruleset.enterRules(context);
55
+ if (!rules || !isNode(rules, N.Rules)) {
56
+ return;
57
+ }
58
+ for (const child of (rules as Rules).value) {
59
+ if (isNode(child, N.Ruleset)) {
60
+ invalidateRulesetSelectorCaches(child as Ruleset, context);
61
+ }
62
+ }
63
+ }
64
+
65
+ function refreshNestedRulesetSelectors(parentRuleset: Ruleset, context?: Context): void {
66
+ const rules = parentRuleset.enterRules(context);
67
+ if (!rules || !isNode(rules, N.Rules)) {
68
+ return;
69
+ }
70
+
71
+ const parentSelector = parentRuleset.getEffectiveSelector(false, context);
72
+ if (!parentSelector || isNode(parentSelector, N.Nil)) {
73
+ return;
74
+ }
75
+
76
+ for (const child of (rules as Rules).value) {
77
+ if (!isNode(child, N.Ruleset)) {
78
+ continue;
79
+ }
80
+
81
+ const childRuleset = child as Ruleset;
82
+ syncRulesetDerivedSelector(childRuleset, context);
83
+ refreshNestedRulesetSelectors(childRuleset, context);
84
+ }
85
+ }
86
+
87
+ function hasReferenceBoundaryParent(ruleset: Ruleset, context?: Context): boolean {
88
+ const parent = getCurrentParentNode(ruleset, context);
89
+ return Boolean(
90
+ parent
91
+ && isNode(parent, N.Rules)
92
+ && (parent as Rules).options?.referenceMode === true
93
+ );
94
+ }
95
+
96
+ function parentRulesetOwnsDerivedSelectorState(parentRuleset: Ruleset, context?: Context): boolean {
97
+ const extendedSelector = context
98
+ ? parentRuleset.get('_extendedSelector', context)
99
+ : parentRuleset.getExtendedSelector();
100
+ if (extendedSelector !== undefined) {
101
+ return true;
102
+ }
103
+ const selectorBeforeExtend = context
104
+ ? parentRuleset.get('selectorBeforeExtend', context)
105
+ : parentRuleset.getSelectorBeforeExtend();
106
+ if (selectorBeforeExtend !== undefined) {
107
+ return true;
108
+ }
109
+ return getRulesetHoistToRoot(parentRuleset, context) === true;
110
+ }
111
+
112
+ function getDerivedSelectorFromParent(ruleset: Ruleset, context?: Context): Selector | Nil | undefined {
113
+ const ownSelector = ruleset.getOwnSelector(context);
114
+ if (!ownSelector || isNode(ownSelector, N.Nil)) {
115
+ return undefined;
116
+ }
117
+ if (isBareAmpersandOwnSelector(ownSelector) && hasReferenceBoundaryParent(ruleset, context)) {
118
+ return undefined;
119
+ }
120
+
121
+ const parentRuleset = getParentRuleset(ruleset, context);
122
+ if (!parentRuleset || !parentRulesetOwnsDerivedSelectorState(parentRuleset, context)) {
123
+ return undefined;
124
+ }
125
+ const parentSelector = parentRuleset?.getEffectiveSelector(false, context);
126
+ if (!parentSelector || isNode(parentSelector, N.Nil)) {
127
+ return undefined;
128
+ }
129
+
130
+ const composedSelector = getImplicitSelector(ownSelector, parentSelector, false);
131
+ const currentSelector = ruleset.get('selector', context);
132
+ if (!isNode(currentSelector, N.Nil) && composedSelector.valueOf() === currentSelector.valueOf()) {
133
+ return undefined;
134
+ }
135
+
136
+ return composedSelector;
137
+ }
138
+
139
+ function syncRulesetDerivedSelector(ruleset: Ruleset, context?: Context): void {
140
+ const derivedSelector = getDerivedSelectorFromParent(ruleset, context);
141
+ ruleset.setExtendedSelector(derivedSelector, context);
142
+ }
143
+
144
+ function normalizeGeneratedIsOrder(selector: Selector, insideGeneratedIs = false): Selector {
145
+ if (isNode(selector, N.SelectorList)) {
146
+ return SelectorList.create(
147
+ (selector as SelectorList).get('value').map(item => normalizeGeneratedIsOrder(item as Selector, insideGeneratedIs))
148
+ ).inherit(selector) as Selector;
149
+ }
150
+
151
+ if (isNode(selector, N.ComplexSelector)) {
152
+ return ComplexSelector.create(
153
+ (selector as ComplexSelector).get('value').map(part =>
154
+ normalizeGeneratedIsOrder(part as Selector, insideGeneratedIs) as ComplexSelectorComponent
155
+ )
156
+ ).inherit(selector) as Selector;
157
+ }
158
+
159
+ if (isNode(selector, N.CompoundSelector)) {
160
+ const normalizedMembers = (selector as CompoundSelector).get('value').map(child =>
161
+ normalizeGeneratedIsOrder(child as Selector, insideGeneratedIs)
162
+ );
163
+ if (!insideGeneratedIs) {
164
+ return CompoundSelector.create(normalizedMembers).inherit(selector) as Selector;
165
+ }
166
+ const generatedIs = normalizedMembers.filter(member =>
167
+ isNode(member, N.PseudoSelector)
168
+ && member.generated
169
+ && member.get('name') === ':is'
170
+ );
171
+ if (generatedIs.length !== 1 || generatedIs[0] === normalizedMembers[0]) {
172
+ return CompoundSelector.create(normalizedMembers).inherit(selector) as Selector;
173
+ }
174
+ const leadingGeneratedIs = generatedIs[0]!;
175
+ const others = normalizedMembers.filter(member => member !== leadingGeneratedIs);
176
+ return CompoundSelector.create([
177
+ leadingGeneratedIs,
178
+ ...others
179
+ ]).inherit(selector) as Selector;
180
+ }
181
+
182
+ if (isNode(selector, N.PseudoSelector)) {
183
+ const arg = selector.get('arg');
184
+ if (arg && isNode(arg, N.Selector)) {
185
+ const copy = selector.copy(true) as PseudoSelector;
186
+ const nextArg = normalizeGeneratedIsOrder(
187
+ arg as Selector,
188
+ insideGeneratedIs || (selector.generated && selector.get('name') === ':is')
189
+ );
190
+ copy.adopt(nextArg);
191
+ copy.arg = nextArg;
192
+ return copy as Selector;
193
+ }
194
+ }
195
+
196
+ return selector;
197
+ }
198
+
199
+ type ExtendRootRecord = {
200
+ rules: Rules;
201
+ parent?: Rules;
202
+ children: Set<Rules>;
203
+ rulesets: Set<Ruleset>;
204
+ layerName?: string;
205
+ isProtected: boolean;
206
+ isCompose: boolean;
207
+ namespace?: string;
208
+ };
209
+
210
+ export class ExtendRootRegistry {
211
+ private rootRecords = new WeakMap<Rules, ExtendRootRecord>();
212
+ private rootsByLayerName = new Map<string, Set<Rules>>();
213
+ private rootsByNamespace = new Map<string, Set<Rules>>();
214
+ private layerNames = new WeakMap<AtRule, string>();
215
+ private allRoots = new Set<Rules>();
216
+ private visibleRootsCache = new WeakMap<Rules, Set<Rules>>();
217
+
218
+ root?: Rules;
219
+ extendRootStack: Rules[] = [];
220
+
221
+ private ensureRootRecord(rules: Rules): ExtendRootRecord {
222
+ let record = this.rootRecords.get(rules);
223
+ if (!record) {
224
+ record = {
225
+ rules,
226
+ children: new Set(),
227
+ rulesets: new Set(),
228
+ isProtected: false,
229
+ isCompose: false
230
+ };
231
+ this.rootRecords.set(rules, record);
232
+ this.allRoots.add(rules);
233
+ this.visibleRootsCache = new WeakMap();
234
+ }
235
+ return record;
236
+ }
237
+
238
+ getCurrentExtendRoot(): Rules | undefined {
239
+ return this.extendRootStack[this.extendRootStack.length - 1];
240
+ }
241
+
242
+ registerRoot(
243
+ rules: Rules,
244
+ parent?: Rules,
245
+ options?: { layerName?: string; isProtected?: boolean; isCompose?: boolean; namespace?: string }
246
+ ): void {
247
+ const record = this.ensureRootRecord(rules);
248
+ if (!this.root) {
249
+ this.root = rules;
250
+ }
251
+
252
+ if (parent) {
253
+ const parentRecord = this.ensureRootRecord(parent);
254
+ record.parent = parent;
255
+ parentRecord.children.add(rules);
256
+ }
257
+
258
+ if (options?.layerName) {
259
+ record.layerName = options.layerName;
260
+ let layerRoots = this.rootsByLayerName.get(options.layerName);
261
+ if (!layerRoots) {
262
+ layerRoots = new Set<Rules>();
263
+ this.rootsByLayerName.set(options.layerName, layerRoots);
264
+ }
265
+ layerRoots.add(rules);
266
+ }
267
+
268
+ if (options?.namespace) {
269
+ record.namespace = options.namespace;
270
+ let nsRoots = this.rootsByNamespace.get(options.namespace);
271
+ if (!nsRoots) {
272
+ nsRoots = new Set<Rules>();
273
+ this.rootsByNamespace.set(options.namespace, nsRoots);
274
+ }
275
+ nsRoots.add(rules);
276
+ }
277
+
278
+ if (options?.isProtected) {
279
+ record.isProtected = true;
280
+ }
281
+ if (options?.isCompose) {
282
+ record.isCompose = true;
283
+ }
284
+ this.visibleRootsCache = new WeakMap();
285
+ }
286
+
287
+ registerRuleset(root: Rules, ruleset: Ruleset): void {
288
+ if (!root || !ruleset) {
289
+ return;
290
+ }
291
+ this.ensureRootRecord(root).rulesets.add(ruleset);
292
+ }
293
+
294
+ getRulesets(root: Rules): ReadonlySet<Ruleset> | undefined {
295
+ return this.rootRecords.get(root)?.rulesets;
296
+ }
297
+
298
+ clearRegisteredRulesets(): void {
299
+ for (const root of this.allRoots) {
300
+ this.rootRecords.get(root)?.rulesets.clear();
301
+ }
302
+ }
303
+
304
+ getAllRoots(): Set<Rules> {
305
+ return new Set(this.allRoots);
306
+ }
307
+
308
+ pushExtendRoot(rules: Rules): void {
309
+ this.extendRootStack.push(rules);
310
+ }
311
+
312
+ popExtendRoot(): void {
313
+ this.extendRootStack.pop();
314
+ }
315
+
316
+ getVisibleRoots(root: Rules): Set<Rules> {
317
+ return this.getAccessibleRoots(root);
318
+ }
319
+
320
+ getAccessibleRoots(root: Rules): Set<Rules> {
321
+ const cached = this.visibleRootsCache.get(root);
322
+ if (cached) {
323
+ return cached;
324
+ }
325
+
326
+ const accessible = new Set<Rules>();
327
+ const visited = new Set<Rules>();
328
+
329
+ const traverseChildren = (currentRoot: Rules): void => {
330
+ if (visited.has(currentRoot)) {
331
+ return;
332
+ }
333
+ visited.add(currentRoot);
334
+ accessible.add(currentRoot);
335
+
336
+ const currentRecord = this.rootRecords.get(currentRoot);
337
+ if (!currentRecord) {
338
+ return;
339
+ }
340
+
341
+ if (currentRecord.isProtected) {
342
+ return;
343
+ }
344
+
345
+ if (currentRecord.children.size) {
346
+ for (const child of currentRecord.children) {
347
+ if (this.rootRecords.get(child)?.isProtected) {
348
+ continue;
349
+ }
350
+ traverseChildren(child);
351
+ }
352
+ }
353
+
354
+ const layer = currentRecord.layerName;
355
+ if (layer) {
356
+ const sameLayerRoots = this.rootsByLayerName.get(layer);
357
+ if (sameLayerRoots) {
358
+ for (const layerRoot of sameLayerRoots) {
359
+ if (layerRoot !== currentRoot && !visited.has(layerRoot) && !this.rootRecords.get(layerRoot)?.isProtected) {
360
+ accessible.add(layerRoot);
361
+ traverseChildren(layerRoot);
362
+ }
363
+ }
364
+ }
365
+ }
366
+ };
367
+
368
+ traverseChildren(root);
369
+ this.visibleRootsCache.set(root, accessible);
370
+ return accessible;
371
+ }
372
+
373
+ isRootInNamespace(root: Rules, namespace: string): boolean {
374
+ const namespaceRoots = this.rootsByNamespace.get(namespace);
375
+ if (!namespaceRoots?.size) {
376
+ return false;
377
+ }
378
+ for (const namespaceRoot of namespaceRoots) {
379
+ if (this.getAccessibleRoots(namespaceRoot).has(root)) {
380
+ return true;
381
+ }
382
+ }
383
+ return false;
384
+ }
385
+
386
+ isSameOrDescendantRoot(rulesetRoot: Rules, extendRoot: Rules): boolean {
387
+ if (rulesetRoot === extendRoot) {
388
+ return true;
389
+ }
390
+ const rulesetRecord = this.rootRecords.get(rulesetRoot);
391
+ if (!rulesetRecord) {
392
+ return false;
393
+ }
394
+ if (rulesetRecord.isProtected) {
395
+ return false;
396
+ }
397
+ const layerA = rulesetRecord.layerName;
398
+ const layerB = this.rootRecords.get(extendRoot)?.layerName;
399
+ if (layerA && layerB && layerA === layerB) {
400
+ return true;
401
+ }
402
+ const extendRecord = this.rootRecords.get(extendRoot);
403
+ if (!extendRecord || extendRecord.children.size === 0) {
404
+ return false;
405
+ }
406
+ for (const child of extendRecord.children) {
407
+ if (this.rootRecords.get(child)?.isProtected) {
408
+ continue;
409
+ }
410
+ if (this.isSameOrDescendantRoot(rulesetRoot, child)) {
411
+ return true;
412
+ }
413
+ }
414
+ return false;
415
+ }
416
+
417
+ setLayerName(atRule: AtRule, layerName: string): void {
418
+ this.layerNames.set(atRule, layerName);
419
+ }
420
+
421
+ getLayerName(atRule: AtRule): string | undefined {
422
+ return this.layerNames.get(atRule);
423
+ }
424
+
425
+ takeLayerName(atRule: AtRule): string | undefined {
426
+ const layer = this.layerNames.get(atRule);
427
+ if (layer) {
428
+ this.layerNames.delete(atRule);
429
+ }
430
+ return layer;
431
+ }
432
+
433
+ isProtectedRoot(rules: Rules): boolean {
434
+ return this.rootRecords.get(rules)?.isProtected === true;
435
+ }
436
+ }
437
+
438
+ function isInstructionVisibleForRoot(
439
+ context: Context,
440
+ rootRules: Rules,
441
+ instruction: {
442
+ extendRoot?: Rules;
443
+ fromReferenceScope: boolean;
444
+ namespace?: string;
445
+ },
446
+ getCachedVisibleRoots?: (root: Rules) => Set<Rules>
447
+ ): boolean {
448
+ if (!instruction.extendRoot) {
449
+ return false;
450
+ }
451
+ if (instruction.fromReferenceScope === true) {
452
+ return false;
453
+ }
454
+ if (context.extendRoots.isProtectedRoot(rootRules) && instruction.extendRoot !== rootRules) {
455
+ return false;
456
+ }
457
+ if (instruction.namespace) {
458
+ if (instruction.namespace === '*') {
459
+ return true;
460
+ }
461
+ return context.extendRoots.isRootInNamespace(rootRules, instruction.namespace);
462
+ }
463
+ if (instruction.extendRoot === rootRules) {
464
+ return true;
465
+ }
466
+ if (context.extendRoots.isSameOrDescendantRoot(rootRules, instruction.extendRoot)) {
467
+ return true;
468
+ }
469
+ const visibleRoots = getCachedVisibleRoots
470
+ ? getCachedVisibleRoots(instruction.extendRoot)
471
+ : context.extendRoots.getVisibleRoots(instruction.extendRoot);
472
+ return visibleRoots.has(rootRules);
473
+ }
474
+
475
+ function isRootWithinInstructionNamespace(
476
+ context: Context,
477
+ rootRules: Rules,
478
+ instruction: {
479
+ namespace?: string;
480
+ }
481
+ ): boolean {
482
+ if (!instruction.namespace || instruction.namespace === '*') {
483
+ return true;
484
+ }
485
+ return context.extendRoots.isRootInNamespace(rootRules, instruction.namespace);
486
+ }
487
+
488
+ type RecordedExtendInstruction = {
489
+ target: Selector;
490
+ extendWith: Selector;
491
+ partial: boolean;
492
+ extendRoot: Rules;
493
+ extendNode: Node;
494
+ fromReferenceScope: boolean;
495
+ namespace?: string;
496
+ };
497
+
498
+ type TargetInfo = ReturnType<typeof getRulesetExtendTarget>;
499
+ type TargetInfoCache = WeakMap<Ruleset, Map<RecordedExtendInstruction, TargetInfo>>;
500
+
501
+ function getCachedTargetInfo(
502
+ cache: TargetInfoCache | undefined,
503
+ ruleset: Ruleset,
504
+ instruction: RecordedExtendInstruction,
505
+ context?: Context
506
+ ): TargetInfo {
507
+ if (cache) {
508
+ let perRuleset = cache.get(ruleset);
509
+ if (perRuleset?.has(instruction)) {
510
+ return perRuleset.get(instruction);
511
+ }
512
+ const result = getRulesetExtendTarget(ruleset, instruction.target, instruction.partial, context);
513
+ if (!perRuleset) {
514
+ perRuleset = new Map();
515
+ cache.set(ruleset, perRuleset);
516
+ }
517
+ perRuleset.set(instruction, result);
518
+ return result;
519
+ }
520
+ return getRulesetExtendTarget(ruleset, instruction.target, instruction.partial, context);
521
+ }
522
+
523
+ function invalidateTargetInfoCacheTree(cache: TargetInfoCache, ruleset: Ruleset): void {
524
+ cache.delete(ruleset);
525
+ const rules = ruleset.get('rules');
526
+ if (!rules || !isNode(rules, N.Rules)) {
527
+ return;
528
+ }
529
+ for (const child of (rules as Rules).value) {
530
+ if (isNode(child, N.Ruleset)) {
531
+ invalidateTargetInfoCacheTree(cache, child as Ruleset);
532
+ }
533
+ }
534
+ }
535
+
536
+ function getRulesetInstructionSignature(
537
+ ruleset: Ruleset,
538
+ instruction: RecordedExtendInstruction,
539
+ cache?: TargetInfoCache,
540
+ context?: Context
541
+ ): string | undefined {
542
+ const targetInfo = getCachedTargetInfo(cache, ruleset, instruction, context);
543
+ if (!targetInfo) {
544
+ return undefined;
545
+ }
546
+
547
+ return [
548
+ targetInfo.selector.valueOf(),
549
+ targetInfo.parent?.valueOf() ?? '',
550
+ targetInfo.usingOwnSelector ? 'own' : 'full'
551
+ ].join('\u0000');
552
+ }
553
+
554
+ function isNodeInsideRules(node: Node, rules: Rules): boolean {
555
+ let current: Node | undefined = node;
556
+ while (current) {
557
+ if (current === rules) {
558
+ return true;
559
+ }
560
+ current = current.parent;
561
+ }
562
+ return false;
563
+ }
564
+
565
+ function getRulesetExtendTarget(
566
+ ruleset: Ruleset,
567
+ find: Selector,
568
+ partial: boolean,
569
+ context?: Context
570
+ ): { selector: Selector; parent?: Selector; usingOwnSelector: boolean } | undefined {
571
+ const selector = ruleset.getEffectiveSelector(false, context);
572
+ if (!selector || isNode(selector, N.Nil)) {
573
+ return undefined;
574
+ }
575
+
576
+ const ownSelector = ruleset.getOwnSelector(context);
577
+ if (hasSourceExtendWrapperParent(ruleset)) {
578
+ return {
579
+ selector,
580
+ usingOwnSelector: false
581
+ };
582
+ }
583
+ // Bare `&` rulesets are pure mirrors of their parent selector and are updated
584
+ // by refreshNestedRulesetSelectors when the parent is extended. Skip direct
585
+ // extend processing so selectorBeforeExtend is not incorrectly set on them.
586
+ if (ownSelector && !isNode(ownSelector, N.Nil) && isBareAmpersandOwnSelector(ownSelector)) {
587
+ return undefined;
588
+ }
589
+ const parentRs = getParentRuleset(ruleset, context);
590
+ const parentSelectorBeforeExtend = parentRs
591
+ ? (context ? parentRs.get('selectorBeforeExtend', context) : parentRs.getSelectorBeforeExtend())
592
+ : undefined;
593
+ const activeParentSelector = parentRs?.getEffectiveSelector(false, context);
594
+ const parentSelector = (
595
+ !partial
596
+ && parentSelectorBeforeExtend
597
+ && !isNode(parentSelectorBeforeExtend, N.Nil)
598
+ ? parentSelectorBeforeExtend
599
+ : activeParentSelector
600
+ );
601
+ if (
602
+ ownSelector
603
+ && !isNode(ownSelector, N.Nil)
604
+ && ownSelector.valueOf() !== selector.valueOf()
605
+ && parentSelector
606
+ && !isNode(parentSelector, N.Nil)
607
+ ) {
608
+ const ownMatch = selectorMatch(find, ownSelector, parentSelector, context);
609
+ const rawOwnMatch = partial
610
+ ? selectorMatch(find, ownSelector, undefined, context)
611
+ : undefined;
612
+ const shouldUseOwnSelector = partial
613
+ ? (
614
+ ownMatch.fullMatch
615
+ || ownMatch.partialMatch
616
+ || Boolean(rawOwnMatch?.fullMatch)
617
+ || Boolean(rawOwnMatch?.partialMatch)
618
+ )
619
+ : (
620
+ ownMatch.fullMatch
621
+ && ownMatch.crossesAmpersand
622
+ );
623
+
624
+ if (shouldUseOwnSelector) {
625
+ return {
626
+ selector: ownSelector,
627
+ parent: parentSelector,
628
+ usingOwnSelector: true
629
+ };
630
+ }
631
+
632
+ if (
633
+ !partial
634
+ && activeParentSelector
635
+ && !isNode(activeParentSelector, N.Nil)
636
+ && activeParentSelector.valueOf() !== parentSelector.valueOf()
637
+ ) {
638
+ const activeOwnMatch = selectorMatch(find, ownSelector, activeParentSelector, context);
639
+ if (activeOwnMatch.fullMatch && activeOwnMatch.crossesAmpersand) {
640
+ return {
641
+ selector: ownSelector,
642
+ parent: activeParentSelector,
643
+ usingOwnSelector: true
644
+ };
645
+ }
646
+ }
647
+
648
+ if (!partial && selectorHasAuthoredAmpersand(ownSelector as Selector)) {
649
+ const composedMatch = selectorMatch(find, selector, undefined, context);
650
+ if (composedMatch.fullMatch) {
651
+ return {
652
+ selector,
653
+ usingOwnSelector: false
654
+ };
655
+ }
656
+ }
657
+
658
+ // Target doesn't match ownSelector (with parent context). Don't fall
659
+ // through to the full composed selector — any match there would be in
660
+ // the parent-prefix portion, which is handled when the parent ruleset
661
+ // itself is extended + refreshNestedRulesetSelectors propagates changes.
662
+ return undefined;
663
+ }
664
+
665
+ return {
666
+ selector,
667
+ usingOwnSelector: false
668
+ };
669
+ }
670
+
671
+ function markExtendedSelector(selector: Selector, context?: Context): void {
672
+ if (context) {
673
+ selector._addFlag(F_EXTENDED, context);
674
+ selector._addFlag(F_VISIBLE, context);
675
+ } else {
676
+ selector.addFlag(F_EXTENDED);
677
+ selector.addFlag(F_VISIBLE);
678
+ }
679
+ if (isNode(selector, N.SelectorList)) {
680
+ for (const item of (selector as SelectorList).get('value')) {
681
+ if (context) {
682
+ (item as Selector)._addFlag(F_EXTENDED, context);
683
+ (item as Selector)._addFlag(F_VISIBLE, context);
684
+ } else {
685
+ (item as Selector).addFlag(F_EXTENDED);
686
+ (item as Selector).addFlag(F_VISIBLE);
687
+ }
688
+ }
689
+ }
690
+ }
691
+
692
+ function activateExtendedRuleset(ruleset: Ruleset, selector: Selector, context?: Context): void {
693
+ const rulesetFlagTarget = ruleset;
694
+ if (context) {
695
+ rulesetFlagTarget._addFlag(F_EXTENDED, context);
696
+ rulesetFlagTarget._addFlag(F_VISIBLE, context);
697
+ } else {
698
+ rulesetFlagTarget.addFlag(F_EXTENDED);
699
+ rulesetFlagTarget.addFlag(F_VISIBLE);
700
+ }
701
+ markExtendedSelector(selector, context);
702
+ }
703
+
704
+ function selectorHasTopLevelValue(selector: Selector | Nil | undefined, value: string): boolean {
705
+ if (!selector || isNode(selector, N.Nil)) {
706
+ return false;
707
+ }
708
+ if (isNode(selector, N.SelectorList)) {
709
+ return ((selector as SelectorList).get('value') as readonly Selector[]).some(item => item.valueOf() === value);
710
+ }
711
+ return selector.valueOf() === value;
712
+ }
713
+
714
+ function getExactOwnSelectorFallbackTarget(
715
+ ruleset: Ruleset,
716
+ instruction: RecordedExtendInstruction,
717
+ currentTargetInfo: { selector: Selector; parent?: Selector; usingOwnSelector: boolean } | undefined,
718
+ context?: Context
719
+ ): { selector: Selector; parent?: Selector; usingOwnSelector: boolean } | undefined {
720
+ if (instruction.partial || currentTargetInfo?.usingOwnSelector) {
721
+ return undefined;
722
+ }
723
+
724
+ const ownSelector = ruleset.getOwnSelector(context);
725
+ if (!ownSelector || isNode(ownSelector, N.Nil)) {
726
+ return undefined;
727
+ }
728
+
729
+ const parentRuleset = getParentRuleset(ruleset, context);
730
+ const parentOwnSelector = parentRuleset?.getOwnSelector(context);
731
+ if (
732
+ parentOwnSelector
733
+ && !isNode(parentOwnSelector, N.Nil)
734
+ && isNode(parentOwnSelector, N.SelectorList)
735
+ ) {
736
+ return undefined;
737
+ }
738
+ const parentSelectorBeforeExtend = parentRuleset
739
+ ? (context ? parentRuleset.get('selectorBeforeExtend', context) : parentRuleset.getSelectorBeforeExtend())
740
+ : undefined;
741
+ const activeParentSelector = parentRuleset?.getEffectiveSelector(false, context);
742
+ const parentSelector = (
743
+ parentSelectorBeforeExtend
744
+ && !isNode(parentSelectorBeforeExtend, N.Nil)
745
+ ? parentSelectorBeforeExtend
746
+ : activeParentSelector
747
+ );
748
+ if (!parentSelector || isNode(parentSelector, N.Nil)) {
749
+ return undefined;
750
+ }
751
+
752
+ if (selectorHasTopLevelValue(activeParentSelector, instruction.extendWith.valueOf())) {
753
+ return undefined;
754
+ }
755
+
756
+ const ownMatch = selectorMatch(instruction.target, ownSelector, parentSelector, context);
757
+ if (!ownMatch.partialMatch || ownMatch.crossesAmpersand) {
758
+ return undefined;
759
+ }
760
+
761
+ return {
762
+ selector: ownSelector,
763
+ parent: parentSelector,
764
+ usingOwnSelector: true
765
+ };
766
+ }
767
+
768
+ function clearExtendedRuleset(ruleset: Ruleset, context?: Context): void {
769
+ const rulesetFlagTarget = ruleset;
770
+ if (context) {
771
+ rulesetFlagTarget._removeFlag(F_EXTENDED, context);
772
+ } else {
773
+ rulesetFlagTarget.removeFlag(F_EXTENDED);
774
+ }
775
+ if (getRulesetHoistToRoot(ruleset, context) !== undefined) {
776
+ setRulesetHoistToRoot(ruleset, undefined, context);
777
+ }
778
+ const selector = ((context ? ruleset.get('_extendedSelector', context) : ruleset.getExtendedSelector()) ?? ruleset.get('selector', context));
779
+ if (selector && !isNode(selector, N.Nil)) {
780
+ if (context) {
781
+ selector._removeFlag(F_EXTENDED, context);
782
+ } else {
783
+ selector.removeFlag(F_EXTENDED);
784
+ }
785
+ }
786
+ syncRulesetDerivedSelector(ruleset, context);
787
+ }
788
+
789
+ function getRulesetHoistToRoot(ruleset: Ruleset, _context?: Context): boolean | undefined {
790
+ return ruleset.hoistToRoot;
791
+ }
792
+
793
+ function setRulesetHoistToRoot(ruleset: Ruleset, value: boolean | undefined, _context?: Context): void {
794
+ ruleset.hoistToRoot = value;
795
+ }
796
+
797
+ function applyInstructionToRuleset(
798
+ ruleset: Ruleset,
799
+ instruction: RecordedExtendInstruction,
800
+ cache?: TargetInfoCache,
801
+ context?: Context
802
+ ): { matched: boolean; changed: boolean } {
803
+ let targetInfo = getCachedTargetInfo(cache, ruleset, instruction, context);
804
+ if (!targetInfo) {
805
+ const fallbackTargetInfo = getExactOwnSelectorFallbackTarget(ruleset, instruction, undefined, context);
806
+ if (!fallbackTargetInfo) {
807
+ return { matched: false, changed: false };
808
+ }
809
+ targetInfo = fallbackTargetInfo;
810
+ }
811
+
812
+ let targetMatch = selectorMatch(
813
+ instruction.target,
814
+ targetInfo.selector,
815
+ targetInfo.parent,
816
+ context
817
+ );
818
+ if (!targetMatch.partialMatch) {
819
+ const fallbackTargetInfo = getExactOwnSelectorFallbackTarget(ruleset, instruction, targetInfo, context);
820
+ if (!fallbackTargetInfo) {
821
+ return { matched: false, changed: false };
822
+ }
823
+ targetInfo = fallbackTargetInfo;
824
+ targetMatch = selectorMatch(
825
+ instruction.target,
826
+ targetInfo.selector,
827
+ targetInfo.parent,
828
+ context
829
+ );
830
+ if (!targetMatch.partialMatch) {
831
+ return { matched: false, changed: false };
832
+ }
833
+ }
834
+
835
+ const currentSelector = ruleset.get('selector', context);
836
+ const selectorBeforeExtend = targetInfo.usingOwnSelector
837
+ ? targetInfo.selector
838
+ : currentSelector;
839
+ if (
840
+ !(context ? ruleset.get('selectorBeforeExtend', context) : ruleset.getSelectorBeforeExtend())
841
+ && selectorBeforeExtend
842
+ && !isNode(selectorBeforeExtend, N.Nil)
843
+ ) {
844
+ ruleset.setSelectorBeforeExtend(selectorBeforeExtend.copy(true) as Selector, context!);
845
+ }
846
+
847
+ if (
848
+ isNodeInsideRules(instruction.extendNode, ruleset.enterRules(context))
849
+ && instruction.extendWith.valueOf() === targetInfo.selector.valueOf()
850
+ && targetMatch.fullMatch
851
+ ) {
852
+ activateExtendedRuleset(ruleset, targetInfo.selector, context);
853
+ return { matched: true, changed: false };
854
+ }
855
+
856
+ const extendWithVal = instruction.extendWith.valueOf();
857
+ const extendWithAlreadyTopLevel = isNode(targetInfo.selector, N.SelectorList)
858
+ ? ((targetInfo.selector as SelectorList).get('value') as readonly Selector[]).some(item => item.valueOf() === extendWithVal)
859
+ : targetInfo.selector.valueOf() === extendWithVal;
860
+ if (extendWithAlreadyTopLevel) {
861
+ activateExtendedRuleset(ruleset, targetInfo.selector, context);
862
+ return { matched: true, changed: false };
863
+ }
864
+
865
+ const before = targetInfo.selector.valueOf();
866
+ const selectorInput = targetInfo.selector.copy(true) as Selector;
867
+ const result = tryExtendSelector(
868
+ selectorInput,
869
+ instruction.target,
870
+ instruction.extendWith,
871
+ instruction.partial,
872
+ targetInfo.parent,
873
+ context
874
+ );
875
+ if (result.error) {
876
+ if (instruction.extendWith.valueOf() === targetInfo.selector.valueOf()) {
877
+ activateExtendedRuleset(ruleset, targetInfo.selector, context);
878
+ }
879
+ return { matched: true, changed: false };
880
+ }
881
+
882
+ const normalizedResult = normalizeGeneratedIsOrder(result.value);
883
+ const after = normalizedResult.valueOf();
884
+ activateExtendedRuleset(ruleset, normalizedResult, context);
885
+ if (before === after) {
886
+ return { matched: true, changed: false };
887
+ }
888
+
889
+ let shouldHoist = (
890
+ normalizedResult.hoistToRoot
891
+ || (
892
+ targetInfo.usingOwnSelector
893
+ && targetMatch.fullMatch
894
+ && targetMatch.crossesAmpersand
895
+ && normalizedResult !== targetInfo.selector
896
+ )
897
+ || (
898
+ !targetInfo.usingOwnSelector
899
+ && Boolean(ruleset.getOwnSelector() && !isNode(ruleset.getOwnSelector()!, N.Nil))
900
+ && selectorHasAuthoredAmpersand(ruleset.getOwnSelector() as Selector)
901
+ )
902
+ );
903
+
904
+ let nextSelector = normalizedResult;
905
+ if (targetInfo.usingOwnSelector) {
906
+ const nextOwnSelector = (
907
+ shouldHoist || !targetInfo.parent
908
+ )
909
+ ? normalizedResult
910
+ : localizeSelectorAgainstParent(normalizedResult, targetInfo.parent);
911
+ ruleset.setOwnSelector(nextOwnSelector, context);
912
+
913
+ if (!shouldHoist && targetInfo.parent) {
914
+ nextSelector = getImplicitSelector(nextOwnSelector, targetInfo.parent, false);
915
+ }
916
+ }
917
+ ruleset.setExtendedSelector(nextSelector, context);
918
+ if (shouldHoist) {
919
+ setRulesetHoistToRoot(ruleset, true, context);
920
+ refreshNestedRulesetSelectors(ruleset, context);
921
+ } else if (getRulesetHoistToRoot(ruleset, context) || ruleset.treeContext?.opts?.collapseNesting === true) {
922
+ refreshNestedRulesetSelectors(ruleset, context);
923
+ }
924
+ invalidateRulesetSelectorCaches(ruleset, context);
925
+ return { matched: true, changed: true };
926
+ }
927
+
928
+ function instructionCouldAffectRuleset(
929
+ ruleset: Ruleset,
930
+ instruction: RecordedExtendInstruction,
931
+ cache?: TargetInfoCache,
932
+ context?: Context
933
+ ): boolean {
934
+ const targetInfo = getCachedTargetInfo(cache, ruleset, instruction, context);
935
+ if (!targetInfo) {
936
+ return false;
937
+ }
938
+ const result = selectorMatch(instruction.target, targetInfo.selector, targetInfo.parent, context);
939
+ return result.fullMatch || result.partialMatch;
940
+ }
941
+
942
+ export function processExtends(context: Context): void {
943
+ try {
944
+ const instructions: RecordedExtendInstruction[] = context.extends.map(([target, selectorWithExtend, partial, extendRoot, extendNode, , fromReferenceScope, namespace]) => ({
945
+ target,
946
+ extendWith: selectorWithExtend,
947
+ partial,
948
+ extendRoot,
949
+ extendNode,
950
+ fromReferenceScope: fromReferenceScope === true,
951
+ namespace
952
+ }));
953
+
954
+ if (!instructions.length) {
955
+ return;
956
+ }
957
+
958
+ const instructionMatched = new Set<RecordedExtendInstruction>();
959
+ const seenRulesetInstructionStates = new WeakMap<Ruleset, Map<RecordedExtendInstruction, string>>();
960
+ const appliedRulesetInstructions = new WeakMap<Ruleset, Set<RecordedExtendInstruction>>();
961
+ const visibleRootsCache = new Map<Rules, Set<Rules>>();
962
+ const getCachedVisibleRoots = (extendRoot: Rules): Set<Rules> => {
963
+ let cached = visibleRootsCache.get(extendRoot);
964
+ if (!cached) {
965
+ cached = context.extendRoots.getVisibleRoots(extendRoot);
966
+ visibleRootsCache.set(extendRoot, cached);
967
+ }
968
+ return cached;
969
+ };
970
+
971
+ let targetInfoCache: TargetInfoCache = new WeakMap();
972
+ let changed = true;
973
+ while (changed) {
974
+ changed = false;
975
+
976
+ for (const rootRules of context.extendRoots.getAllRoots()) {
977
+ const rulesetSet = context.extendRoots.getRulesets(rootRules);
978
+ if (!rulesetSet?.size) {
979
+ continue;
980
+ }
981
+
982
+ const savedRenderKey = context.renderKey;
983
+ const savedRulesContext = context.rulesContext;
984
+ context.renderKey = rootRules.renderKey;
985
+ context.rulesContext = rootRules;
986
+
987
+ try {
988
+ const visibleInstructions = instructions.filter(instruction =>
989
+ isInstructionVisibleForRoot(context, rootRules, instruction, getCachedVisibleRoots)
990
+ );
991
+ if (!visibleInstructions.length) {
992
+ continue;
993
+ }
994
+
995
+ for (const ruleset of rulesetSet) {
996
+ let rulesetMatched = false;
997
+ for (const instruction of visibleInstructions) {
998
+ const appliedInstructions = appliedRulesetInstructions.get(ruleset);
999
+ if (appliedInstructions?.has(instruction)) {
1000
+ instructionMatched.add(instruction);
1001
+ rulesetMatched = true;
1002
+ continue;
1003
+ }
1004
+
1005
+ const signatureBefore = getRulesetInstructionSignature(ruleset, instruction, targetInfoCache, context);
1006
+ const perInstructionStates = seenRulesetInstructionStates.get(ruleset);
1007
+ if (
1008
+ signatureBefore !== undefined
1009
+ && perInstructionStates?.get(instruction) === signatureBefore
1010
+ ) {
1011
+ instructionMatched.add(instruction);
1012
+ rulesetMatched = true;
1013
+ continue;
1014
+ }
1015
+
1016
+ const outcome = applyInstructionToRuleset(ruleset, instruction, targetInfoCache, context);
1017
+ if (outcome.matched) {
1018
+ instructionMatched.add(instruction);
1019
+ rulesetMatched = true;
1020
+
1021
+ let nextStates = perInstructionStates;
1022
+ if (!nextStates) {
1023
+ nextStates = new Map<RecordedExtendInstruction, string>();
1024
+ seenRulesetInstructionStates.set(ruleset, nextStates);
1025
+ }
1026
+ nextStates.set(
1027
+ instruction,
1028
+ getRulesetInstructionSignature(ruleset, instruction, targetInfoCache, context) ?? signatureBefore ?? ''
1029
+ );
1030
+ }
1031
+ if (outcome.changed) {
1032
+ invalidateTargetInfoCacheTree(targetInfoCache, ruleset);
1033
+ targetInfoCache = new WeakMap();
1034
+ let nextAppliedInstructions = appliedInstructions;
1035
+ if (!nextAppliedInstructions) {
1036
+ nextAppliedInstructions = new Set<RecordedExtendInstruction>();
1037
+ appliedRulesetInstructions.set(ruleset, nextAppliedInstructions);
1038
+ }
1039
+ nextAppliedInstructions.add(instruction);
1040
+ changed = true;
1041
+ }
1042
+ }
1043
+
1044
+ if (!rulesetMatched) {
1045
+ clearExtendedRuleset(ruleset, context);
1046
+ }
1047
+ }
1048
+ } finally {
1049
+ context.renderKey = savedRenderKey;
1050
+ context.rulesContext = savedRulesContext;
1051
+ }
1052
+ }
1053
+ }
1054
+
1055
+ for (const instruction of instructions) {
1056
+ if (instruction.fromReferenceScope || instructionMatched.has(instruction)) {
1057
+ continue;
1058
+ }
1059
+
1060
+ const target = instruction.target.valueOf();
1061
+ const targetLocation = instruction.target.location;
1062
+ const targetLine = targetLocation.length >= 2 ? targetLocation[1] : undefined;
1063
+ const targetColumn = targetLocation.length >= 3 ? targetLocation[2] : undefined;
1064
+ const targetFile = instruction.target.treeContext?.file;
1065
+ const targetFilePath = targetFile?.fullPath;
1066
+
1067
+ const blockedProtectedRootExists = Array.from(context.extendRoots.getAllRoots()).some((root) => {
1068
+ if (!isRootWithinInstructionNamespace(context, root, instruction)) {
1069
+ return false;
1070
+ }
1071
+ if (isInstructionVisibleForRoot(context, root, instruction, getCachedVisibleRoots)) {
1072
+ return false;
1073
+ }
1074
+
1075
+ const rulesets = context.extendRoots.getRulesets(root);
1076
+ if (!rulesets?.size) {
1077
+ return false;
1078
+ }
1079
+
1080
+ for (const ruleset of rulesets) {
1081
+ if (instructionCouldAffectRuleset(ruleset, instruction, targetInfoCache, context)) {
1082
+ return true;
1083
+ }
1084
+ }
1085
+ return false;
1086
+ });
1087
+
1088
+ const diagnostic = blockedProtectedRootExists
1089
+ ? WARN.extendNotAccessible({
1090
+ ctx: targetFile ? { file: targetFile } : undefined,
1091
+ filePath: targetFilePath,
1092
+ line: targetLine,
1093
+ column: targetColumn,
1094
+ meta: { target }
1095
+ })
1096
+ : WARN.extendNotFound({
1097
+ ctx: targetFile ? { file: targetFile } : undefined,
1098
+ filePath: targetFilePath,
1099
+ line: targetLine,
1100
+ column: targetColumn,
1101
+ meta: { target }
1102
+ });
1103
+ context.warnings.push(toDiagnostic(diagnostic));
1104
+ }
1105
+ } finally {
1106
+ context.extendRoots.clearRegisteredRulesets();
1107
+ }
1108
+ }