@hominis/fireforge 0.43.1 → 0.44.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (478) hide show
  1. package/CHANGELOG.md +153 -0
  2. package/README.md +3 -3
  3. package/dist/bin/fireforge.d.ts +4 -9
  4. package/dist/bin/fireforge.js +42 -40
  5. package/dist/build-info.json +4 -4
  6. package/dist/src/cli.js +74 -8
  7. package/dist/src/commands/bootstrap.js +17 -20
  8. package/dist/src/commands/build.js +25 -32
  9. package/dist/src/commands/config.js +34 -41
  10. package/dist/src/commands/discard.js +8 -9
  11. package/dist/src/commands/doctor-check-core.d.ts +13 -18
  12. package/dist/src/commands/doctor-check-core.js +8 -35
  13. package/dist/src/commands/doctor-external-toolchains.js +2 -2
  14. package/dist/src/commands/doctor-furnace-config-sync.d.ts +18 -0
  15. package/dist/src/commands/{doctor-furnace-manifest-sync.js → doctor-furnace-config-sync.js} +27 -26
  16. package/dist/src/commands/doctor-furnace-jar.d.ts +7 -9
  17. package/dist/src/commands/doctor-furnace-jar.js +7 -9
  18. package/dist/src/commands/doctor-furnace.js +21 -24
  19. package/dist/src/commands/doctor-orphaned-harness.d.ts +16 -20
  20. package/dist/src/commands/doctor-orphaned-harness.js +18 -44
  21. package/dist/src/commands/doctor-patch-manifest.d.ts +8 -0
  22. package/dist/src/commands/doctor-patch-manifest.js +155 -0
  23. package/dist/src/commands/doctor-post-rebase-audit.d.ts +2 -0
  24. package/dist/src/commands/{doctor/post-rebase-audit.js → doctor-post-rebase-audit.js} +3 -3
  25. package/dist/src/commands/doctor-working-tree.d.ts +10 -12
  26. package/dist/src/commands/doctor-working-tree.js +11 -18
  27. package/dist/src/commands/doctor.d.ts +1 -1
  28. package/dist/src/commands/doctor.js +64 -96
  29. package/dist/src/commands/download.js +32 -48
  30. package/dist/src/commands/export-all.js +29 -33
  31. package/dist/src/commands/export-flow.js +6 -6
  32. package/dist/src/commands/export-placement-conflicts.js +10 -9
  33. package/dist/src/commands/export-placement-gate.js +5 -5
  34. package/dist/src/commands/export-shared.d.ts +30 -33
  35. package/dist/src/commands/export-shared.js +45 -43
  36. package/dist/src/commands/export.js +21 -27
  37. package/dist/src/commands/furnace/apply.js +14 -23
  38. package/dist/src/commands/furnace/chrome-doc-remove.js +14 -21
  39. package/dist/src/commands/furnace/chrome-doc-templates.d.ts +23 -23
  40. package/dist/src/commands/furnace/chrome-doc-templates.js +23 -23
  41. package/dist/src/commands/furnace/chrome-doc-tests.js +26 -29
  42. package/dist/src/commands/furnace/chrome-doc.d.ts +16 -17
  43. package/dist/src/commands/furnace/chrome-doc.js +31 -41
  44. package/dist/src/commands/furnace/create-browser-test.d.ts +4 -4
  45. package/dist/src/commands/furnace/create-browser-test.js +8 -8
  46. package/dist/src/commands/furnace/create-mochikit.d.ts +6 -7
  47. package/dist/src/commands/furnace/create-mochikit.js +8 -9
  48. package/dist/src/commands/furnace/create-readback.d.ts +12 -13
  49. package/dist/src/commands/furnace/create-readback.js +12 -13
  50. package/dist/src/commands/furnace/create-templates.d.ts +22 -28
  51. package/dist/src/commands/furnace/create-templates.js +35 -30
  52. package/dist/src/commands/furnace/create-xpcshell.js +2 -2
  53. package/dist/src/commands/furnace/create.js +33 -23
  54. package/dist/src/commands/furnace/deploy.js +16 -24
  55. package/dist/src/commands/furnace/diff.js +15 -10
  56. package/dist/src/commands/furnace/init.js +33 -36
  57. package/dist/src/commands/furnace/override.js +23 -25
  58. package/dist/src/commands/furnace/preview.js +47 -67
  59. package/dist/src/commands/furnace/refresh.js +12 -16
  60. package/dist/src/commands/furnace/remove-mutations.d.ts +3 -6
  61. package/dist/src/commands/furnace/remove-mutations.js +14 -17
  62. package/dist/src/commands/furnace/remove-state.js +1 -1
  63. package/dist/src/commands/furnace/remove.js +33 -38
  64. package/dist/src/commands/furnace/rename-xpcshell.d.ts +8 -11
  65. package/dist/src/commands/furnace/rename-xpcshell.js +8 -11
  66. package/dist/src/commands/furnace/rename.js +59 -69
  67. package/dist/src/commands/furnace/scan.js +19 -33
  68. package/dist/src/commands/furnace/status.js +12 -9
  69. package/dist/src/commands/furnace/sync.js +9 -16
  70. package/dist/src/commands/furnace/validate.js +20 -20
  71. package/dist/src/commands/import.js +48 -37
  72. package/dist/src/commands/lint-per-patch.js +15 -10
  73. package/dist/src/commands/lint-per-run-checkjs.d.ts +13 -13
  74. package/dist/src/commands/lint-per-run-checkjs.js +13 -13
  75. package/dist/src/commands/lint-report.js +6 -7
  76. package/dist/src/commands/lint.d.ts +15 -16
  77. package/dist/src/commands/lint.js +86 -102
  78. package/dist/src/commands/package.js +6 -11
  79. package/dist/src/commands/patch/compact.js +1 -1
  80. package/dist/src/commands/patch/delete.js +24 -33
  81. package/dist/src/commands/patch/index.d.ts +5 -6
  82. package/dist/src/commands/patch/index.js +10 -12
  83. package/dist/src/commands/patch/lint-ignore.js +14 -13
  84. package/dist/src/commands/patch/move-files-create.d.ts +6 -6
  85. package/dist/src/commands/patch/move-files-create.js +8 -8
  86. package/dist/src/commands/patch/move-files-into.d.ts +6 -6
  87. package/dist/src/commands/patch/move-files-into.js +8 -8
  88. package/dist/src/commands/patch/patch-context.d.ts +2 -3
  89. package/dist/src/commands/patch/patch-context.js +2 -3
  90. package/dist/src/commands/patch/rename.d.ts +10 -11
  91. package/dist/src/commands/patch/rename.js +11 -12
  92. package/dist/src/commands/patch/reorder.js +8 -9
  93. package/dist/src/commands/patch/split-plan.js +1 -1
  94. package/dist/src/commands/patch/split.d.ts +8 -10
  95. package/dist/src/commands/patch/split.js +9 -11
  96. package/dist/src/commands/patch/staged-dependency-validate.js +8 -8
  97. package/dist/src/commands/patch/staged-dependency.js +7 -3
  98. package/dist/src/commands/patch/tier.d.ts +9 -9
  99. package/dist/src/commands/patch/tier.js +18 -15
  100. package/dist/src/commands/re-export-adjacent.js +9 -8
  101. package/dist/src/commands/re-export-bulk-scan.d.ts +9 -9
  102. package/dist/src/commands/re-export-bulk-scan.js +22 -21
  103. package/dist/src/commands/re-export-drift.js +10 -10
  104. package/dist/src/commands/re-export-files.d.ts +6 -7
  105. package/dist/src/commands/re-export-files.js +34 -44
  106. package/dist/src/commands/re-export-lint.d.ts +10 -13
  107. package/dist/src/commands/re-export-lint.js +16 -14
  108. package/dist/src/commands/re-export-options.d.ts +6 -6
  109. package/dist/src/commands/re-export-options.js +6 -6
  110. package/dist/src/commands/re-export-register.d.ts +4 -10
  111. package/dist/src/commands/re-export-register.js +5 -11
  112. package/dist/src/commands/re-export-scan.js +1 -1
  113. package/dist/src/commands/re-export-single.d.ts +3 -3
  114. package/dist/src/commands/re-export-single.js +33 -25
  115. package/dist/src/commands/re-export.js +13 -21
  116. package/dist/src/commands/rebase/abort.js +3 -3
  117. package/dist/src/commands/rebase/confirm.js +2 -1
  118. package/dist/src/commands/rebase/continue.d.ts +1 -1
  119. package/dist/src/commands/rebase/continue.js +14 -9
  120. package/dist/src/commands/rebase/index.js +11 -11
  121. package/dist/src/commands/rebase/patch-loop.d.ts +7 -1
  122. package/dist/src/commands/rebase/patch-loop.js +60 -39
  123. package/dist/src/commands/rebase/summary.js +1 -1
  124. package/dist/src/commands/register.js +5 -7
  125. package/dist/src/commands/reset.js +2 -1
  126. package/dist/src/commands/resolve.d.ts +16 -13
  127. package/dist/src/commands/resolve.js +30 -33
  128. package/dist/src/commands/run.js +33 -35
  129. package/dist/src/commands/setup-support.js +15 -19
  130. package/dist/src/commands/setup.js +13 -9
  131. package/dist/src/commands/status-check.d.ts +6 -6
  132. package/dist/src/commands/status-json.d.ts +6 -6
  133. package/dist/src/commands/status-json.js +5 -0
  134. package/dist/src/commands/status-output.d.ts +5 -5
  135. package/dist/src/commands/status-output.js +6 -6
  136. package/dist/src/commands/status-ownership.d.ts +16 -14
  137. package/dist/src/commands/status-ownership.js +16 -14
  138. package/dist/src/commands/status.js +42 -34
  139. package/dist/src/commands/test-build-phase.js +26 -13
  140. package/dist/src/commands/test-diagnose.js +44 -44
  141. package/dist/src/commands/test-register.js +1 -0
  142. package/dist/src/commands/test-run.d.ts +14 -16
  143. package/dist/src/commands/test-run.js +21 -13
  144. package/dist/src/commands/test-stale-gate.d.ts +15 -16
  145. package/dist/src/commands/test-stale-gate.js +15 -16
  146. package/dist/src/commands/test-verdict.d.ts +20 -3
  147. package/dist/src/commands/test-verdict.js +30 -0
  148. package/dist/src/commands/test.js +83 -76
  149. package/dist/src/commands/token-coverage.js +3 -4
  150. package/dist/src/commands/token.js +16 -18
  151. package/dist/src/commands/tree.js +47 -31
  152. package/dist/src/commands/typecheck.d.ts +10 -12
  153. package/dist/src/commands/typecheck.js +24 -27
  154. package/dist/src/commands/verify.js +13 -15
  155. package/dist/src/commands/watch.js +21 -23
  156. package/dist/src/commands/wire.js +52 -62
  157. package/dist/src/core/ast-utils.d.ts +8 -7
  158. package/dist/src/core/ast-utils.js +8 -7
  159. package/dist/src/core/branding.d.ts +9 -14
  160. package/dist/src/core/branding.js +7 -11
  161. package/dist/src/core/browser-wire.d.ts +1 -1
  162. package/dist/src/core/browser-wire.js +14 -19
  163. package/dist/src/core/build-audit-platform.js +25 -33
  164. package/dist/src/core/build-audit-registration.js +17 -25
  165. package/dist/src/core/build-audit-resolve.d.ts +15 -17
  166. package/dist/src/core/build-audit-resolve.js +39 -36
  167. package/dist/src/core/build-audit-transforms.js +18 -19
  168. package/dist/src/core/build-audit.js +28 -42
  169. package/dist/src/core/build-baseline-types.d.ts +29 -35
  170. package/dist/src/core/build-baseline.d.ts +5 -4
  171. package/dist/src/core/build-baseline.js +14 -14
  172. package/dist/src/core/build-overwrite-guard.d.ts +7 -14
  173. package/dist/src/core/build-overwrite-guard.js +17 -27
  174. package/dist/src/core/build-prepare.d.ts +2 -2
  175. package/dist/src/core/build-prepare.js +8 -9
  176. package/dist/src/core/config-mutate.js +20 -19
  177. package/dist/src/core/config-state.js +12 -4
  178. package/dist/src/core/config-validate.js +8 -5
  179. package/dist/src/core/config.d.ts +5 -8
  180. package/dist/src/core/config.js +7 -16
  181. package/dist/src/core/coverage-extend.d.ts +15 -13
  182. package/dist/src/core/coverage-extend.js +15 -13
  183. package/dist/src/core/destructive.d.ts +31 -9
  184. package/dist/src/core/destructive.js +29 -26
  185. package/dist/src/core/diff-hunks.js +10 -12
  186. package/dist/src/core/discard-baseline.d.ts +8 -8
  187. package/dist/src/core/discard-baseline.js +16 -15
  188. package/dist/src/core/display-state.d.ts +12 -14
  189. package/dist/src/core/display-state.js +12 -14
  190. package/dist/src/core/engine-changes.d.ts +2 -4
  191. package/dist/src/core/engine-changes.js +2 -4
  192. package/dist/src/core/engine-precondition.d.ts +28 -13
  193. package/dist/src/core/engine-precondition.js +25 -10
  194. package/dist/src/core/engine-session-lock.d.ts +47 -21
  195. package/dist/src/core/engine-session-lock.js +168 -33
  196. package/dist/src/core/export-moved-code-shape.d.ts +10 -10
  197. package/dist/src/core/export-moved-code-shape.js +10 -10
  198. package/dist/src/core/file-lock.d.ts +62 -5
  199. package/dist/src/core/file-lock.js +196 -59
  200. package/dist/src/core/firefox-cache.js +1 -3
  201. package/dist/src/core/firefox-extract.js +10 -14
  202. package/dist/src/core/firefox.d.ts +7 -5
  203. package/dist/src/core/firefox.js +4 -5
  204. package/dist/src/core/furnace-apply-dry-run.d.ts +2 -2
  205. package/dist/src/core/furnace-apply-dry-run.js +3 -2
  206. package/dist/src/core/furnace-apply-ftl.d.ts +7 -9
  207. package/dist/src/core/furnace-apply-ftl.js +16 -13
  208. package/dist/src/core/furnace-apply-helpers.d.ts +7 -7
  209. package/dist/src/core/furnace-apply-helpers.js +30 -21
  210. package/dist/src/core/furnace-apply-overwrite-warn.d.ts +8 -9
  211. package/dist/src/core/furnace-apply-overwrite-warn.js +8 -9
  212. package/dist/src/core/furnace-apply-undeploy-actions.d.ts +3 -4
  213. package/dist/src/core/furnace-apply-undeploy-actions.js +3 -4
  214. package/dist/src/core/furnace-apply.d.ts +5 -8
  215. package/dist/src/core/furnace-apply.js +19 -24
  216. package/dist/src/core/furnace-checksum-utils.d.ts +14 -0
  217. package/dist/src/core/furnace-checksum-utils.js +16 -0
  218. package/dist/src/core/furnace-config.d.ts +21 -30
  219. package/dist/src/core/furnace-config.js +32 -54
  220. package/dist/src/core/furnace-constants.d.ts +8 -0
  221. package/dist/src/core/furnace-constants.js +10 -2
  222. package/dist/src/core/furnace-css-fragments.d.ts +5 -5
  223. package/dist/src/core/furnace-css-fragments.js +5 -5
  224. package/dist/src/core/furnace-jsconfig.d.ts +11 -12
  225. package/dist/src/core/furnace-jsconfig.js +11 -12
  226. package/dist/src/core/furnace-marker.d.ts +7 -8
  227. package/dist/src/core/furnace-marker.js +7 -8
  228. package/dist/src/core/furnace-operation.d.ts +31 -0
  229. package/dist/src/core/furnace-operation.js +54 -17
  230. package/dist/src/core/furnace-precondition.d.ts +61 -0
  231. package/dist/src/core/furnace-precondition.js +67 -0
  232. package/dist/src/core/furnace-registration-remove.d.ts +5 -6
  233. package/dist/src/core/furnace-registration-remove.js +6 -7
  234. package/dist/src/core/furnace-registration-validate.d.ts +13 -0
  235. package/dist/src/core/furnace-registration-validate.js +20 -1
  236. package/dist/src/core/furnace-registration.d.ts +5 -6
  237. package/dist/src/core/furnace-registration.js +10 -12
  238. package/dist/src/core/furnace-rollback.js +7 -7
  239. package/dist/src/core/furnace-scanner.d.ts +1 -0
  240. package/dist/src/core/furnace-scanner.js +1 -2
  241. package/dist/src/core/furnace-stale-export.d.ts +10 -10
  242. package/dist/src/core/furnace-stale-export.js +10 -10
  243. package/dist/src/core/furnace-state-persist.d.ts +6 -8
  244. package/dist/src/core/furnace-state-persist.js +6 -8
  245. package/dist/src/core/furnace-validate-accessibility.d.ts +22 -0
  246. package/dist/src/core/furnace-validate-accessibility.js +310 -1
  247. package/dist/src/core/furnace-validate-compatibility.js +141 -1
  248. package/dist/src/core/furnace-validate-helpers.d.ts +5 -116
  249. package/dist/src/core/furnace-validate-helpers.js +0 -491
  250. package/dist/src/core/furnace-validate-registration.d.ts +7 -0
  251. package/dist/src/core/furnace-validate-registration.js +115 -41
  252. package/dist/src/core/furnace-validate.d.ts +16 -0
  253. package/dist/src/core/furnace-validate.js +188 -145
  254. package/dist/src/core/furnace-version-drift.d.ts +10 -11
  255. package/dist/src/core/furnace-version-drift.js +10 -11
  256. package/dist/src/core/git-base.d.ts +21 -9
  257. package/dist/src/core/git-base.js +24 -9
  258. package/dist/src/core/git-diff.d.ts +20 -9
  259. package/dist/src/core/git-diff.js +148 -63
  260. package/dist/src/core/git-file-ops.d.ts +19 -19
  261. package/dist/src/core/git-file-ops.js +19 -19
  262. package/dist/src/core/git-readonly-index.d.ts +53 -19
  263. package/dist/src/core/git-readonly-index.js +75 -31
  264. package/dist/src/core/git-status.d.ts +5 -6
  265. package/dist/src/core/git-status.js +5 -6
  266. package/dist/src/core/git.d.ts +9 -10
  267. package/dist/src/core/git.js +57 -71
  268. package/dist/src/core/license-headers.d.ts +17 -23
  269. package/dist/src/core/license-headers.js +17 -23
  270. package/dist/src/core/mach-build-artifacts.d.ts +9 -9
  271. package/dist/src/core/mach-build-artifacts.js +57 -19
  272. package/dist/src/core/mach-error-hints.js +42 -29
  273. package/dist/src/core/mach-known-noise-filter.d.ts +15 -16
  274. package/dist/src/core/mach-known-noise-filter.js +18 -20
  275. package/dist/src/core/mach-mozconfig.d.ts +14 -0
  276. package/dist/src/core/mach-mozconfig.js +30 -0
  277. package/dist/src/core/mach-resource-shim.d.ts +43 -58
  278. package/dist/src/core/mach-resource-shim.js +50 -67
  279. package/dist/src/core/mach.d.ts +37 -41
  280. package/dist/src/core/mach.js +50 -51
  281. package/dist/src/core/marionette-port.d.ts +36 -1
  282. package/dist/src/core/marionette-port.js +96 -31
  283. package/dist/src/core/marionette-preflight.d.ts +8 -12
  284. package/dist/src/core/marionette-preflight.js +86 -52
  285. package/dist/src/core/mochitest-server-port.d.ts +42 -0
  286. package/dist/src/core/mochitest-server-port.js +119 -0
  287. package/dist/src/core/module-resolution-preflight.d.ts +9 -11
  288. package/dist/src/core/module-resolution-preflight.js +9 -11
  289. package/dist/src/core/moz-manifest-helpers.d.ts +79 -0
  290. package/dist/src/core/moz-manifest-helpers.js +163 -0
  291. package/dist/src/core/{manifest-register.d.ts → moz-manifest-register.d.ts} +1 -1
  292. package/dist/src/core/{manifest-register.js → moz-manifest-register.js} +13 -28
  293. package/dist/src/core/{manifest-rules.d.ts → moz-manifest-rules.d.ts} +10 -1
  294. package/dist/src/core/{manifest-rules.js → moz-manifest-rules.js} +31 -24
  295. package/dist/src/core/{manifest-tokenizers.d.ts → moz-manifest-tokenizers.d.ts} +3 -5
  296. package/dist/src/core/{manifest-tokenizers.js → moz-manifest-tokenizers.js} +9 -12
  297. package/dist/src/core/ownership-table.d.ts +14 -16
  298. package/dist/src/core/ownership-table.js +14 -16
  299. package/dist/src/core/parser-fallback.d.ts +15 -1
  300. package/dist/src/core/parser-fallback.js +22 -3
  301. package/dist/src/core/patch-apply-fuzz.d.ts +10 -12
  302. package/dist/src/core/patch-apply-fuzz.js +15 -18
  303. package/dist/src/core/patch-apply.d.ts +13 -34
  304. package/dist/src/core/patch-apply.js +16 -76
  305. package/dist/src/core/patch-artifact-normalize.d.ts +13 -15
  306. package/dist/src/core/patch-artifact-normalize.js +13 -15
  307. package/dist/src/core/patch-export-metadata.d.ts +12 -2
  308. package/dist/src/core/patch-export-metadata.js +13 -4
  309. package/dist/src/core/patch-export-update.d.ts +13 -1
  310. package/dist/src/core/patch-export-update.js +25 -8
  311. package/dist/src/core/patch-export.d.ts +15 -8
  312. package/dist/src/core/patch-export.js +10 -11
  313. package/dist/src/core/patch-files.d.ts +5 -6
  314. package/dist/src/core/patch-files.js +5 -6
  315. package/dist/src/core/patch-identifier-suggest.d.ts +7 -12
  316. package/dist/src/core/patch-identifier-suggest.js +14 -19
  317. package/dist/src/core/patch-lint-binary.d.ts +51 -0
  318. package/dist/src/core/patch-lint-binary.js +39 -0
  319. package/dist/src/core/{lint-cache.d.ts → patch-lint-cache.d.ts} +5 -5
  320. package/dist/src/core/{lint-cache.js → patch-lint-cache.js} +21 -23
  321. package/dist/src/core/patch-lint-checkjs.d.ts +16 -16
  322. package/dist/src/core/patch-lint-checkjs.js +41 -20
  323. package/dist/src/core/patch-lint-chrome-jsdoc.d.ts +6 -9
  324. package/dist/src/core/patch-lint-chrome-jsdoc.js +10 -14
  325. package/dist/src/core/patch-lint-creators.d.ts +8 -8
  326. package/dist/src/core/patch-lint-creators.js +8 -8
  327. package/dist/src/core/patch-lint-cross.d.ts +17 -20
  328. package/dist/src/core/patch-lint-cross.js +16 -16
  329. package/dist/src/core/patch-lint-css.d.ts +3 -5
  330. package/dist/src/core/patch-lint-css.js +17 -22
  331. package/dist/src/core/patch-lint-diff-tag.d.ts +14 -16
  332. package/dist/src/core/patch-lint-diff-tag.js +14 -16
  333. package/dist/src/core/patch-lint-jsdoc.d.ts +7 -8
  334. package/dist/src/core/patch-lint-jsdoc.js +26 -19
  335. package/dist/src/core/patch-lint-mozbuild.js +20 -20
  336. package/dist/src/core/patch-lint-observer.d.ts +7 -7
  337. package/dist/src/core/patch-lint-observer.js +7 -7
  338. package/dist/src/core/patch-lint.d.ts +38 -29
  339. package/dist/src/core/patch-lint.js +89 -121
  340. package/dist/src/core/patch-lock.d.ts +1 -1
  341. package/dist/src/core/patch-lock.js +45 -9
  342. package/dist/src/core/patch-manifest-consistency.d.ts +57 -6
  343. package/dist/src/core/patch-manifest-consistency.js +111 -40
  344. package/dist/src/core/patch-manifest-files-affected.d.ts +43 -0
  345. package/dist/src/core/patch-manifest-files-affected.js +77 -0
  346. package/dist/src/core/patch-manifest-io.js +14 -18
  347. package/dist/src/core/patch-manifest-resolve.d.ts +9 -12
  348. package/dist/src/core/patch-manifest-resolve.js +9 -12
  349. package/dist/src/core/patch-manifest-validate.d.ts +6 -1
  350. package/dist/src/core/patch-manifest-validate.js +25 -13
  351. package/dist/src/core/patch-manifest.d.ts +2 -1
  352. package/dist/src/core/patch-manifest.js +2 -1
  353. package/dist/src/core/patch-parse.d.ts +24 -13
  354. package/dist/src/core/patch-parse.js +19 -14
  355. package/dist/src/core/patch-policy.d.ts +2 -2
  356. package/dist/src/core/patch-policy.js +2 -2
  357. package/dist/src/core/patch-registration-refs.d.ts +7 -8
  358. package/dist/src/core/patch-registration-refs.js +9 -9
  359. package/dist/src/core/process-cpu-time.d.ts +12 -0
  360. package/dist/src/core/process-cpu-time.js +52 -0
  361. package/dist/src/core/rebase-session.d.ts +38 -26
  362. package/dist/src/core/rebase-session.js +55 -28
  363. package/dist/src/core/register-browser-content.js +9 -74
  364. package/dist/src/core/{register-test-manifest.js → register-browser-test.js} +7 -42
  365. package/dist/src/core/register-module.js +10 -43
  366. package/dist/src/core/register-scaffold.d.ts +8 -8
  367. package/dist/src/core/register-scaffold.js +10 -10
  368. package/dist/src/core/register-shared-css.d.ts +9 -12
  369. package/dist/src/core/register-shared-css.js +17 -87
  370. package/dist/src/core/register-xpcshell-test.d.ts +6 -7
  371. package/dist/src/core/register-xpcshell-test.js +7 -8
  372. package/dist/src/core/shared-ftl.js +12 -4
  373. package/dist/src/core/state-file.d.ts +45 -0
  374. package/dist/src/core/state-file.js +34 -0
  375. package/dist/src/core/status-binary.d.ts +18 -11
  376. package/dist/src/core/status-binary.js +19 -12
  377. package/dist/src/core/status-classify.d.ts +30 -36
  378. package/dist/src/core/status-classify.js +21 -26
  379. package/dist/src/core/test-changed-prefs.d.ts +30 -0
  380. package/dist/src/core/test-changed-prefs.js +78 -0
  381. package/dist/src/core/test-harness-crash.d.ts +25 -63
  382. package/dist/src/core/test-harness-crash.js +121 -142
  383. package/dist/src/core/test-harness-signature.d.ts +18 -0
  384. package/dist/src/core/test-harness-signature.js +13 -0
  385. package/dist/src/core/test-path-scope.d.ts +12 -15
  386. package/dist/src/core/test-path-scope.js +15 -18
  387. package/dist/src/core/test-stale-check.d.ts +17 -17
  388. package/dist/src/core/test-stale-check.js +50 -43
  389. package/dist/src/core/test-stall-triage.d.ts +51 -0
  390. package/dist/src/core/test-stall-triage.js +126 -0
  391. package/dist/src/core/token-category.js +66 -14
  392. package/dist/src/core/token-coverage.js +9 -9
  393. package/dist/src/core/token-dark-mode.d.ts +9 -11
  394. package/dist/src/core/token-dark-mode.js +29 -13
  395. package/dist/src/core/token-docs.d.ts +2 -0
  396. package/dist/src/core/token-docs.js +3 -1
  397. package/dist/src/core/token-manager.d.ts +10 -2
  398. package/dist/src/core/token-manager.js +17 -8
  399. package/dist/src/core/token-scaffold.d.ts +7 -7
  400. package/dist/src/core/token-scaffold.js +7 -7
  401. package/dist/src/core/token-variant.d.ts +4 -4
  402. package/dist/src/core/token-variant.js +28 -6
  403. package/dist/src/core/toolchain-preflight.d.ts +20 -21
  404. package/dist/src/core/toolchain-preflight.js +28 -31
  405. package/dist/src/core/tree-guard.js +12 -2
  406. package/dist/src/core/tree-store.d.ts +41 -27
  407. package/dist/src/core/tree-store.js +68 -43
  408. package/dist/src/core/typecheck-shim.d.ts +23 -24
  409. package/dist/src/core/typecheck-shim.js +23 -24
  410. package/dist/src/core/typecheck.js +15 -9
  411. package/dist/src/core/wire-destroy.d.ts +3 -3
  412. package/dist/src/core/wire-destroy.js +7 -15
  413. package/dist/src/core/wire-dom-fragment.d.ts +9 -17
  414. package/dist/src/core/wire-dom-fragment.js +11 -44
  415. package/dist/src/core/wire-init.d.ts +2 -3
  416. package/dist/src/core/wire-init.js +8 -19
  417. package/dist/src/core/wire-subscript.d.ts +2 -3
  418. package/dist/src/core/wire-subscript.js +4 -13
  419. package/dist/src/core/wire-utils.d.ts +7 -8
  420. package/dist/src/core/wire-utils.js +7 -8
  421. package/dist/src/core/xpcshell-appdir.d.ts +38 -45
  422. package/dist/src/core/xpcshell-appdir.js +38 -45
  423. package/dist/src/errors/base.d.ts +37 -16
  424. package/dist/src/errors/base.js +37 -16
  425. package/dist/src/errors/build.d.ts +13 -1
  426. package/dist/src/errors/build.js +14 -2
  427. package/dist/src/errors/codes.d.ts +16 -0
  428. package/dist/src/errors/codes.js +16 -0
  429. package/dist/src/errors/furnace.d.ts +4 -4
  430. package/dist/src/errors/git.d.ts +6 -10
  431. package/dist/src/errors/git.js +6 -10
  432. package/dist/src/errors/patch.d.ts +7 -7
  433. package/dist/src/errors/patch.js +7 -7
  434. package/dist/src/errors/rebase.d.ts +4 -4
  435. package/dist/src/errors/rebase.js +4 -4
  436. package/dist/src/index.d.ts +7 -1
  437. package/dist/src/index.js +5 -0
  438. package/dist/src/types/commands/index.d.ts +2 -2
  439. package/dist/src/types/commands/options.d.ts +111 -70
  440. package/dist/src/types/commands/patches.d.ts +24 -34
  441. package/dist/src/types/commands/project.d.ts +5 -34
  442. package/dist/src/types/config.d.ts +25 -23
  443. package/dist/src/types/config.js +6 -1
  444. package/dist/src/types/furnace.d.ts +37 -13
  445. package/dist/src/types/furnace.js +19 -1
  446. package/dist/src/types/index.d.ts +3 -3
  447. package/dist/src/utils/build-info.d.ts +7 -8
  448. package/dist/src/utils/build-info.js +12 -11
  449. package/dist/src/utils/errors.d.ts +6 -8
  450. package/dist/src/utils/errors.js +6 -8
  451. package/dist/src/utils/logger.d.ts +27 -10
  452. package/dist/src/utils/logger.js +28 -16
  453. package/dist/src/utils/machine-output.d.ts +12 -0
  454. package/dist/src/utils/machine-output.js +33 -0
  455. package/dist/src/utils/options.d.ts +31 -14
  456. package/dist/src/utils/options.js +86 -30
  457. package/dist/src/utils/paths.d.ts +10 -8
  458. package/dist/src/utils/paths.js +10 -8
  459. package/dist/src/utils/platform.d.ts +0 -25
  460. package/dist/src/utils/platform.js +1 -42
  461. package/dist/src/utils/process-group.d.ts +9 -4
  462. package/dist/src/utils/process-group.js +19 -5
  463. package/dist/src/utils/process.d.ts +42 -7
  464. package/dist/src/utils/process.js +44 -17
  465. package/dist/src/utils/ps-duration.d.ts +31 -0
  466. package/dist/src/utils/ps-duration.js +70 -0
  467. package/dist/src/utils/regex.d.ts +9 -10
  468. package/dist/src/utils/regex.js +9 -10
  469. package/dist/src/utils/validation.d.ts +58 -28
  470. package/dist/src/utils/validation.js +60 -33
  471. package/package.json +3 -3
  472. package/dist/src/commands/doctor/post-rebase-audit.d.ts +0 -2
  473. package/dist/src/commands/doctor-furnace-manifest-sync.d.ts +0 -18
  474. package/dist/src/core/manifest-helpers.d.ts +0 -38
  475. package/dist/src/core/manifest-helpers.js +0 -120
  476. /package/dist/src/core/{lint-projection.d.ts → patch-lint-projection.d.ts} +0 -0
  477. /package/dist/src/core/{lint-projection.js → patch-lint-projection.js} +0 -0
  478. /package/dist/src/core/{register-test-manifest.d.ts → register-browser-test.d.ts} +0 -0
@@ -1,495 +1,4 @@
1
- // SPDX-License-Identifier: EUPL-1.2
2
- import { join } from 'node:path';
3
- import { pathExists, readText } from '../utils/fs.js';
4
- import { getProjectPaths } from './config.js';
5
- import { extractComponentChecksums } from './furnace-checksum-utils.js';
6
1
  /** Creates a normalized validation issue object. */
7
2
  export function createIssue(component, severity, check, message) {
8
3
  return { component, severity, check, message };
9
4
  }
10
- /** Detects whether template or script content assigns an ARIA role. */
11
- export function hasAriaRole(content) {
12
- return (/role\s*=\s*["']/.test(content) ||
13
- /\.role\s*=/.test(content) ||
14
- /setAttribute\(\s*["']role["']/.test(content));
15
- }
16
- /** Detects generic elements being used as custom interactive controls. */
17
- export function hasGenericInteractiveElement(content) {
18
- return /<(div|span)\b(?=[^>]*(?:@click|@key(?:down|press|up)|\btabindex\s*=|\.onclick\s*=))/i.test(content);
19
- }
20
- /** Detects a positive tabindex value, which disrupts natural tab order. */
21
- export function hasPositiveTabindex(content) {
22
- const match = content.match(/tabindex\s*=\s*["']?(\d+)/g);
23
- if (!match)
24
- return false;
25
- return match.some((m) => {
26
- const value = /(\d+)/.exec(m)?.[1];
27
- return value !== undefined && parseInt(value, 10) > 0;
28
- });
29
- }
30
- /**
31
- * Collects `[start, end)` spans of `<label>…</label>` elements whose content
32
- * includes actual label text. Labels cannot nest per HTML, so the non-greedy
33
- * inner match is sound. A span qualifies only when the inner content minus
34
- * tags still contains non-whitespace — an empty or tag-only wrapper provides
35
- * no accessible name. A `${…}` Lit binding counts as label text: dynamic
36
- * (usually localized) text is a legitimate accessible name.
37
- */
38
- function collectLabelledSpans(content) {
39
- const spans = [];
40
- const labelPattern = /<label\b[^>]*>([\s\S]*?)<\/label>/gi;
41
- let labelMatch;
42
- while ((labelMatch = labelPattern.exec(content)) !== null) {
43
- const inner = labelMatch[1] ?? '';
44
- if (/\S/.test(inner.replace(/<[^>]*>/g, ' '))) {
45
- spans.push({ start: labelMatch.index, end: labelMatch.index + labelMatch[0].length });
46
- }
47
- }
48
- return spans;
49
- }
50
- /** Detects form inputs without associated labels. */
51
- export function hasUnlabelledFormInput(content) {
52
- // Look for <input> or <select> or <textarea> without aria-label, aria-labelledby, or id
53
- // (id implies an external <label for="..."> could exist). A control wrapped
54
- // in a <label> that carries actual text is implicitly associated and is
55
- // exempt as well.
56
- const labelledSpans = collectLabelledSpans(content);
57
- const inputPattern = /<(input|select|textarea)\b([^>]*)>/gi;
58
- let inputMatch;
59
- while ((inputMatch = inputPattern.exec(content)) !== null) {
60
- const attrs = inputMatch[2] ?? '';
61
- if (/aria-label\s*=/.test(attrs) ||
62
- /aria-labelledby\s*=/.test(attrs) ||
63
- /\bid\s*=/.test(attrs) ||
64
- /type\s*=\s*["']hidden["']/i.test(attrs)) {
65
- continue;
66
- }
67
- const index = inputMatch.index;
68
- if (labelledSpans.some((span) => index >= span.start && index < span.end)) {
69
- continue;
70
- }
71
- return true;
72
- }
73
- return false;
74
- }
75
- /** Detects Lit-style template click handlers. */
76
- export function hasTemplateClickHandler(content) {
77
- return /@click\s*=\s*\$\{/.test(content);
78
- }
79
- /** Detects Lit-style template keyboard handlers. */
80
- export function hasTemplateKeyboardHandler(content) {
81
- return /@key(down|press|up)\s*=\s*\$\{/.test(content);
82
- }
83
- /**
84
- * Native HTML elements that dispatch `click` on Enter and Space via the
85
- * platform. Attaching `@click` to these is NOT a keyboard-a11y bug because
86
- * the browser already handles the keyboard activation path — a duplicate
87
- * `@keydown`/`@keypress` handler would usually double-fire the action.
88
- *
89
- * `<a>` is accepted only when an `href` attribute is present; bare `<a>` is
90
- * non-interactive and is treated as synthetic.
91
- */
92
- const NATIVE_CLICK_INTERACTIVE_TAGS = new Set([
93
- 'button',
94
- 'input',
95
- 'select',
96
- 'textarea',
97
- 'summary',
98
- 'details',
99
- // Mozilla widgets that extend the native pattern and keep Enter/Space activation.
100
- 'moz-button',
101
- 'moz-toggle',
102
- 'moz-checkbox',
103
- 'moz-radio',
104
- 'moz-radio-group',
105
- 'moz-menulist',
106
- ]);
107
- /**
108
- * Returns true when `customConfig` declares that the component's keyboard
109
- * activation path is covered by a wrapped native-interactive inner element,
110
- * either through an explicit opt-out (`keyboardCovered: true`) or by
111
- * composing a tag that lives in {@link NATIVE_CLICK_INTERACTIVE_TAGS}.
112
- *
113
- * Uses `.some` rather than `.every` so that a wrapper composing e.g.
114
- * `['moz-button', 'my-tooltip']` still skips the warning: the keyboard
115
- * activation path flows through the button, even if other composed
116
- * children are synthetic.
117
- */
118
- export function isKeyboardCoveredByComposition(customConfig) {
119
- if (!customConfig)
120
- return false;
121
- if (customConfig.keyboardCovered === true)
122
- return true;
123
- const composes = customConfig.composes ?? [];
124
- return composes.some((tag) => NATIVE_CLICK_INTERACTIVE_TAGS.has(tag));
125
- }
126
- /**
127
- * Returns true when `content` has at least one `@click=${...}` handler on a
128
- * *synthetic* interactive element (e.g. `<div @click>`), which lacks native
129
- * keyboard activation and therefore needs an explicit key handler for
130
- * Enter/Space. Returns false when every `@click` handler sits on a native
131
- * interactive element — those already fire `click` on keyboard activation.
132
- */
133
- export function hasTemplateClickOnSyntheticInteractive(content) {
134
- const pattern = /@click\s*=\s*\$\{/g;
135
- let match;
136
- while ((match = pattern.exec(content)) !== null) {
137
- if (isClickOnSyntheticInteractive(content, match.index)) {
138
- return true;
139
- }
140
- }
141
- return false;
142
- }
143
- /**
144
- * Given the offset of an `@click=${...}` occurrence, walks backwards to find
145
- * the opening `<tag` that owns it and decides whether that tag is a native
146
- * interactive element (no warning needed) or a synthetic one (warning needed).
147
- */
148
- function isClickOnSyntheticInteractive(content, clickIndex) {
149
- // Find the nearest preceding `<` that starts a tag (skip `</` closers).
150
- let i = clickIndex - 1;
151
- let tagOpenIndex = -1;
152
- while (i >= 0) {
153
- if (content[i] === '<' && content[i + 1] !== '/') {
154
- tagOpenIndex = i;
155
- break;
156
- }
157
- // A `>` before an unclosed `<` means we're outside the attribute list,
158
- // which shouldn't happen for a well-formed template but we defensively
159
- // treat it as synthetic to preserve the prior-behaviour warning.
160
- if (content[i] === '>') {
161
- return true;
162
- }
163
- i--;
164
- }
165
- if (tagOpenIndex < 0)
166
- return true;
167
- const tagMatch = /^<([a-zA-Z][a-zA-Z0-9-]*)/.exec(content.slice(tagOpenIndex));
168
- if (!tagMatch?.[1])
169
- return true;
170
- const tagName = tagMatch[1].toLowerCase();
171
- if (tagName === 'a') {
172
- // Bare <a> (no href) is non-interactive; require a keyboard handler.
173
- // Look forward from the tag open for the closing `>` and scan the
174
- // attribute text in between for an href attribute.
175
- const tagEnd = content.indexOf('>', tagOpenIndex);
176
- if (tagEnd < 0)
177
- return true;
178
- const attrs = content.slice(tagOpenIndex, tagEnd);
179
- return !/\shref\s*=/.test(attrs);
180
- }
181
- return !NATIVE_CLICK_INTERACTIVE_TAGS.has(tagName);
182
- }
183
- /** ASCII punctuation that reads as decoration rather than localizable text. */
184
- const SYMBOL_ONLY_ASCII = '+-*=<>|/\\^~@#&!?%';
185
- /**
186
- * Reports whether `text` is decoration (arrows, maths, emoji, bare
187
- * punctuation) rather than user-facing prose that needs localizing.
188
- *
189
- * The letter/number/mark test comes first and is script-agnostic. Until
190
- * 0.41.0 the only non-ASCII rule was `code > 0xff`, which classified *every*
191
- * code point above U+00FF as a symbol — so all CJK, Cyrillic, Greek, Arabic,
192
- * Hebrew, Devanagari and Thai text was exempted from a **localization**
193
- * validator, i.e. the rule was blind to precisely the strings most likely to
194
- * need translating.
195
- *
196
- * Combining marks are deliberately NOT counted as text: the check is an
197
- * `every()`, so a script's base letters already disqualify the string, and
198
- * treating marks as text would flag emoji carrying a variation selector
199
- * (U+FE0F is category Mn — `⚙️` is U+2699 + U+FE0F).
200
- *
201
- * High code points that are not letters — emoji, arrows, CJK punctuation —
202
- * stay exempt, which is the rule's original intent.
203
- *
204
- * A handful of emoji are ALSO Unicode letters, and the letter test alone gets
205
- * them wrong. U+2139 (`ℹ`, the base of the very common `ℹ️`) is category Ll, so
206
- * the `\p{L}` branch classified an info badge as prose needing localization.
207
- * Non-ASCII code points carrying `Emoji` are therefore read as symbols before
208
- * the letter test. The ASCII guard matters: `\p{Emoji}` also covers the digits
209
- * `0`-`9`, `#` and `*`, which must keep their existing classification.
210
- */
211
- function isSymbolOnlyText(text) {
212
- return Array.from(text).every((character) => {
213
- const code = character.codePointAt(0) ?? 0;
214
- if (code > 0x7f && /\p{Emoji}/u.test(character))
215
- return true;
216
- if (/[\p{L}\p{N}]/u.test(character))
217
- return false;
218
- return code > 0xff || SYMBOL_ONLY_ASCII.includes(character);
219
- });
220
- }
221
- function isWithinLocalizedElement(content, matchIndex) {
222
- const contentBefore = content.slice(0, matchIndex + 1);
223
- const lastTagOpen = contentBefore.lastIndexOf('<');
224
- if (lastTagOpen === -1) {
225
- return false;
226
- }
227
- const tagContent = contentBefore.slice(lastTagOpen, matchIndex + 1);
228
- return /data-l10n-id\s*=/.test(tagContent);
229
- }
230
- /**
231
- * Detects hardcoded user-visible template text that should usually be
232
- * localized.
233
- *
234
- * Scoped to three positive contexts rather than scanning the whole file,
235
- * because a bare `>…<` regex catches JS comparisons (`if (x > 0 && y <
236
- * 100)`), diagnostic strings (`console.error("Failed <id> lookup")`), and
237
- * identifier literals that are never shown to a user. Only matches that
238
- * actually enter a UI render path count:
239
- *
240
- * 1. Content inside a Lit `` html`…` `` tagged template literal.
241
- * 2. The string literal on the RHS of `.textContent = "…"` or
242
- * `.innerHTML = "…"`.
243
- * 3. The string literal assigned to an XUL-widget `label=`,
244
- * `title=`, or `tooltiptext=` attribute when constructing DOM in JS.
245
- *
246
- * A file-wide `// furnace-ignore: hardcoded-text` comment suppresses all
247
- * findings (matches the pre-existing escape hatch).
248
- */
249
- export function containsHardcodedTemplateText(content) {
250
- if (/furnace-ignore:\s*hardcoded-text/.test(content)) {
251
- return false;
252
- }
253
- return (hasFlaggedTextInLitTemplates(content) ||
254
- hasFlaggedTextInDomAssignment(content) ||
255
- hasFlaggedTextInXulAttribute(content));
256
- }
257
- function isFlaggableText(text) {
258
- const trimmed = text.trim();
259
- if (!trimmed)
260
- return false;
261
- if (/\$\{/.test(trimmed))
262
- return false;
263
- if (Array.from(trimmed).length <= 1)
264
- return false;
265
- if (isSymbolOnlyText(trimmed))
266
- return false;
267
- return true;
268
- }
269
- function hasFlaggedTextInLitTemplates(content) {
270
- // Match `html\`…\`` regions, anchored on a non-identifier char before `html`
271
- // so substrings like `otherhtml` do not spuriously open a template.
272
- const htmlPattern = /(?:^|[^a-zA-Z0-9_$])html`([\s\S]*?)`/g;
273
- let litMatch;
274
- while ((litMatch = htmlPattern.exec(content)) !== null) {
275
- const region = litMatch[1] ?? '';
276
- const textPattern = />([^<$\s][^<$]*)</g;
277
- let textMatch;
278
- while ((textMatch = textPattern.exec(region)) !== null) {
279
- const text = textMatch[1] ?? '';
280
- if (!isFlaggableText(text))
281
- continue;
282
- if (isWithinLocalizedElement(region, textMatch.index))
283
- continue;
284
- return true;
285
- }
286
- }
287
- return false;
288
- }
289
- function hasFlaggedTextInDomAssignment(content) {
290
- // `<expr>.textContent = "abc"` and `<expr>.innerHTML = "abc"` — these are
291
- // user-visible render paths. Template-literal RHS is excluded (usually
292
- // dynamic), matching the `${` guard used elsewhere in this helper.
293
- const assignPattern = /\.(?:textContent|innerHTML)\s*=\s*(["'])((?:\\.|(?!\1).)*)\1/g;
294
- let match;
295
- while ((match = assignPattern.exec(content)) !== null) {
296
- const text = match[2] ?? '';
297
- if (isFlaggableText(text))
298
- return true;
299
- }
300
- return false;
301
- }
302
- function hasFlaggedTextInXulAttribute(content) {
303
- // Assignments like `node.setAttribute("label", "Save")` or JS-built XUL
304
- // attributes `label="…"` / `title="…"` / `tooltiptext="…"` in template
305
- // literals outside Lit blocks. Covers DOM built via createXULElement.
306
- const setAttrPattern = /setAttribute\s*\(\s*["'](?:label|title|tooltiptext)["']\s*,\s*(["'])((?:\\.|(?!\1).)*)\1/g;
307
- let setAttrMatch;
308
- while ((setAttrMatch = setAttrPattern.exec(content)) !== null) {
309
- const text = setAttrMatch[2] ?? '';
310
- if (isFlaggableText(text))
311
- return true;
312
- }
313
- return false;
314
- }
315
- /** Detects whether a component opts into shadow-root focus delegation. */
316
- export function hasDelegatesFocusEnabled(content) {
317
- return /shadowRootOptions[\s\S]*?delegatesFocus\s*:\s*true/.test(content);
318
- }
319
- /** Removes CSS block comments before running simple string-based checks. */
320
- export function stripCssBlockComments(content) {
321
- return content.replace(/\/\*[\s\S]*?\*\//g, '');
322
- }
323
- /** Detects relative ES module imports in a component module file. */
324
- export function hasRelativeModuleImport(mjsContent) {
325
- return (/^\s*import\s.*from\s+["']\.\.?\//m.test(mjsContent) ||
326
- /^\s*import\s+["']\.\.?\//m.test(mjsContent));
327
- }
328
- /** Detects whether a module defines a custom element at runtime. */
329
- export function hasCustomElementDefineCall(mjsContent) {
330
- return /customElements\.define\s*\(/.test(mjsContent);
331
- }
332
- /**
333
- * Detects whether the module's `customElements.define(...)` call includes a
334
- * literal `extends:` option (third argument). That shape is the marker for
335
- * a customized built-in element — the class extends a specific
336
- * `HTMLxxxElement` rather than the autonomous `MozLitElement` path.
337
- *
338
- * Firefox's own widgets use this pattern for toolkit anchors (e.g.
339
- * `moz-support-link` extends `HTMLAnchorElement` with
340
- * `customElements.define("moz-support-link", ..., { extends: "a" })`), and
341
- * the validator's `not-moz-lit-element` check must allow them through or
342
- * `furnace override` of a valid upstream component fails its own
343
- * `furnace validate` pass with nothing the operator can fix.
344
- */
345
- function hasCustomElementExtendsOption(mjsContent) {
346
- // Match `customElements.define(..., { ..., extends: "..." })`. Tolerant of
347
- // whitespace, line breaks, and other object properties. The `[^)]*` stops
348
- // the inner greedy match at the closing define call paren so a later
349
- // `define` call on a different custom element in the same module does
350
- // not bleed its options in.
351
- return /customElements\.define\s*\([^)]*\bextends\s*:\s*["'`]/.test(mjsContent);
352
- }
353
- /**
354
- * Checks whether a declared component class extends a valid element base.
355
- *
356
- * Two shapes are accepted:
357
- *
358
- * 1. Autonomous custom element: `class X extends MozLitElement` — the
359
- * default FireForge pattern for fork-authored components and most
360
- * toolkit widgets.
361
- * 2. Customized built-in: `class X extends HTML<Something>Element` paired
362
- * with a `customElements.define(..., ..., { extends: "<tagname>" })`
363
- * call. Firefox's `moz-support-link`, `moz-button-group` tabbing
364
- * widgets, and a handful of other toolkit components use this form;
365
- * `furnace override` of those components writes the original source
366
- * verbatim and the validator must not reject them.
367
- *
368
- * A class that extends a plain `HTMLElement` WITHOUT a `extends:` option
369
- * is still rejected — that's the legitimate `not-moz-lit-element` case
370
- * the rule was originally designed to catch.
371
- */
372
- export function classExtendsMozLitElement(mjsContent) {
373
- const hasClassDeclaration = /class\s+\w+\s+extends\s+/.test(mjsContent);
374
- if (!hasClassDeclaration) {
375
- // No class declaration — skip this check since the component may use a
376
- // different pattern (e.g. function-based). Other validators will catch
377
- // structural issues.
378
- return true;
379
- }
380
- if (/class\s+\w+\s+extends\s+MozLitElement\b/.test(mjsContent)) {
381
- return true;
382
- }
383
- // Customized built-in: extend a specific HTMLxxxElement AND the define
384
- // call carries an `extends:` option. Both halves are required — a class
385
- // that extends `HTMLAnchorElement` without the matching define option is
386
- // almost certainly an author mistake, and a define call with `extends:`
387
- // without a matching class is unreachable.
388
- const extendsCustomizedBuiltin = /class\s+\w+\s+extends\s+HTML[A-Z]\w*Element\b/.test(mjsContent);
389
- if (extendsCustomizedBuiltin && hasCustomElementExtendsOption(mjsContent)) {
390
- return true;
391
- }
392
- return false;
393
- }
394
- /** Collects CSS custom property references used via var(--token-name). */
395
- export function collectCssVariableReferences(cssContent) {
396
- const referencedVariables = [];
397
- const variablePattern = /var\(\s*(--[\w-]+)/g;
398
- let match;
399
- while ((match = variablePattern.exec(cssContent)) !== null) {
400
- const variableName = match[1];
401
- if (variableName) {
402
- referencedVariables.push(variableName);
403
- }
404
- }
405
- return referencedVariables;
406
- }
407
- /**
408
- * Collects CSS custom property *declarations* — names appearing on the
409
- * left-hand side of a `--name:` declaration. Used to auto-exempt
410
- * component-local runtime variables from the token-prefix check: if the
411
- * component both declares and consumes a variable in its own CSS file, it
412
- * is a local runtime channel, not a design-token reference.
413
- *
414
- * The anchor `(?:^|[{;,\s])` rules out `var(--name)` occurrences (which are
415
- * always preceded by `(`), so references are not mistaken for declarations.
416
- */
417
- export function collectCssVariableDeclarations(cssContent) {
418
- const declared = new Set();
419
- const pattern = /(?:^|[{;,\s])(--[\w-]+)\s*:/g;
420
- let match;
421
- while ((match = pattern.exec(cssContent)) !== null) {
422
- const name = match[1];
423
- if (name)
424
- declared.add(name);
425
- }
426
- return declared;
427
- }
428
- async function collectInheritedOverrideVariables(tagName, config, root) {
429
- const inheritedVariables = new Set();
430
- const basePath = config.overrides[tagName]?.basePath;
431
- if (!basePath) {
432
- return inheritedVariables;
433
- }
434
- const { engine: engineDir } = getProjectPaths(root);
435
- const originalCssPath = join(engineDir, basePath, `${tagName}.css`);
436
- if (!(await pathExists(originalCssPath))) {
437
- return inheritedVariables;
438
- }
439
- const originalCssContent = stripCssBlockComments(await readText(originalCssPath));
440
- for (const variableName of collectCssVariableReferences(originalCssContent)) {
441
- inheritedVariables.add(variableName);
442
- }
443
- return inheritedVariables;
444
- }
445
- /** Builds token-validation context from the config allowlist and inherited override CSS. */
446
- export async function getTokenPrefixContext(tagName, type, config, root) {
447
- const allowlist = new Set(config.tokenAllowlist ?? []);
448
- const runtimeVariables = new Set(config.runtimeVariables ?? []);
449
- if (type !== 'override' || !root) {
450
- return { allowlist, inheritedOverrideVars: new Set(), runtimeVariables };
451
- }
452
- return {
453
- allowlist,
454
- inheritedOverrideVars: await collectInheritedOverrideVariables(tagName, config, root),
455
- runtimeVariables,
456
- };
457
- }
458
- /**
459
- * Flags engine-side files that a previous deploy of `tagName` left behind
460
- * after their workspace source was renamed or removed (field report D1).
461
- *
462
- * Detection keys on the furnace state file: every `appliedChecksums` entry
463
- * under `custom/<tagName>/` whose workspace source no longer exists but
464
- * whose engine target is still present is an orphan — the next deploy will
465
- * prune it, but until then jar.mn and the deployed directory disagree with
466
- * the workspace, and a re-export could capture the stale state into a patch.
467
- *
468
- * Custom components only: override undeploys restore the upstream baseline
469
- * rather than deleting files, so "orphan" has no meaning there.
470
- */
471
- export async function findOrphanedEngineFiles(root, config, tagName, state, ftlDir) {
472
- const customConfig = config.custom[tagName];
473
- if (!customConfig)
474
- return [];
475
- const previous = extractComponentChecksums(state.appliedChecksums, 'custom', tagName);
476
- const fileNames = Object.keys(previous);
477
- if (fileNames.length === 0)
478
- return [];
479
- const { engine: engineDir, componentsDir } = getProjectPaths(root);
480
- const componentDir = join(componentsDir, 'custom', tagName);
481
- const issues = [];
482
- for (const fileName of fileNames) {
483
- if (await pathExists(join(componentDir, fileName)))
484
- continue;
485
- const enginePath = fileName.endsWith('.ftl')
486
- ? join(engineDir, ftlDir, fileName)
487
- : join(engineDir, customConfig.targetPath, fileName);
488
- if (!(await pathExists(enginePath)))
489
- continue;
490
- issues.push(createIssue(tagName, 'warning', 'orphaned-engine-file', `Engine file ${fileName} was deployed by a previous apply but its workspace source ` +
491
- `is gone (renamed or deleted). The deployed copy${customConfig.register ? ' and any stale jar.mn entry' : ''} ` +
492
- `will linger until the next deploy prunes it. Run "fireforge furnace deploy ${tagName}".`));
493
- }
494
- return issues;
495
- }
@@ -30,6 +30,13 @@ export declare function checkRegistrationConsistency(root: string, name: string,
30
30
  * @returns Array of validation issues for missing jar.mn entries
31
31
  */
32
32
  export declare function validateJarMnEntries(root: string, config: FurnaceConfig): Promise<ValidationIssue[]>;
33
+ /**
34
+ * Runs `body` with the per-run caches enabled, then clears them.
35
+ *
36
+ * @param body - The batch to run
37
+ * @returns Whatever `body` resolves to
38
+ */
39
+ export declare function withRegistrationValidationCache<T>(body: () => Promise<T>): Promise<T>;
33
40
  /**
34
41
  * Validates that components using design tokens have the tokens CSS
35
42
  * linked in at least one chrome host document. Without the link, tokens