@cplieger/deadset-ts 8.0.0-dev.2 → 8.0.0-dev.21

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 (431) hide show
  1. package/README.md +3 -1
  2. package/THIRD_PARTY_NOTICES.md +27 -0
  3. package/dist/bin/mapper-connection.js +2 -1
  4. package/dist/bin/node-host.js +24 -5
  5. package/dist/src/alias-chain.js +35 -9
  6. package/dist/src/amd.js +81 -0
  7. package/dist/src/analysis.js +274 -496
  8. package/dist/src/augmentations.js +64 -3
  9. package/dist/src/automatic-types.js +10 -29
  10. package/dist/src/bindings.js +382 -0
  11. package/dist/src/commands/held.js +499 -0
  12. package/dist/src/commands/read.js +161 -0
  13. package/dist/src/commands/shell.js +169 -0
  14. package/dist/src/commands/tools.js +1847 -0
  15. package/dist/src/component-files.js +3 -2
  16. package/dist/src/component-layer.js +4 -2
  17. package/dist/src/config.js +6 -82
  18. package/dist/src/conformance-record.js +2 -2
  19. package/dist/src/consumers.js +10 -38
  20. package/dist/src/contextual-uses.js +57 -26
  21. package/dist/src/contract/config.generated.js +561 -0
  22. package/dist/src/contract/contract.generated.js +1370 -0
  23. package/dist/src/contract/report.generated.js +866 -0
  24. package/dist/src/dependencies.js +165 -122
  25. package/dist/src/destructuring.js +1 -19
  26. package/dist/src/edges.js +38 -122
  27. package/dist/src/element-access.js +181 -168
  28. package/dist/src/entries/build-scripts.js +222 -0
  29. package/dist/src/{configuration-files.js → entries/configuration-files.js} +52 -256
  30. package/dist/src/{convention-rows.js → entries/convention-rows.js} +170 -30
  31. package/dist/src/entries/conventions.js +740 -0
  32. package/dist/src/{html-entries.js → entries/html-entries.js} +12 -42
  33. package/dist/src/{mdx-entries.js → entries/mdx-entries.js} +5 -28
  34. package/dist/src/entries/run-directories.js +77 -0
  35. package/dist/src/entries/sources.js +144 -0
  36. package/dist/src/entries/static-module.js +670 -0
  37. package/dist/src/entries/test-runners.js +650 -0
  38. package/dist/src/entries/workflow-steps.js +345 -0
  39. package/dist/src/exemptions/argument-places.js +131 -0
  40. package/dist/src/exemptions/calls.js +338 -0
  41. package/dist/src/exemptions/classes.js +13 -0
  42. package/dist/src/{decorator.js → exemptions/decorator.js} +19 -30
  43. package/dist/src/exemptions/detectors.js +48 -0
  44. package/dist/src/{enum-group.js → exemptions/enum-group.js} +9 -16
  45. package/dist/src/{erased-stores.js → exemptions/erased-stores.js} +7 -11
  46. package/dist/src/{framework-lifecycle.js → exemptions/framework-lifecycle.js} +76 -54
  47. package/dist/src/exemptions/generated-file.js +241 -0
  48. package/dist/src/{injection-container.js → exemptions/injection-container.js} +20 -26
  49. package/dist/src/exemptions/installed-globals.js +173 -0
  50. package/dist/src/{interface-satisfaction.js → exemptions/interface-satisfaction.js} +52 -121
  51. package/dist/src/exemptions/lifecycle.js +150 -0
  52. package/dist/src/{reflective-lookup.js → exemptions/reflective-lookup.js} +3 -3
  53. package/dist/src/exemptions/serialization-contract.js +1276 -0
  54. package/dist/src/exemptions/sites.js +182 -0
  55. package/dist/src/{template-field.js → exemptions/template-field.js} +13 -23
  56. package/dist/src/{value-reach.js → exemptions/value-reach.js} +14 -7
  57. package/dist/src/exposure.js +400 -0
  58. package/dist/src/extensions.js +37 -0
  59. package/dist/src/facts.js +38 -0
  60. package/dist/src/failure.js +36 -0
  61. package/dist/src/file-facts.js +3 -26
  62. package/dist/src/findings/completion.js +109 -56
  63. package/dist/src/findings/dependencies-and-module-machinery.js +4 -5
  64. package/dist/src/findings/emitters.js +27 -41
  65. package/dist/src/{implementations.js → findings/implementations.js} +3 -3
  66. package/dist/src/{in-operands.js → findings/in-operands.js} +3 -2
  67. package/dist/src/findings/interfaces.js +4 -5
  68. package/dist/src/findings/intra-function.js +16 -13
  69. package/dist/src/findings/non-code-artifacts.js +17 -12
  70. package/dist/src/findings/reads-and-writes.js +86 -27
  71. package/dist/src/findings/self-check.js +44 -30
  72. package/dist/src/findings/unused-declarations.js +29 -45
  73. package/dist/src/findings/visibility-narrowing.js +23 -31
  74. package/dist/src/findings-pass.js +13 -21
  75. package/dist/src/fs/document.js +52 -0
  76. package/dist/src/fs/manifest.js +67 -0
  77. package/dist/src/fs/tree.js +88 -0
  78. package/dist/src/git-ignore.js +39 -26
  79. package/dist/src/import-bindings.js +73 -28
  80. package/dist/src/index/sites.js +557 -0
  81. package/dist/src/index/values.js +124 -0
  82. package/dist/src/index.js +2 -2
  83. package/dist/src/indexed-access.js +523 -478
  84. package/dist/src/intra-function-parts.js +63 -43
  85. package/dist/src/inventory/commonjs.js +507 -0
  86. package/dist/src/inventory/enumerate.js +167 -0
  87. package/dist/src/inventory/syntax.js +236 -0
  88. package/dist/src/inventory.js +323 -724
  89. package/dist/src/javascript-file.js +48 -0
  90. package/dist/src/json-document.js +198 -67
  91. package/dist/src/keyof-comparisons.js +126 -107
  92. package/dist/src/kinds.js +3 -366
  93. package/dist/src/{components.js → liveness/components.js} +2 -3
  94. package/dist/src/{graph.js → liveness/graph.js} +52 -28
  95. package/dist/src/liveness/matrix.js +99 -0
  96. package/dist/src/liveness/sweep.js +558 -0
  97. package/dist/src/load/classify.js +289 -0
  98. package/dist/src/load/diagnostics.js +87 -0
  99. package/dist/src/load/discover.js +285 -0
  100. package/dist/src/{emit-map.js → load/emit-map.js} +1 -1
  101. package/dist/src/load/expected-module.js +136 -0
  102. package/dist/src/load/load.js +27 -0
  103. package/dist/src/load/module-lookup.js +37 -0
  104. package/dist/src/load/package-scope.js +56 -0
  105. package/dist/src/load/plan.js +313 -0
  106. package/dist/src/load/specifiers.js +113 -0
  107. package/dist/src/load/synthesize.js +152 -0
  108. package/dist/src/load/test-globals.js +207 -0
  109. package/dist/src/load/test-joins.js +82 -0
  110. package/dist/src/{workspace-manifests.js → load/workspace-manifests.js} +4 -4
  111. package/dist/src/{workspace-programs.js → load/workspace-programs.js} +89 -66
  112. package/dist/src/{workspace-resolution.js → load/workspace-resolution.js} +24 -66
  113. package/dist/src/{workspace-run.js → load/workspace-run.js} +7 -7
  114. package/dist/src/{workspace.js → load/workspace.js} +62 -124
  115. package/dist/src/module-declarations.js +70 -85
  116. package/dist/src/overrides.js +134 -112
  117. package/dist/src/partial.js +2 -1
  118. package/dist/src/paths.js +82 -16
  119. package/dist/src/platform-calls.js +78 -0
  120. package/dist/src/platform-symbols.js +134 -0
  121. package/dist/src/position.js +43 -1
  122. package/dist/src/print.js +11 -79
  123. package/dist/src/product.js +13 -0
  124. package/dist/src/query.js +95 -0
  125. package/dist/src/ref.js +12 -20
  126. package/dist/src/references/read-rule.js +1 -0
  127. package/dist/src/references/read-rules.js +48 -0
  128. package/dist/src/references/sink.js +237 -0
  129. package/dist/src/references/sources.js +450 -0
  130. package/dist/src/references.js +117 -1074
  131. package/dist/src/report-schema.js +51 -0
  132. package/dist/src/report.js +57 -41
  133. package/dist/src/reporters/annotations.js +15 -8
  134. package/dist/src/reporters/sarif.js +16 -10
  135. package/dist/src/reporters/template.js +4 -19
  136. package/dist/src/resolve.js +246 -730
  137. package/dist/src/{configured-declarations.js → roots/configured-declarations.js} +22 -24
  138. package/dist/src/{entry-point-gaps.js → roots/entry-point-gaps.js} +6 -15
  139. package/dist/src/roots/manifest.js +216 -0
  140. package/dist/src/roots/published-reach.js +412 -0
  141. package/dist/src/roots/root-set.js +487 -0
  142. package/dist/src/roots/unseen-loads.js +236 -0
  143. package/dist/src/run.js +66 -77
  144. package/dist/src/schema.js +320 -343
  145. package/dist/src/scope.js +38 -115
  146. package/dist/src/session.js +37 -29
  147. package/dist/src/source-files.js +6 -10
  148. package/dist/src/stores.js +4 -2
  149. package/dist/src/suppress-file.js +25 -28
  150. package/dist/src/suppress-inline.js +36 -83
  151. package/dist/src/suppress.js +50 -71
  152. package/dist/src/symbol-keys.js +92 -88
  153. package/dist/src/tests/file-class.js +76 -0
  154. package/dist/src/{outside-tests.js → tests/outside.js} +7 -7
  155. package/dist/src/{test-support.js → tests/support.js} +5 -12
  156. package/dist/src/text/compare.js +26 -0
  157. package/dist/src/text/glob.js +194 -0
  158. package/dist/src/text/named-files.js +298 -0
  159. package/dist/src/text/yaml.js +684 -0
  160. package/dist/src/type-errors.js +11 -232
  161. package/dist/src/type-parameter-reads.js +178 -139
  162. package/dist/src/unimplemented-callees.js +262 -242
  163. package/dist/src/unwrap.js +23 -0
  164. package/dist/src/usage.js +10 -0
  165. package/dist/src/vendor/unbash/ansi-c.js +132 -0
  166. package/dist/src/vendor/unbash/arithmetic-parts.js +37 -0
  167. package/dist/src/vendor/unbash/arithmetic.js +591 -0
  168. package/dist/src/vendor/unbash/assignment.js +131 -0
  169. package/dist/src/vendor/unbash/chars.js +48 -0
  170. package/dist/src/vendor/unbash/command.js +41 -0
  171. package/dist/src/vendor/unbash/expansion.js +80 -0
  172. package/dist/src/vendor/unbash/glob.js +268 -0
  173. package/dist/src/vendor/unbash/heredoc.js +27 -0
  174. package/dist/src/vendor/unbash/internal-types.js +1 -0
  175. package/dist/src/vendor/unbash/lexer.js +4274 -0
  176. package/dist/src/vendor/unbash/limits.js +3 -0
  177. package/dist/src/vendor/unbash/parser.js +1366 -0
  178. package/dist/src/vendor/unbash/parts.js +57 -0
  179. package/dist/src/vendor/unbash/substitution-context.js +8 -0
  180. package/dist/src/vendor/unbash/traversal.js +212 -0
  181. package/dist/src/vendor/unbash/types.js +1 -0
  182. package/dist/src/vendor/unbash/word-value.js +61 -0
  183. package/dist/src/vendor/unbash/word.js +40 -0
  184. package/dist/src/verbs/analyze.js +194 -127
  185. package/dist/src/verbs/describe.js +13 -18
  186. package/dist/src/verbs/explain.js +85 -139
  187. package/dist/src/verbs/print-config.js +2 -1
  188. package/dist/src/verbs/print-projects.js +6 -4
  189. package/dist/src/verbs/print-retained.js +30 -6
  190. package/dist/src/verbs/print-roots.js +4 -2
  191. package/dist/src/verbs/verb.js +1 -5
  192. package/dist/src/verbs/version.js +14 -3
  193. package/jsr.json +2 -1
  194. package/package.json +14 -8
  195. package/src/alias-chain.ts +40 -11
  196. package/src/amd.ts +130 -0
  197. package/src/analysis.ts +426 -733
  198. package/src/augmentations.ts +93 -4
  199. package/src/automatic-types.ts +12 -30
  200. package/src/bindings.ts +460 -0
  201. package/src/commands/held.ts +632 -0
  202. package/src/commands/read.ts +242 -0
  203. package/src/commands/shell.ts +228 -0
  204. package/src/commands/tools.ts +2382 -0
  205. package/src/component-files.ts +4 -2
  206. package/src/component-layer.ts +4 -2
  207. package/src/config.ts +31 -302
  208. package/src/conformance-record.ts +2 -2
  209. package/src/consumers.ts +16 -66
  210. package/src/contextual-uses.ts +66 -34
  211. package/src/contract/config.generated.ts +821 -0
  212. package/src/contract/contract.generated.ts +1453 -0
  213. package/src/contract/report.generated.ts +1241 -0
  214. package/src/dependencies.ts +223 -128
  215. package/src/destructuring.ts +1 -31
  216. package/src/edges.ts +41 -140
  217. package/src/element-access.ts +190 -187
  218. package/src/entries/build-scripts.ts +292 -0
  219. package/src/{configuration-files.ts → entries/configuration-files.ts} +68 -278
  220. package/src/{convention-rows.ts → entries/convention-rows.ts} +227 -31
  221. package/src/{conventions.ts → entries/conventions.ts} +367 -583
  222. package/src/{html-entries.ts → entries/html-entries.ts} +22 -48
  223. package/src/{mdx-entries.ts → entries/mdx-entries.ts} +7 -30
  224. package/src/entries/run-directories.ts +108 -0
  225. package/src/entries/sources.ts +266 -0
  226. package/src/entries/static-module.ts +858 -0
  227. package/src/entries/test-runners.ts +835 -0
  228. package/src/entries/workflow-steps.ts +432 -0
  229. package/src/exemptions/argument-places.ts +198 -0
  230. package/src/exemptions/calls.ts +483 -0
  231. package/src/exemptions/classes.ts +49 -0
  232. package/src/exemptions/decorator.ts +56 -0
  233. package/src/exemptions/detectors.ts +75 -0
  234. package/src/{enum-group.ts → exemptions/enum-group.ts} +10 -19
  235. package/src/{erased-stores.ts → exemptions/erased-stores.ts} +7 -14
  236. package/src/{framework-lifecycle.ts → exemptions/framework-lifecycle.ts} +85 -66
  237. package/src/exemptions/generated-file.ts +318 -0
  238. package/src/{injection-container.ts → exemptions/injection-container.ts} +29 -34
  239. package/src/exemptions/installed-globals.ts +255 -0
  240. package/src/{interface-satisfaction.ts → exemptions/interface-satisfaction.ts} +69 -160
  241. package/src/exemptions/lifecycle.ts +286 -0
  242. package/src/{reflective-lookup.ts → exemptions/reflective-lookup.ts} +5 -5
  243. package/src/exemptions/serialization-contract.ts +1729 -0
  244. package/src/exemptions/sites.ts +293 -0
  245. package/src/{template-field.ts → exemptions/template-field.ts} +22 -32
  246. package/src/{value-reach.ts → exemptions/value-reach.ts} +16 -8
  247. package/src/exposure.ts +492 -0
  248. package/src/extensions.ts +45 -0
  249. package/src/facts.ts +46 -0
  250. package/src/failure.ts +63 -0
  251. package/src/file-facts.ts +15 -25
  252. package/src/finding.ts +10 -10
  253. package/src/findings/boundary.ts +11 -0
  254. package/src/findings/completion.ts +133 -64
  255. package/src/findings/dependencies-and-module-machinery.ts +4 -7
  256. package/src/findings/emitter.ts +9 -10
  257. package/src/findings/emitters.ts +38 -52
  258. package/src/{implementations.ts → findings/implementations.ts} +4 -4
  259. package/src/{in-operands.ts → findings/in-operands.ts} +4 -3
  260. package/src/findings/interfaces.ts +7 -9
  261. package/src/findings/intra-function.ts +16 -14
  262. package/src/findings/non-code-artifacts.ts +24 -15
  263. package/src/findings/reads-and-writes.ts +118 -41
  264. package/src/findings/self-check.ts +51 -38
  265. package/src/findings/unused-declarations.ts +31 -49
  266. package/src/findings/visibility-narrowing.ts +36 -40
  267. package/src/findings-pass.ts +15 -31
  268. package/src/fs/document.ts +70 -0
  269. package/src/fs/manifest.ts +96 -0
  270. package/src/fs/tree.ts +110 -0
  271. package/src/git-ignore.ts +50 -26
  272. package/src/host.ts +12 -5
  273. package/src/import-bindings.ts +98 -29
  274. package/src/index/sites.ts +781 -0
  275. package/src/index/values.ts +170 -0
  276. package/src/index.ts +2 -2
  277. package/src/indexed-access.ts +570 -527
  278. package/src/intra-function-parts.ts +73 -44
  279. package/src/inventory/commonjs.ts +696 -0
  280. package/src/inventory/enumerate.ts +203 -0
  281. package/src/inventory/syntax.ts +311 -0
  282. package/src/inventory.ts +442 -895
  283. package/src/javascript-file.ts +54 -0
  284. package/src/json-document.ts +241 -76
  285. package/src/keyof-comparisons.ts +133 -122
  286. package/src/kinds.ts +5 -413
  287. package/src/{components.ts → liveness/components.ts} +4 -6
  288. package/src/{graph.ts → liveness/graph.ts} +100 -35
  289. package/src/liveness/matrix.ts +162 -0
  290. package/src/liveness/sweep.ts +855 -0
  291. package/src/load/classify.ts +433 -0
  292. package/src/load/diagnostics.ts +154 -0
  293. package/src/load/discover.ts +471 -0
  294. package/src/{emit-map.ts → load/emit-map.ts} +1 -1
  295. package/src/load/expected-module.ts +194 -0
  296. package/src/load/load.ts +73 -0
  297. package/src/load/module-lookup.ts +50 -0
  298. package/src/load/package-scope.ts +74 -0
  299. package/src/load/plan.ts +513 -0
  300. package/src/load/specifiers.ts +171 -0
  301. package/src/load/synthesize.ts +230 -0
  302. package/src/load/test-globals.ts +251 -0
  303. package/src/load/test-joins.ts +98 -0
  304. package/src/{workspace-manifests.ts → load/workspace-manifests.ts} +5 -5
  305. package/src/{workspace-programs.ts → load/workspace-programs.ts} +128 -85
  306. package/src/{workspace-resolution.ts → load/workspace-resolution.ts} +41 -77
  307. package/src/{workspace-run.ts → load/workspace-run.ts} +18 -16
  308. package/src/{workspace.ts → load/workspace.ts} +90 -134
  309. package/src/module-declarations.ts +74 -98
  310. package/src/overrides.ts +162 -134
  311. package/src/partial.ts +3 -2
  312. package/src/paths.ts +92 -16
  313. package/src/platform-calls.ts +119 -0
  314. package/src/platform-symbols.ts +189 -0
  315. package/src/position.ts +44 -1
  316. package/src/print.ts +12 -92
  317. package/src/product.ts +18 -0
  318. package/src/query.ts +201 -10
  319. package/src/ref.ts +12 -20
  320. package/src/references/read-rule.ts +60 -0
  321. package/src/references/read-rules.ts +55 -0
  322. package/src/references/sink.ts +314 -0
  323. package/src/references/sources.ts +632 -0
  324. package/src/references.ts +187 -1450
  325. package/src/report-schema.ts +68 -0
  326. package/src/report.ts +103 -226
  327. package/src/reporters/annotations.ts +22 -11
  328. package/src/reporters/json.ts +1 -1
  329. package/src/reporters/reporter.ts +2 -4
  330. package/src/reporters/reporters.ts +1 -1
  331. package/src/reporters/sarif.ts +29 -16
  332. package/src/reporters/template.ts +4 -20
  333. package/src/reporters/text.ts +3 -3
  334. package/src/resolve.ts +284 -1115
  335. package/src/{configured-declarations.ts → roots/configured-declarations.ts} +26 -29
  336. package/src/{entry-point-gaps.ts → roots/entry-point-gaps.ts} +7 -16
  337. package/src/roots/manifest.ts +303 -0
  338. package/src/roots/published-reach.ts +486 -0
  339. package/src/{roots.ts → roots/root-set.ts} +286 -469
  340. package/src/roots/unseen-loads.ts +345 -0
  341. package/src/run.ts +75 -91
  342. package/src/schema.ts +391 -388
  343. package/src/scope.ts +46 -138
  344. package/src/session.ts +87 -55
  345. package/src/source-files.ts +6 -11
  346. package/src/stores.ts +15 -3
  347. package/src/suppress-file.ts +24 -33
  348. package/src/suppress-inline.ts +55 -91
  349. package/src/suppress.ts +78 -79
  350. package/src/symbol-keys.ts +104 -107
  351. package/src/tests/file-class.ts +135 -0
  352. package/src/{outside-tests.ts → tests/outside.ts} +16 -10
  353. package/src/{test-support.ts → tests/support.ts} +15 -21
  354. package/src/text/compare.ts +27 -0
  355. package/src/text/glob.ts +210 -0
  356. package/src/text/named-files.ts +388 -0
  357. package/src/text/yaml.ts +747 -0
  358. package/src/type-errors.ts +18 -288
  359. package/src/type-parameter-reads.ts +187 -158
  360. package/src/unimplemented-callees.ts +297 -280
  361. package/src/unwrap.ts +34 -0
  362. package/src/usage.ts +10 -0
  363. package/src/vendor/unbash/LICENSE +15 -0
  364. package/src/vendor/unbash/VENDORED.md +16 -0
  365. package/src/vendor/unbash/ansi-c.ts +132 -0
  366. package/src/vendor/unbash/arithmetic-parts.ts +53 -0
  367. package/src/vendor/unbash/arithmetic.ts +641 -0
  368. package/src/vendor/unbash/assignment.ts +163 -0
  369. package/src/vendor/unbash/chars.ts +48 -0
  370. package/src/vendor/unbash/command.ts +47 -0
  371. package/src/vendor/unbash/expansion.ts +144 -0
  372. package/src/vendor/unbash/glob.ts +284 -0
  373. package/src/vendor/unbash/heredoc.ts +34 -0
  374. package/src/vendor/unbash/internal-types.ts +94 -0
  375. package/src/vendor/unbash/lexer.ts +4352 -0
  376. package/src/vendor/unbash/limits.ts +3 -0
  377. package/src/vendor/unbash/parser.ts +1612 -0
  378. package/src/vendor/unbash/parts.ts +96 -0
  379. package/src/vendor/unbash/substitution-context.ts +20 -0
  380. package/src/vendor/unbash/traversal.ts +182 -0
  381. package/src/vendor/unbash/types.ts +660 -0
  382. package/src/vendor/unbash/word-value.ts +64 -0
  383. package/src/vendor/unbash/word.ts +50 -0
  384. package/src/verbs/analyze.ts +255 -164
  385. package/src/verbs/describe.ts +19 -17
  386. package/src/verbs/explain.ts +93 -169
  387. package/src/verbs/print-config.ts +2 -1
  388. package/src/verbs/print-projects.ts +6 -4
  389. package/src/verbs/print-retained.ts +36 -6
  390. package/src/verbs/print-roots.ts +4 -2
  391. package/src/verbs/verb.ts +2 -8
  392. package/src/verbs/version.ts +15 -3
  393. package/dist/src/base-url.js +0 -18
  394. package/dist/src/calls.js +0 -155
  395. package/dist/src/conventions.js +0 -937
  396. package/dist/src/discover.js +0 -468
  397. package/dist/src/entry-points.js +0 -529
  398. package/dist/src/exempt-classes.js +0 -75
  399. package/dist/src/exempt.js +0 -209
  400. package/dist/src/generated-file.js +0 -95
  401. package/dist/src/glob.js +0 -65
  402. package/dist/src/manifest.js +0 -165
  403. package/dist/src/matrix.js +0 -246
  404. package/dist/src/pnpm-workspace.js +0 -120
  405. package/dist/src/roots.js +0 -672
  406. package/dist/src/serialization-contract.js +0 -611
  407. package/dist/src/setup-failure.js +0 -23
  408. package/dist/src/sweep.js +0 -224
  409. package/dist/src/test-joins.js +0 -101
  410. package/dist/src/value-flow.js +0 -74
  411. package/dist/src/version.js +0 -7
  412. package/dist/src/workflow-steps.js +0 -185
  413. package/src/base-url.ts +0 -24
  414. package/src/calls.ts +0 -225
  415. package/src/decorator.ts +0 -78
  416. package/src/discover.ts +0 -653
  417. package/src/entry-points.ts +0 -687
  418. package/src/exempt-classes.ts +0 -123
  419. package/src/exempt.ts +0 -323
  420. package/src/generated-file.ts +0 -111
  421. package/src/glob.ts +0 -67
  422. package/src/manifest.ts +0 -234
  423. package/src/matrix.ts +0 -423
  424. package/src/pnpm-workspace.ts +0 -135
  425. package/src/serialization-contract.ts +0 -849
  426. package/src/setup-failure.ts +0 -39
  427. package/src/sweep.ts +0 -347
  428. package/src/test-joins.ts +0 -120
  429. package/src/value-flow.ts +0 -104
  430. package/src/version.ts +0 -7
  431. package/src/workflow-steps.ts +0 -216
@@ -29,34 +29,55 @@ import {
29
29
  type Node,
30
30
  type SourceFile,
31
31
  } from "@typescript/native/ast";
32
+ import { amdLoadOf, amdPlatform } from "./amd.ts";
32
33
  import { automaticTypes, type AutomaticTypes } from "./automatic-types.ts";
33
34
  import {
34
- configurationFiles,
35
35
  declaredIn as declaredBeside,
36
36
  dependenciesNamed,
37
37
  moduleStrings,
38
38
  outsideChain,
39
+ type ConfigurationFiles,
39
40
  type OutsideModule,
40
41
  type ParseFile,
41
- } from "./configuration-files.ts";
42
+ } from "./entries/configuration-files.ts";
42
43
  import type { FindingPosition } from "./finding.ts";
43
44
  import type { Host } from "./host.ts";
44
- import { nodeKey, packageScope, type Inventory } from "./inventory.ts";
45
- import { scriptTokens } from "./manifest.ts";
46
- import { dirnamePath, isAbsolutePath, joinPath, relativePath, resolvePath } from "./paths.ts";
45
+ import { declarationBindings } from "./import-bindings.ts";
46
+ import { nodeKey, type Inventory } from "./inventory.ts";
47
+ import { packageScope } from "./load/package-scope.ts";
48
+ import {
49
+ ancestors,
50
+ cannotStartPackageName,
51
+ dirnamePath,
52
+ joinPath,
53
+ relativePath,
54
+ resolvePath,
55
+ } from "./paths.ts";
47
56
  import type { DependencySection, Module } from "./ref.ts";
48
57
  import { UNANSWERED } from "./query.ts";
49
58
  import type { Handle, ProjectView } from "./session.ts";
50
59
  import { sourceFilesOf, type SourceFiles } from "./source-files.ts";
51
- import { workflowTokens } from "./workflow-steps.ts";
60
+ import { manifestCommands, nodemonTexts } from "./roots/manifest.ts";
61
+ import { writtenName } from "./platform-calls.ts";
62
+ import { callsPlatform } from "./platform-symbols.ts";
63
+ import { parenthesesRemoved } from "./unwrap.ts";
64
+ import type { Workflows } from "./entries/workflow-steps.ts";
65
+ import {
66
+ pathsNamed,
67
+ preloadedPackages,
68
+ readCommands,
69
+ type CommandReading,
70
+ } from "./commands/read.ts";
71
+ import { heldNames } from "./text/named-files.ts";
72
+ import { bytewise } from "./text/compare.ts";
73
+ import { isRecord } from "./json-document.ts";
74
+ import { inInstalledPackages, INSTALLED_PACKAGES, MANIFEST, readDocument } from "./fs/manifest.ts";
52
75
 
53
- const MANIFEST = "package.json";
54
- const MODULES_DIR = "node_modules";
55
- const MODULES_SEGMENT = `/${MODULES_DIR}/`;
76
+ const MODULES_SEGMENT = `/${INSTALLED_PACKAGES}/`;
56
77
  const TYPES_SCOPE = "@types/";
57
78
 
58
- /** A script token naming a JavaScript file by a path no expansion changes. */
59
- const SCRIPT_FILE = /^[^$`{*?[~]+\.(?:js|mjs|cjs)$/u;
79
+ /** A path a command names that is a JavaScript file's. */
80
+ const SCRIPT_FILE = /\.(?:js|mjs|cjs)$/u;
60
81
 
61
82
  /** The manifest sections a dependency is declared in, each by the selector its reference spells. */
62
83
  const SECTIONS: readonly (readonly [string, DependencySection])[] = [
@@ -160,25 +181,6 @@ export interface Dependencies {
160
181
  readonly heldBy: ReadonlyMap<string, readonly string[]>;
161
182
  }
162
183
 
163
- function isRecord(value: unknown): value is Record<string, unknown> {
164
- return typeof value === "object" && value !== null && !Array.isArray(value);
165
- }
166
-
167
- /** One JSON document's decoded value, or undefined where it cannot be read or parsed. */
168
- function readJSON(host: Host, path: string): { text: string; value: unknown } | undefined {
169
- let text: string;
170
- try {
171
- text = host.readFile(path);
172
- } catch {
173
- return undefined;
174
- }
175
- try {
176
- return { text, value: JSON.parse(text) };
177
- } catch {
178
- return undefined;
179
- }
180
- }
181
-
182
184
  /**
183
185
  * The package a bare module specifier names: its first segment, or its first two
184
186
  * where it starts with a scope. A relative, absolute or scheme-prefixed specifier and
@@ -200,7 +202,7 @@ export function packageOfSpecifier(specifier: string): string | undefined {
200
202
  }
201
203
 
202
204
  /** The package an installed file belongs to, read below the last dependency directory of its path. */
203
- function packageOfPath(path: string): string | undefined {
205
+ export function packageOfPath(path: string): string | undefined {
204
206
  const at = path.lastIndexOf(MODULES_SEGMENT);
205
207
  return at < 0 ? undefined : packageOfSpecifier(path.slice(at + MODULES_SEGMENT.length));
206
208
  }
@@ -302,7 +304,7 @@ function configurationPackages(
302
304
  }
303
305
  seen.add(file);
304
306
  for (const entry of extendsOf(host, file, parse)) {
305
- if (entry.startsWith(".") || isAbsolutePath(entry)) {
307
+ if (cannotStartPackageName(entry)) {
306
308
  const local = resolvePath(dirnamePath(file), entry);
307
309
  pending.push(local.endsWith(".json") ? local : `${local}.json`);
308
310
  } else {
@@ -332,34 +334,18 @@ function importOf(specifier: Node): Node | undefined {
332
334
 
333
335
  /** The local names one import declaration binds. */
334
336
  function bindingsOf(node: Node | undefined): readonly Texted[] {
335
- if (node === undefined) {
336
- return [];
337
- }
338
- if (isImportEqualsDeclaration(node)) {
339
- return [node.name];
340
- }
341
- if (!isImportDeclaration(node) || node.importClause === undefined) {
342
- return [];
343
- }
344
- const clause = node.importClause;
345
- const names: Texted[] = clause.name === undefined ? [] : [clause.name];
346
- const bindings = clause.namedBindings;
347
- if (bindings !== undefined) {
348
- if (bindings.kind === SyntaxKind.NamespaceImport) {
349
- names.push(bindings.name);
350
- } else {
351
- names.push(...bindings.elements.map((element) => element.name));
352
- }
353
- }
354
- return names;
337
+ return node !== undefined && (isImportDeclaration(node) || isImportEqualsDeclaration(node))
338
+ ? declarationBindings(node).map((binding) => binding.name)
339
+ : [];
355
340
  }
356
341
 
357
342
  /**
358
343
  * Every package one project needs, and which declaration each use is written in.
359
344
  * One local walk and one batched resolution per file: a use of an import binding is
360
345
  * an identifier resolving to the binding's own symbol, so a local declaration that
361
- * shadows the name is not one. A string of a configuration file uses each dependency
362
- * the manifest beside the file declares that it spells.
346
+ * shadows the name is not one. A string of a configuration file, as the entry sources
347
+ * read them in `configuration`, uses each dependency the manifest beside the file
348
+ * declares that it spells.
363
349
  */
364
350
  export function projectNeeds<Brand>(
365
351
  project: ProjectView<Brand>,
@@ -367,6 +353,8 @@ export function projectNeeds<Brand>(
367
353
  host: Host,
368
354
  targetRoot: string,
369
355
  parse: ParseFile,
356
+ configuration: ConfigurationFiles,
357
+ workflows: Workflows,
370
358
  ): ProjectNeeds {
371
359
  const programPackages = new Set<string>();
372
360
  for (const name of project.program.getSourceFileNames()) {
@@ -420,7 +408,6 @@ export function projectNeeds<Brand>(
420
408
  return names;
421
409
  };
422
410
  const files = sourceFilesOf(project, targetRoot);
423
- const configuration = configurationFiles(host, targetRoot, files, parse);
424
411
  for (const { file, manifestDir } of configuration.modules) {
425
412
  const names = declaredAt(joinPath(manifestDir, MANIFEST));
426
413
  for (const { node, text } of moduleStrings(file)) {
@@ -429,7 +416,7 @@ export function projectNeeds<Brand>(
429
416
  }
430
417
  for (const { strings, manifestDirs } of configuration.documents) {
431
418
  for (const manifestDir of manifestDirs) {
432
- const names = declaredAt(joinPath(manifestDir, "package.json"));
419
+ const names = declaredAt(joinPath(manifestDir, MANIFEST));
433
420
  for (const text of strings) {
434
421
  use([PROJECT_OWNER], dependenciesNamed(text, names), joinPath(manifestDir, MANIFEST));
435
422
  }
@@ -440,11 +427,11 @@ export function projectNeeds<Brand>(
440
427
  targetRoot,
441
428
  files,
442
429
  parse,
443
- scriptRunFiles(host, targetRoot, files),
430
+ scriptRunFiles(host, targetRoot, files, workflows),
444
431
  );
445
432
  for (const { file, manifestDirs } of [...configuration.outside, ...ranFiles]) {
446
433
  for (const manifestDir of manifestDirs) {
447
- const names = declaredAt(joinPath(manifestDir, "package.json"));
434
+ const names = declaredAt(joinPath(manifestDir, MANIFEST));
448
435
  for (const { text } of moduleStrings(file)) {
449
436
  use([PROJECT_OWNER], dependenciesNamed(text, names), joinPath(manifestDir, MANIFEST));
450
437
  }
@@ -454,44 +441,46 @@ export function projectNeeds<Brand>(
454
441
  }
455
442
 
456
443
  /**
457
- * The JavaScript files no program holds that a script of a manifest at or above one of the
458
- * project's files runs, each with the directory of that manifest, and those a workflow
459
- * step or git hook runs, with the target root's: a token naming such a file below the
460
- * target root and in no `node_modules`, read against the manifest's directory.
444
+ * The JavaScript files no program holds that a command string of a manifest at or above one of
445
+ * the project's files runs or names, each with the directory of that manifest, and those a
446
+ * workflow step or git hook names, with the target root's: a path `pathsNamed` reads, below the
447
+ * target root and in no `node_modules`.
461
448
  */
462
449
  function scriptRunFiles(
463
450
  host: Host,
464
451
  targetRoot: string,
465
452
  files: SourceFiles,
453
+ workflows: Workflows,
466
454
  ): readonly { readonly path: string; readonly manifestDir: string }[] {
467
455
  const root = resolvePath(host.workingDirectory(), targetRoot);
468
456
  const dirs = new Set<string>([root]);
469
457
  for (const name of files.byName.keys()) {
470
- for (let dir = dirnamePath(name); !dirs.has(dir); dir = dirnamePath(dir)) {
471
- if (relativePath(root, dir) === undefined) {
458
+ for (const dir of ancestors(dirnamePath(name), root)) {
459
+ if (dirs.has(dir)) {
472
460
  break;
473
461
  }
474
462
  dirs.add(dir);
475
463
  }
476
464
  }
477
- const tokens = new Map<string, ReadonlySet<string>>([
478
- [root, new Set(workflowTokens(host, root))],
465
+ const named = new Map<string, readonly string[]>([
466
+ [root, workflows.readings.flatMap(pathsNamed).map((one) => one.path)],
479
467
  ]);
480
468
  for (const dir of dirs) {
481
- const read = readJSON(host, joinPath(dir, MANIFEST));
469
+ const read = readDocument(host, joinPath(dir, MANIFEST));
482
470
  if (read !== undefined && isRecord(read.value)) {
483
- const own = scriptTokensOf(read.value);
484
- tokens.set(dir, dir === root ? new Set([...own, ...(tokens.get(root) ?? [])]) : own);
471
+ const own = manifestReadings(host, dir, read.value)
472
+ .flatMap(pathsNamed)
473
+ .map((one) => one.path);
474
+ named.set(dir, [...own, ...(named.get(dir) ?? [])]);
485
475
  }
486
476
  }
487
477
  const found: { path: string; manifestDir: string }[] = [];
488
- for (const [manifestDir, held] of tokens) {
489
- for (const token of held) {
490
- const path = SCRIPT_FILE.test(token) ? resolvePath(manifestDir, token) : undefined;
491
- const below = path === undefined ? undefined : relativePath(root, path);
478
+ for (const [manifestDir, paths] of named) {
479
+ for (const path of new Set(paths)) {
480
+ const below = SCRIPT_FILE.test(path) ? relativePath(root, path) : undefined;
492
481
  if (
493
- path !== undefined &&
494
- below?.split("/").includes(MODULES_DIR) === false &&
482
+ below !== undefined &&
483
+ !inInstalledPackages(below) &&
495
484
  !files.byName.has(path) &&
496
485
  host.kindOf(path) === "file"
497
486
  ) {
@@ -502,6 +491,54 @@ function scriptRunFiles(
502
491
  return found;
503
492
  }
504
493
 
494
+ /** What the command strings of one manifest, its scripts and nodemon's command, run. */
495
+ function manifestReadings(
496
+ host: Host,
497
+ dir: string,
498
+ manifest: Record<string, unknown>,
499
+ ): readonly CommandReading[] {
500
+ return manifestCommands(host, dir, manifest).map(({ command }) => readCommands(command, dir));
501
+ }
502
+
503
+ /** What one manifest's command strings use, held with the whole text of nodemon's configuration. */
504
+ function manifestUses(host: Host, dir: string, manifest: Record<string, unknown>): CommandUses {
505
+ const uses = usesOf(manifestReadings(host, dir, manifest));
506
+ const texts = nodemonTexts(host, dir, manifest).map(({ text }) => text);
507
+ return { ...uses, held: [uses.held, ...texts].join("\n") };
508
+ }
509
+
510
+ /** What the target root's workflow steps, git hooks and recipes use, held with their files' whole text. */
511
+ function workflowUses(workflows: Workflows): CommandUses {
512
+ const uses = usesOf(workflows.readings);
513
+ return { ...uses, held: [uses.held, ...workflows.texts].join("\n") };
514
+ }
515
+
516
+ /** What some command strings say about the packages they use. */
517
+ interface CommandUses {
518
+ /** Every static word of their commands, which uses a dependency whose command it is. */
519
+ readonly words: ReadonlySet<string>;
520
+ /** The package each module a read command preloads by name is in. */
521
+ readonly preloads: ReadonlySet<string>;
522
+ /** The whole text of every string, which the dependency rule reads: each package or command name in it is a use. */
523
+ readonly held: string;
524
+ }
525
+
526
+ function usesOf(readings: readonly CommandReading[]): CommandUses {
527
+ return {
528
+ words: new Set(
529
+ readings.flatMap((one) =>
530
+ one.commands.flatMap((command) => command.words.flatMap((word) => word ?? [])),
531
+ ),
532
+ ),
533
+ preloads: new Set(
534
+ readings
535
+ .flatMap((one) => one.runs.flatMap(preloadedPackages))
536
+ .flatMap((specifier) => packageOfSpecifier(specifier) ?? []),
537
+ ),
538
+ held: readings.map((one) => one.held).join("\n"),
539
+ };
540
+ }
541
+
505
542
  /** The declarations of the inventory a use written at one node belongs to. */
506
543
  function ownersOf(file: SourceFile, held: Inventory, node: Node): readonly string[] {
507
544
  const parent = node.parent as Node | undefined;
@@ -599,8 +636,17 @@ function fileNeeds<Brand>(
599
636
  if (names.size > 0 || automatic.globals.size > 0) {
600
637
  visit(file);
601
638
  }
639
+ const loads = runtimeLoads(file);
640
+ const callees = loads.flatMap((load) => load.callees);
641
+ const amdCallees = new Set(loads.flatMap((load) => (load.amd ? load.callees : [])));
602
642
 
603
- const asked = [...specifiers, ...bindings.map(({ node }) => node), ...candidates, ...globals];
643
+ const asked = [
644
+ ...specifiers,
645
+ ...bindings.map(({ node }) => node),
646
+ ...candidates,
647
+ ...globals,
648
+ ...callees,
649
+ ];
604
650
  const handles: Handle<Brand>[] = asked.map((node) => project.handle(node));
605
651
  const resolved = project.symbolsAt(handles);
606
652
 
@@ -676,35 +722,96 @@ function fileNeeds<Brand>(
676
722
  for (const reference of file.typeReferenceDirectives) {
677
723
  use(ownersOf(file, held, file), typePackages(reference.fileName, programPackages));
678
724
  }
679
- for (const specifier of resolvedSpecifiers(file)) {
680
- const named = packageOfSpecifier(specifier.text);
681
- if (named !== undefined) {
725
+ // A callee the checker leaves unanswered may be a require, so its call holds the
726
+ // dependency it names by live code, as program.33 holds one.
727
+ const calleesAt = unresolvedAt + globals.length;
728
+ const decided = new Map<string, boolean>();
729
+ const requires = new Set<Identifier>();
730
+ const unansweredCallees = new Set<Identifier>();
731
+ callees.forEach((callee, index) => {
732
+ const symbol = resolved[calleesAt + index];
733
+ if (symbol === UNANSWERED) {
734
+ unansweredCallees.add(callee);
735
+ return;
736
+ }
737
+ // The decision reads the callee's symbol, its written name and its platform name, and nothing else.
738
+ const platform = amdCallees.has(callee) ? amdPlatform(callee) : "require";
739
+ const key =
740
+ symbol === undefined ? undefined : `${symbol.id}\u0000${platform}\u0000${callee.text}`;
741
+ const answer =
742
+ (key === undefined ? undefined : decided.get(key)) ??
743
+ callsPlatform(project, platform, callee, symbol);
744
+ if (key !== undefined) {
745
+ decided.set(key, answer);
746
+ }
747
+ if (answer) {
748
+ requires.add(callee);
749
+ }
750
+ });
751
+ for (const { specifier, named, callees: through } of loads) {
752
+ if (through.length === 0 || through.some((one) => requires.has(one))) {
682
753
  use(ownersOf(file, held, specifier), [named]);
754
+ } else if (through.some((one) => unansweredCallees.has(one))) {
755
+ use([PROJECT_OWNER], [named]);
683
756
  }
684
757
  }
685
758
  return resolved.slice(0, specifiers.length).includes(UNANSWERED);
686
759
  }
687
760
 
688
761
  /**
689
- * The literal specifiers one file asks the runtime to resolve, through `import.meta.resolve`
690
- * or `require.resolve`, each of which needs the package it names installed.
762
+ * A call of one file that may load or resolve a package at run time: the literal specifier
763
+ * naming it, and the names a `require` would be written with, of which one has to be a
764
+ * `require` for the call to need the package; none for a use where it stands.
691
765
  */
692
- function resolvedSpecifiers(file: SourceFile): readonly Texted[] {
693
- const found: Texted[] = [];
694
- if (!file.text.includes(".resolve(")) {
695
- return found;
696
- }
766
+ interface RuntimeLoad {
767
+ readonly specifier: Texted;
768
+ readonly named: string;
769
+ readonly callees: readonly Identifier[];
770
+ /** Whether the specifier is an id of an AMD call's dependency list, its callee AMD's `define` or `require`. */
771
+ readonly amd: boolean;
772
+ }
773
+
774
+ /**
775
+ * The calls one file may load or resolve a package with at run time, each of whose first
776
+ * argument is literal text naming a package: a `require()` call, which the compiler lists among
777
+ * a file's imports only in a JavaScript file and only through the bare name; a `.resolve` of
778
+ * another name, which needs it where that name is a `require`; and `import.meta.resolve` or
779
+ * a `.resolve` of the name `require`, whatever it names, a use where it stands; and each id of
780
+ * an AMD dependency list (references-ts.37), which needs it where the call is AMD's.
781
+ */
782
+ function runtimeLoads(file: SourceFile): readonly RuntimeLoad[] {
783
+ const found: RuntimeLoad[] = [];
697
784
  const visit = (node: Node): void => {
698
- if (isCallExpression(node) && isPropertyAccessExpression(node.expression)) {
699
- const callee = node.expression;
785
+ const amd = amdLoadOf(node);
786
+ if (amd !== undefined) {
787
+ for (const { id } of amd.ids) {
788
+ const named = packageOfSpecifier(id.text);
789
+ if (named !== undefined) {
790
+ found.push({ specifier: id, named, callees: [amd.callee], amd: true });
791
+ }
792
+ }
793
+ } else if (isCallExpression(node)) {
700
794
  const [argument] = node.arguments;
701
- const receiver = callee.expression;
702
- const resolving =
703
- callee.name.text === "resolve" &&
704
- ((isMetaProperty(receiver) && receiver.name.text === "meta") ||
705
- (isIdentifier(receiver) && receiver.text === "require"));
706
- if (resolving && argument !== undefined && isLiteralText(argument)) {
707
- found.push(argument);
795
+ if (argument !== undefined && isLiteralText(argument)) {
796
+ const named = packageOfSpecifier(argument.text);
797
+ const callee = parenthesesRemoved(node.expression);
798
+ const receiver =
799
+ isPropertyAccessExpression(callee) && callee.name.text === "resolve"
800
+ ? parenthesesRemoved(callee.expression)
801
+ : undefined;
802
+ const stands =
803
+ receiver !== undefined &&
804
+ ((isMetaProperty(receiver) && receiver.name.text === "meta") ||
805
+ (isIdentifier(receiver) && receiver.text === "require"));
806
+ const callees = stands
807
+ ? []
808
+ : [
809
+ writtenName(callee),
810
+ receiver === undefined ? undefined : writtenName(receiver),
811
+ ].filter((one) => one !== undefined);
812
+ if (named !== undefined && (stands || callees.length > 0)) {
813
+ found.push({ specifier: argument, named, callees, amd: false });
814
+ }
708
815
  }
709
816
  }
710
817
  node.forEachChild(visit);
@@ -797,8 +904,8 @@ function lineAndColumn(text: string, offset: number): { line: number; column: nu
797
904
 
798
905
  /** The installed copy of one dependency, read where the package manager puts it for the target. */
799
906
  function installedOf(host: Host, root: string, name: string): InstalledDependency | undefined {
800
- for (let dir = root; ; dir = dirnamePath(dir)) {
801
- const read = readJSON(host, joinPath(dir, MODULES_DIR, name, MANIFEST));
907
+ for (const dir of ancestors(root)) {
908
+ const read = readDocument(host, joinPath(dir, INSTALLED_PACKAGES, name, MANIFEST));
802
909
  if (read !== undefined && isRecord(read.value)) {
803
910
  const bin = read.value["bin"];
804
911
  const peers = read.value["peerDependencies"];
@@ -815,10 +922,8 @@ function installedOf(host: Host, root: string, name: string): InstalledDependenc
815
922
  : [],
816
923
  };
817
924
  }
818
- if (dirnamePath(dir) === dir) {
819
- return undefined;
820
- }
821
925
  }
926
+ return undefined;
822
927
  }
823
928
 
824
929
  /** Every dependency the manifest text at `path` declares, in the order the text writes them. */
@@ -857,20 +962,6 @@ export function declarationKey(dependency: DeclaredDependency): string {
857
962
  return `${dependency.position.path}\u0000${dependency.name}`;
858
963
  }
859
964
 
860
- /** Every token of every value of one manifest's `scripts` member. */
861
- function scriptTokensOf(manifest: Record<string, unknown>): ReadonlySet<string> {
862
- const scripts = manifest["scripts"];
863
- const found = new Set<string>();
864
- if (isRecord(scripts)) {
865
- for (const command of Object.values(scripts)) {
866
- if (typeof command === "string") {
867
- scriptTokens(command).forEach((token) => found.add(token));
868
- }
869
- }
870
- }
871
- return found;
872
- }
873
-
874
965
  /** Whether a path below the target root lies in the directory `dir` below it, `""` being the root. */
875
966
  function isInside(path: string, dir: string): boolean {
876
967
  return dir === "" || path.startsWith(`${dir}/`);
@@ -943,6 +1034,7 @@ function addNeededPeers(
943
1034
  export function dependenciesOf(
944
1035
  host: Host,
945
1036
  targetRoot: string,
1037
+ workflows: Workflows,
946
1038
  perProject: readonly ProjectNeeds[],
947
1039
  candidates: readonly string[],
948
1040
  members: readonly string[] = [],
@@ -965,29 +1057,38 @@ export function dependenciesOf(
965
1057
  unbuilt.add(path);
966
1058
  }
967
1059
  }
968
- const workflow = new Set(workflowTokens(host, targetRoot));
1060
+ const workflow = workflowUses(workflows);
969
1061
  const declared: DeclaredDependency[] = [];
970
1062
  const ran = new Set<string>();
971
1063
  const peers = new Map<string, readonly string[]>();
972
1064
  const uninstalledHere = new Set(nested);
973
1065
  for (const [dir, path] of manifests) {
974
- const read = readJSON(host, joinPath(dir, MANIFEST));
1066
+ const read = readDocument(host, joinPath(dir, MANIFEST));
975
1067
  if (read === undefined || !isRecord(read.value)) {
976
1068
  continue;
977
1069
  }
978
- const tokens = scriptTokensOf(read.value);
1070
+ const own = manifestUses(host, dir, read.value);
1071
+ const held = `${own.held}\n${workflow.held}`;
979
1072
  for (const dependency of declaredIn(read.text, read.value, path, scopeOf(path))) {
980
1073
  const found = installedOf(host, dir, dependency.name);
981
1074
  if (found === undefined && uninstalledHere.has(dir)) {
982
1075
  continue;
983
1076
  }
984
1077
  declared.push(dependency);
1078
+ if (
1079
+ own.preloads.has(dependency.name) ||
1080
+ workflow.preloads.has(dependency.name) ||
1081
+ heldNames(held, [dependency.name]).size > 0
1082
+ ) {
1083
+ ran.add(declarationKey(dependency));
1084
+ }
985
1085
  if (found === undefined) {
986
1086
  continue;
987
1087
  }
988
1088
  peers.set(declarationKey(dependency), found.peers);
989
- const runs = (command: string): boolean => tokens.has(command) || workflow.has(command);
990
- if (found.commands.some(runs)) {
1089
+ const runs = (command: string): boolean =>
1090
+ own.words.has(command) || workflow.words.has(command);
1091
+ if (found.commands.some(runs) || heldNames(held, found.commands).size > 0) {
991
1092
  ran.add(declarationKey(dependency));
992
1093
  }
993
1094
  }
@@ -1045,10 +1146,7 @@ export function dependenciesOf(
1045
1146
  const heldBy = new Map<string, readonly string[]>();
1046
1147
  for (const [key, held] of holders) {
1047
1148
  if (!live.has(key) && !ran.has(key)) {
1048
- heldBy.set(
1049
- key,
1050
- [...held].sort((a, b) => (a < b ? -1 : 1)),
1051
- );
1149
+ heldBy.set(key, [...held].sort(bytewise));
1052
1150
  }
1053
1151
  }
1054
1152
  const users = new Map<string, number>();
@@ -1060,10 +1158,7 @@ export function dependenciesOf(
1060
1158
  for (const id of candidates) {
1061
1159
  const sole = [...(uses.get(id) ?? [])].filter((one) => users.get(one) === 1 && names.has(one));
1062
1160
  if (sole.length > 0) {
1063
- lastUses.set(
1064
- id,
1065
- sole.sort((a, b) => (a < b ? -1 : 1)),
1066
- );
1161
+ lastUses.set(id, sole.sort(bytewise));
1067
1162
  }
1068
1163
  }
1069
1164
  const owners = new Map<string, Set<string>>();
@@ -1075,7 +1170,7 @@ export function dependenciesOf(
1075
1170
  }
1076
1171
  }
1077
1172
  const fileLastUses = new Map<string, string[]>();
1078
- for (const [one, held] of [...owners].sort(([a], [b]) => (a < b ? -1 : 1))) {
1173
+ for (const [one, held] of [...owners].sort(([a], [b]) => bytewise(a, b))) {
1079
1174
  const paths = new Set([...held].map((owner) => owner.replace(/:\d+:\d+$/u, "")));
1080
1175
  const [path] = paths;
1081
1176
  if (paths.size === 1 && path !== undefined && path !== PROJECT_OWNER) {