@hominis/fireforge 0.43.1 → 0.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (470) hide show
  1. package/CHANGELOG.md +126 -0
  2. package/README.md +10 -1
  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 +4 -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-post-rebase-audit.d.ts +2 -0
  22. package/dist/src/commands/{doctor/post-rebase-audit.js → doctor-post-rebase-audit.js} +3 -3
  23. package/dist/src/commands/doctor-working-tree.d.ts +10 -12
  24. package/dist/src/commands/doctor-working-tree.js +11 -18
  25. package/dist/src/commands/doctor.js +35 -53
  26. package/dist/src/commands/download.js +32 -48
  27. package/dist/src/commands/export-all.js +29 -33
  28. package/dist/src/commands/export-flow.js +6 -6
  29. package/dist/src/commands/export-placement-conflicts.js +10 -9
  30. package/dist/src/commands/export-placement-gate.js +5 -5
  31. package/dist/src/commands/export-shared.d.ts +30 -33
  32. package/dist/src/commands/export-shared.js +45 -43
  33. package/dist/src/commands/export.js +21 -27
  34. package/dist/src/commands/furnace/apply.js +14 -23
  35. package/dist/src/commands/furnace/chrome-doc-remove.js +14 -21
  36. package/dist/src/commands/furnace/chrome-doc-templates.d.ts +23 -23
  37. package/dist/src/commands/furnace/chrome-doc-templates.js +23 -23
  38. package/dist/src/commands/furnace/chrome-doc-tests.js +26 -29
  39. package/dist/src/commands/furnace/chrome-doc.d.ts +16 -17
  40. package/dist/src/commands/furnace/chrome-doc.js +31 -41
  41. package/dist/src/commands/furnace/create-browser-test.d.ts +4 -4
  42. package/dist/src/commands/furnace/create-browser-test.js +8 -8
  43. package/dist/src/commands/furnace/create-mochikit.d.ts +6 -7
  44. package/dist/src/commands/furnace/create-mochikit.js +8 -9
  45. package/dist/src/commands/furnace/create-readback.d.ts +12 -13
  46. package/dist/src/commands/furnace/create-readback.js +12 -13
  47. package/dist/src/commands/furnace/create-templates.d.ts +22 -28
  48. package/dist/src/commands/furnace/create-templates.js +35 -30
  49. package/dist/src/commands/furnace/create-xpcshell.js +2 -2
  50. package/dist/src/commands/furnace/create.js +33 -23
  51. package/dist/src/commands/furnace/deploy.js +16 -24
  52. package/dist/src/commands/furnace/diff.js +9 -9
  53. package/dist/src/commands/furnace/init.js +33 -36
  54. package/dist/src/commands/furnace/override.js +23 -25
  55. package/dist/src/commands/furnace/preview.js +47 -67
  56. package/dist/src/commands/furnace/refresh.js +12 -16
  57. package/dist/src/commands/furnace/remove-mutations.d.ts +3 -6
  58. package/dist/src/commands/furnace/remove-mutations.js +9 -16
  59. package/dist/src/commands/furnace/remove-state.js +1 -1
  60. package/dist/src/commands/furnace/remove.js +33 -38
  61. package/dist/src/commands/furnace/rename-xpcshell.d.ts +8 -11
  62. package/dist/src/commands/furnace/rename-xpcshell.js +8 -11
  63. package/dist/src/commands/furnace/rename.js +59 -69
  64. package/dist/src/commands/furnace/scan.js +19 -33
  65. package/dist/src/commands/furnace/status.js +12 -9
  66. package/dist/src/commands/furnace/sync.js +9 -16
  67. package/dist/src/commands/furnace/validate.js +20 -20
  68. package/dist/src/commands/import.js +42 -35
  69. package/dist/src/commands/lint-per-patch.js +15 -10
  70. package/dist/src/commands/lint-per-run-checkjs.d.ts +13 -13
  71. package/dist/src/commands/lint-per-run-checkjs.js +13 -13
  72. package/dist/src/commands/lint-report.js +6 -7
  73. package/dist/src/commands/lint.d.ts +15 -16
  74. package/dist/src/commands/lint.js +86 -102
  75. package/dist/src/commands/package.js +6 -11
  76. package/dist/src/commands/patch/compact.js +1 -1
  77. package/dist/src/commands/patch/delete.js +24 -33
  78. package/dist/src/commands/patch/index.d.ts +5 -6
  79. package/dist/src/commands/patch/index.js +10 -12
  80. package/dist/src/commands/patch/lint-ignore.js +14 -13
  81. package/dist/src/commands/patch/move-files-create.d.ts +6 -6
  82. package/dist/src/commands/patch/move-files-create.js +8 -8
  83. package/dist/src/commands/patch/move-files-into.d.ts +6 -6
  84. package/dist/src/commands/patch/move-files-into.js +8 -8
  85. package/dist/src/commands/patch/patch-context.d.ts +2 -3
  86. package/dist/src/commands/patch/patch-context.js +2 -3
  87. package/dist/src/commands/patch/rename.d.ts +10 -11
  88. package/dist/src/commands/patch/rename.js +11 -12
  89. package/dist/src/commands/patch/reorder.js +8 -9
  90. package/dist/src/commands/patch/split-plan.js +1 -1
  91. package/dist/src/commands/patch/split.d.ts +8 -10
  92. package/dist/src/commands/patch/split.js +9 -11
  93. package/dist/src/commands/patch/staged-dependency-validate.js +8 -8
  94. package/dist/src/commands/patch/staged-dependency.js +7 -3
  95. package/dist/src/commands/patch/tier.d.ts +9 -9
  96. package/dist/src/commands/patch/tier.js +18 -15
  97. package/dist/src/commands/re-export-adjacent.js +9 -8
  98. package/dist/src/commands/re-export-bulk-scan.d.ts +9 -9
  99. package/dist/src/commands/re-export-bulk-scan.js +22 -21
  100. package/dist/src/commands/re-export-drift.js +10 -10
  101. package/dist/src/commands/re-export-files.d.ts +6 -7
  102. package/dist/src/commands/re-export-files.js +34 -44
  103. package/dist/src/commands/re-export-lint.d.ts +10 -13
  104. package/dist/src/commands/re-export-lint.js +16 -14
  105. package/dist/src/commands/re-export-options.d.ts +6 -6
  106. package/dist/src/commands/re-export-options.js +6 -6
  107. package/dist/src/commands/re-export-register.d.ts +4 -10
  108. package/dist/src/commands/re-export-register.js +5 -11
  109. package/dist/src/commands/re-export-scan.js +1 -1
  110. package/dist/src/commands/re-export-single.d.ts +3 -3
  111. package/dist/src/commands/re-export-single.js +33 -25
  112. package/dist/src/commands/re-export.js +13 -21
  113. package/dist/src/commands/rebase/abort.js +3 -3
  114. package/dist/src/commands/rebase/confirm.js +2 -1
  115. package/dist/src/commands/rebase/continue.d.ts +1 -1
  116. package/dist/src/commands/rebase/continue.js +14 -9
  117. package/dist/src/commands/rebase/index.js +11 -11
  118. package/dist/src/commands/rebase/patch-loop.d.ts +7 -1
  119. package/dist/src/commands/rebase/patch-loop.js +60 -39
  120. package/dist/src/commands/rebase/summary.js +1 -1
  121. package/dist/src/commands/register.js +5 -7
  122. package/dist/src/commands/reset.js +2 -1
  123. package/dist/src/commands/resolve.d.ts +16 -13
  124. package/dist/src/commands/resolve.js +30 -33
  125. package/dist/src/commands/run.js +33 -35
  126. package/dist/src/commands/setup-support.js +15 -19
  127. package/dist/src/commands/setup.js +13 -9
  128. package/dist/src/commands/status-check.d.ts +6 -6
  129. package/dist/src/commands/status-json.d.ts +6 -6
  130. package/dist/src/commands/status-json.js +5 -0
  131. package/dist/src/commands/status-output.d.ts +5 -5
  132. package/dist/src/commands/status-output.js +6 -6
  133. package/dist/src/commands/status-ownership.d.ts +16 -14
  134. package/dist/src/commands/status-ownership.js +16 -14
  135. package/dist/src/commands/status.js +42 -34
  136. package/dist/src/commands/test-build-phase.js +26 -13
  137. package/dist/src/commands/test-diagnose.js +44 -44
  138. package/dist/src/commands/test-register.js +1 -0
  139. package/dist/src/commands/test-run.d.ts +14 -16
  140. package/dist/src/commands/test-run.js +21 -13
  141. package/dist/src/commands/test-stale-gate.d.ts +15 -16
  142. package/dist/src/commands/test-stale-gate.js +15 -16
  143. package/dist/src/commands/test-verdict.d.ts +20 -3
  144. package/dist/src/commands/test-verdict.js +30 -0
  145. package/dist/src/commands/test.js +83 -76
  146. package/dist/src/commands/token-coverage.js +3 -4
  147. package/dist/src/commands/token.js +16 -18
  148. package/dist/src/commands/tree.js +47 -31
  149. package/dist/src/commands/typecheck.d.ts +10 -12
  150. package/dist/src/commands/typecheck.js +24 -27
  151. package/dist/src/commands/verify.js +13 -15
  152. package/dist/src/commands/watch.js +21 -23
  153. package/dist/src/commands/wire.js +52 -62
  154. package/dist/src/core/ast-utils.d.ts +8 -7
  155. package/dist/src/core/ast-utils.js +8 -7
  156. package/dist/src/core/branding.d.ts +9 -14
  157. package/dist/src/core/branding.js +7 -11
  158. package/dist/src/core/browser-wire.d.ts +1 -1
  159. package/dist/src/core/browser-wire.js +14 -19
  160. package/dist/src/core/build-audit-platform.js +25 -33
  161. package/dist/src/core/build-audit-registration.js +17 -25
  162. package/dist/src/core/build-audit-resolve.d.ts +15 -17
  163. package/dist/src/core/build-audit-resolve.js +27 -33
  164. package/dist/src/core/build-audit-transforms.js +18 -19
  165. package/dist/src/core/build-audit.js +28 -42
  166. package/dist/src/core/build-baseline-types.d.ts +29 -35
  167. package/dist/src/core/build-baseline.d.ts +5 -4
  168. package/dist/src/core/build-baseline.js +14 -14
  169. package/dist/src/core/build-overwrite-guard.d.ts +7 -14
  170. package/dist/src/core/build-overwrite-guard.js +17 -27
  171. package/dist/src/core/build-prepare.d.ts +2 -2
  172. package/dist/src/core/build-prepare.js +8 -9
  173. package/dist/src/core/config-state.js +12 -4
  174. package/dist/src/core/config-validate.js +8 -5
  175. package/dist/src/core/config.d.ts +5 -8
  176. package/dist/src/core/config.js +7 -16
  177. package/dist/src/core/coverage-extend.d.ts +15 -13
  178. package/dist/src/core/coverage-extend.js +15 -13
  179. package/dist/src/core/destructive.d.ts +31 -9
  180. package/dist/src/core/destructive.js +29 -26
  181. package/dist/src/core/diff-hunks.js +10 -12
  182. package/dist/src/core/discard-baseline.d.ts +8 -8
  183. package/dist/src/core/discard-baseline.js +16 -15
  184. package/dist/src/core/display-state.d.ts +12 -14
  185. package/dist/src/core/display-state.js +12 -14
  186. package/dist/src/core/engine-changes.d.ts +2 -4
  187. package/dist/src/core/engine-changes.js +2 -4
  188. package/dist/src/core/engine-precondition.d.ts +28 -13
  189. package/dist/src/core/engine-precondition.js +25 -10
  190. package/dist/src/core/engine-session-lock.d.ts +47 -21
  191. package/dist/src/core/engine-session-lock.js +168 -33
  192. package/dist/src/core/export-moved-code-shape.d.ts +10 -10
  193. package/dist/src/core/export-moved-code-shape.js +10 -10
  194. package/dist/src/core/file-lock.d.ts +62 -5
  195. package/dist/src/core/file-lock.js +196 -59
  196. package/dist/src/core/firefox-cache.js +1 -3
  197. package/dist/src/core/firefox-extract.js +10 -14
  198. package/dist/src/core/firefox.d.ts +7 -5
  199. package/dist/src/core/firefox.js +4 -5
  200. package/dist/src/core/furnace-apply-dry-run.d.ts +2 -2
  201. package/dist/src/core/furnace-apply-dry-run.js +3 -2
  202. package/dist/src/core/furnace-apply-ftl.d.ts +7 -9
  203. package/dist/src/core/furnace-apply-ftl.js +12 -12
  204. package/dist/src/core/furnace-apply-helpers.d.ts +7 -7
  205. package/dist/src/core/furnace-apply-helpers.js +19 -16
  206. package/dist/src/core/furnace-apply-overwrite-warn.d.ts +8 -9
  207. package/dist/src/core/furnace-apply-overwrite-warn.js +8 -9
  208. package/dist/src/core/furnace-apply-undeploy-actions.d.ts +3 -4
  209. package/dist/src/core/furnace-apply-undeploy-actions.js +3 -4
  210. package/dist/src/core/furnace-apply.d.ts +5 -8
  211. package/dist/src/core/furnace-apply.js +19 -24
  212. package/dist/src/core/furnace-checksum-utils.d.ts +14 -0
  213. package/dist/src/core/furnace-checksum-utils.js +16 -0
  214. package/dist/src/core/furnace-config.d.ts +21 -30
  215. package/dist/src/core/furnace-config.js +32 -54
  216. package/dist/src/core/furnace-constants.d.ts +8 -0
  217. package/dist/src/core/furnace-constants.js +10 -2
  218. package/dist/src/core/furnace-css-fragments.d.ts +5 -5
  219. package/dist/src/core/furnace-css-fragments.js +5 -5
  220. package/dist/src/core/furnace-jsconfig.d.ts +11 -12
  221. package/dist/src/core/furnace-jsconfig.js +11 -12
  222. package/dist/src/core/furnace-marker.d.ts +7 -8
  223. package/dist/src/core/furnace-marker.js +7 -8
  224. package/dist/src/core/furnace-operation.d.ts +31 -0
  225. package/dist/src/core/furnace-operation.js +54 -17
  226. package/dist/src/core/furnace-precondition.d.ts +61 -0
  227. package/dist/src/core/furnace-precondition.js +67 -0
  228. package/dist/src/core/furnace-registration-remove.d.ts +5 -6
  229. package/dist/src/core/furnace-registration-remove.js +6 -7
  230. package/dist/src/core/furnace-registration-validate.d.ts +13 -0
  231. package/dist/src/core/furnace-registration-validate.js +20 -1
  232. package/dist/src/core/furnace-registration.d.ts +5 -6
  233. package/dist/src/core/furnace-registration.js +10 -12
  234. package/dist/src/core/furnace-rollback.js +7 -7
  235. package/dist/src/core/furnace-scanner.d.ts +1 -0
  236. package/dist/src/core/furnace-scanner.js +1 -2
  237. package/dist/src/core/furnace-stale-export.d.ts +10 -10
  238. package/dist/src/core/furnace-stale-export.js +10 -10
  239. package/dist/src/core/furnace-state-persist.d.ts +6 -8
  240. package/dist/src/core/furnace-state-persist.js +6 -8
  241. package/dist/src/core/furnace-validate-accessibility.d.ts +22 -0
  242. package/dist/src/core/furnace-validate-accessibility.js +310 -1
  243. package/dist/src/core/furnace-validate-compatibility.js +141 -1
  244. package/dist/src/core/furnace-validate-helpers.d.ts +5 -116
  245. package/dist/src/core/furnace-validate-helpers.js +0 -491
  246. package/dist/src/core/furnace-validate-registration.d.ts +7 -0
  247. package/dist/src/core/furnace-validate-registration.js +115 -41
  248. package/dist/src/core/furnace-validate.d.ts +16 -0
  249. package/dist/src/core/furnace-validate.js +188 -145
  250. package/dist/src/core/furnace-version-drift.d.ts +10 -11
  251. package/dist/src/core/furnace-version-drift.js +10 -11
  252. package/dist/src/core/git-base.d.ts +7 -9
  253. package/dist/src/core/git-base.js +7 -9
  254. package/dist/src/core/git-diff.d.ts +20 -9
  255. package/dist/src/core/git-diff.js +148 -63
  256. package/dist/src/core/git-file-ops.d.ts +19 -19
  257. package/dist/src/core/git-file-ops.js +19 -19
  258. package/dist/src/core/git-readonly-index.d.ts +53 -19
  259. package/dist/src/core/git-readonly-index.js +75 -31
  260. package/dist/src/core/git-status.d.ts +5 -6
  261. package/dist/src/core/git-status.js +5 -6
  262. package/dist/src/core/git.d.ts +9 -10
  263. package/dist/src/core/git.js +54 -70
  264. package/dist/src/core/license-headers.d.ts +17 -23
  265. package/dist/src/core/license-headers.js +17 -23
  266. package/dist/src/core/mach-build-artifacts.d.ts +9 -9
  267. package/dist/src/core/mach-build-artifacts.js +57 -19
  268. package/dist/src/core/mach-error-hints.js +42 -29
  269. package/dist/src/core/mach-known-noise-filter.d.ts +15 -16
  270. package/dist/src/core/mach-known-noise-filter.js +18 -20
  271. package/dist/src/core/mach-mozconfig.d.ts +14 -0
  272. package/dist/src/core/mach-mozconfig.js +30 -0
  273. package/dist/src/core/mach-resource-shim.d.ts +43 -58
  274. package/dist/src/core/mach-resource-shim.js +50 -67
  275. package/dist/src/core/mach.d.ts +37 -41
  276. package/dist/src/core/mach.js +50 -51
  277. package/dist/src/core/marionette-port.d.ts +36 -1
  278. package/dist/src/core/marionette-port.js +96 -31
  279. package/dist/src/core/marionette-preflight.d.ts +8 -12
  280. package/dist/src/core/marionette-preflight.js +86 -52
  281. package/dist/src/core/mochitest-server-port.d.ts +42 -0
  282. package/dist/src/core/mochitest-server-port.js +119 -0
  283. package/dist/src/core/module-resolution-preflight.d.ts +9 -11
  284. package/dist/src/core/module-resolution-preflight.js +9 -11
  285. package/dist/src/core/moz-manifest-helpers.d.ts +79 -0
  286. package/dist/src/core/moz-manifest-helpers.js +163 -0
  287. package/dist/src/core/{manifest-register.d.ts → moz-manifest-register.d.ts} +1 -1
  288. package/dist/src/core/{manifest-register.js → moz-manifest-register.js} +13 -28
  289. package/dist/src/core/{manifest-rules.d.ts → moz-manifest-rules.d.ts} +10 -1
  290. package/dist/src/core/{manifest-rules.js → moz-manifest-rules.js} +31 -24
  291. package/dist/src/core/{manifest-tokenizers.d.ts → moz-manifest-tokenizers.d.ts} +3 -5
  292. package/dist/src/core/{manifest-tokenizers.js → moz-manifest-tokenizers.js} +9 -12
  293. package/dist/src/core/ownership-table.d.ts +14 -16
  294. package/dist/src/core/ownership-table.js +14 -16
  295. package/dist/src/core/parser-fallback.d.ts +15 -1
  296. package/dist/src/core/parser-fallback.js +22 -3
  297. package/dist/src/core/patch-apply-fuzz.d.ts +10 -12
  298. package/dist/src/core/patch-apply-fuzz.js +15 -18
  299. package/dist/src/core/patch-apply.d.ts +13 -34
  300. package/dist/src/core/patch-apply.js +16 -76
  301. package/dist/src/core/patch-artifact-normalize.d.ts +13 -15
  302. package/dist/src/core/patch-artifact-normalize.js +13 -15
  303. package/dist/src/core/patch-export-metadata.d.ts +12 -2
  304. package/dist/src/core/patch-export-metadata.js +13 -4
  305. package/dist/src/core/patch-export-update.d.ts +13 -1
  306. package/dist/src/core/patch-export-update.js +25 -8
  307. package/dist/src/core/patch-export.d.ts +15 -8
  308. package/dist/src/core/patch-export.js +10 -11
  309. package/dist/src/core/patch-files.d.ts +5 -6
  310. package/dist/src/core/patch-files.js +5 -6
  311. package/dist/src/core/patch-identifier-suggest.d.ts +7 -12
  312. package/dist/src/core/patch-identifier-suggest.js +14 -19
  313. package/dist/src/core/patch-lint-binary.d.ts +51 -0
  314. package/dist/src/core/patch-lint-binary.js +39 -0
  315. package/dist/src/core/{lint-cache.d.ts → patch-lint-cache.d.ts} +5 -5
  316. package/dist/src/core/{lint-cache.js → patch-lint-cache.js} +21 -23
  317. package/dist/src/core/patch-lint-checkjs.d.ts +16 -16
  318. package/dist/src/core/patch-lint-checkjs.js +16 -16
  319. package/dist/src/core/patch-lint-chrome-jsdoc.d.ts +6 -9
  320. package/dist/src/core/patch-lint-chrome-jsdoc.js +10 -14
  321. package/dist/src/core/patch-lint-creators.d.ts +8 -8
  322. package/dist/src/core/patch-lint-creators.js +8 -8
  323. package/dist/src/core/patch-lint-cross.d.ts +17 -20
  324. package/dist/src/core/patch-lint-cross.js +16 -16
  325. package/dist/src/core/patch-lint-css.d.ts +3 -5
  326. package/dist/src/core/patch-lint-css.js +17 -22
  327. package/dist/src/core/patch-lint-diff-tag.d.ts +14 -16
  328. package/dist/src/core/patch-lint-diff-tag.js +14 -16
  329. package/dist/src/core/patch-lint-jsdoc.d.ts +7 -8
  330. package/dist/src/core/patch-lint-jsdoc.js +26 -19
  331. package/dist/src/core/patch-lint-mozbuild.js +20 -20
  332. package/dist/src/core/patch-lint-observer.d.ts +7 -7
  333. package/dist/src/core/patch-lint-observer.js +7 -7
  334. package/dist/src/core/patch-lint.d.ts +38 -29
  335. package/dist/src/core/patch-lint.js +89 -121
  336. package/dist/src/core/patch-lock.d.ts +1 -1
  337. package/dist/src/core/patch-lock.js +45 -9
  338. package/dist/src/core/patch-manifest-consistency.d.ts +2 -1
  339. package/dist/src/core/patch-manifest-consistency.js +25 -27
  340. package/dist/src/core/patch-manifest-io.js +14 -18
  341. package/dist/src/core/patch-manifest-resolve.d.ts +9 -12
  342. package/dist/src/core/patch-manifest-resolve.js +9 -12
  343. package/dist/src/core/patch-manifest-validate.d.ts +6 -1
  344. package/dist/src/core/patch-manifest-validate.js +25 -13
  345. package/dist/src/core/patch-parse.d.ts +24 -13
  346. package/dist/src/core/patch-parse.js +19 -14
  347. package/dist/src/core/patch-policy.d.ts +2 -2
  348. package/dist/src/core/patch-policy.js +2 -2
  349. package/dist/src/core/patch-registration-refs.d.ts +7 -8
  350. package/dist/src/core/patch-registration-refs.js +9 -9
  351. package/dist/src/core/process-cpu-time.d.ts +12 -0
  352. package/dist/src/core/process-cpu-time.js +52 -0
  353. package/dist/src/core/rebase-session.d.ts +38 -26
  354. package/dist/src/core/rebase-session.js +55 -28
  355. package/dist/src/core/register-browser-content.js +9 -74
  356. package/dist/src/core/{register-test-manifest.js → register-browser-test.js} +7 -42
  357. package/dist/src/core/register-module.js +10 -43
  358. package/dist/src/core/register-scaffold.d.ts +8 -8
  359. package/dist/src/core/register-scaffold.js +10 -10
  360. package/dist/src/core/register-shared-css.d.ts +9 -12
  361. package/dist/src/core/register-shared-css.js +17 -87
  362. package/dist/src/core/register-xpcshell-test.d.ts +6 -7
  363. package/dist/src/core/register-xpcshell-test.js +7 -8
  364. package/dist/src/core/shared-ftl.js +12 -4
  365. package/dist/src/core/state-file.d.ts +45 -0
  366. package/dist/src/core/state-file.js +34 -0
  367. package/dist/src/core/status-binary.d.ts +18 -11
  368. package/dist/src/core/status-binary.js +19 -12
  369. package/dist/src/core/status-classify.d.ts +30 -36
  370. package/dist/src/core/status-classify.js +21 -26
  371. package/dist/src/core/test-changed-prefs.d.ts +30 -0
  372. package/dist/src/core/test-changed-prefs.js +78 -0
  373. package/dist/src/core/test-harness-crash.d.ts +25 -63
  374. package/dist/src/core/test-harness-crash.js +121 -142
  375. package/dist/src/core/test-harness-signature.d.ts +18 -0
  376. package/dist/src/core/test-harness-signature.js +13 -0
  377. package/dist/src/core/test-path-scope.d.ts +12 -15
  378. package/dist/src/core/test-path-scope.js +15 -18
  379. package/dist/src/core/test-stale-check.d.ts +17 -17
  380. package/dist/src/core/test-stale-check.js +50 -43
  381. package/dist/src/core/test-stall-triage.d.ts +51 -0
  382. package/dist/src/core/test-stall-triage.js +126 -0
  383. package/dist/src/core/token-category.js +5 -7
  384. package/dist/src/core/token-coverage.js +9 -9
  385. package/dist/src/core/token-dark-mode.d.ts +9 -11
  386. package/dist/src/core/token-dark-mode.js +9 -11
  387. package/dist/src/core/token-docs.d.ts +2 -0
  388. package/dist/src/core/token-docs.js +2 -0
  389. package/dist/src/core/token-manager.d.ts +10 -2
  390. package/dist/src/core/token-manager.js +17 -8
  391. package/dist/src/core/token-scaffold.d.ts +7 -7
  392. package/dist/src/core/token-scaffold.js +7 -7
  393. package/dist/src/core/token-variant.d.ts +4 -4
  394. package/dist/src/core/token-variant.js +4 -4
  395. package/dist/src/core/toolchain-preflight.d.ts +20 -21
  396. package/dist/src/core/toolchain-preflight.js +28 -31
  397. package/dist/src/core/tree-guard.js +12 -2
  398. package/dist/src/core/tree-store.d.ts +41 -27
  399. package/dist/src/core/tree-store.js +63 -42
  400. package/dist/src/core/typecheck-shim.d.ts +23 -24
  401. package/dist/src/core/typecheck-shim.js +23 -24
  402. package/dist/src/core/typecheck.js +8 -8
  403. package/dist/src/core/wire-destroy.d.ts +3 -3
  404. package/dist/src/core/wire-destroy.js +7 -15
  405. package/dist/src/core/wire-dom-fragment.d.ts +9 -17
  406. package/dist/src/core/wire-dom-fragment.js +11 -44
  407. package/dist/src/core/wire-init.d.ts +2 -3
  408. package/dist/src/core/wire-init.js +8 -19
  409. package/dist/src/core/wire-subscript.d.ts +2 -3
  410. package/dist/src/core/wire-subscript.js +4 -13
  411. package/dist/src/core/wire-utils.d.ts +7 -8
  412. package/dist/src/core/wire-utils.js +7 -8
  413. package/dist/src/core/xpcshell-appdir.d.ts +38 -45
  414. package/dist/src/core/xpcshell-appdir.js +38 -45
  415. package/dist/src/errors/base.d.ts +37 -16
  416. package/dist/src/errors/base.js +37 -16
  417. package/dist/src/errors/build.d.ts +13 -1
  418. package/dist/src/errors/build.js +14 -2
  419. package/dist/src/errors/codes.d.ts +16 -0
  420. package/dist/src/errors/codes.js +16 -0
  421. package/dist/src/errors/furnace.d.ts +4 -4
  422. package/dist/src/errors/git.d.ts +6 -10
  423. package/dist/src/errors/git.js +6 -10
  424. package/dist/src/errors/patch.d.ts +7 -7
  425. package/dist/src/errors/patch.js +7 -7
  426. package/dist/src/errors/rebase.d.ts +4 -4
  427. package/dist/src/errors/rebase.js +4 -4
  428. package/dist/src/index.d.ts +7 -1
  429. package/dist/src/index.js +5 -0
  430. package/dist/src/types/commands/index.d.ts +2 -2
  431. package/dist/src/types/commands/options.d.ts +88 -70
  432. package/dist/src/types/commands/patches.d.ts +24 -34
  433. package/dist/src/types/commands/project.d.ts +5 -34
  434. package/dist/src/types/config.d.ts +25 -23
  435. package/dist/src/types/config.js +6 -1
  436. package/dist/src/types/furnace.d.ts +37 -13
  437. package/dist/src/types/furnace.js +19 -1
  438. package/dist/src/types/index.d.ts +3 -3
  439. package/dist/src/utils/build-info.d.ts +7 -8
  440. package/dist/src/utils/build-info.js +12 -11
  441. package/dist/src/utils/errors.d.ts +6 -8
  442. package/dist/src/utils/errors.js +6 -8
  443. package/dist/src/utils/logger.d.ts +27 -10
  444. package/dist/src/utils/logger.js +28 -16
  445. package/dist/src/utils/machine-output.d.ts +12 -0
  446. package/dist/src/utils/machine-output.js +33 -0
  447. package/dist/src/utils/options.d.ts +31 -14
  448. package/dist/src/utils/options.js +86 -30
  449. package/dist/src/utils/paths.d.ts +10 -8
  450. package/dist/src/utils/paths.js +10 -8
  451. package/dist/src/utils/platform.d.ts +0 -25
  452. package/dist/src/utils/platform.js +1 -42
  453. package/dist/src/utils/process-group.d.ts +9 -4
  454. package/dist/src/utils/process-group.js +19 -5
  455. package/dist/src/utils/process.d.ts +42 -7
  456. package/dist/src/utils/process.js +44 -17
  457. package/dist/src/utils/ps-duration.d.ts +31 -0
  458. package/dist/src/utils/ps-duration.js +70 -0
  459. package/dist/src/utils/regex.d.ts +9 -10
  460. package/dist/src/utils/regex.js +9 -10
  461. package/dist/src/utils/validation.d.ts +58 -28
  462. package/dist/src/utils/validation.js +60 -33
  463. package/package.json +2 -2
  464. package/dist/src/commands/doctor/post-rebase-audit.d.ts +0 -2
  465. package/dist/src/commands/doctor-furnace-manifest-sync.d.ts +0 -18
  466. package/dist/src/core/manifest-helpers.d.ts +0 -38
  467. package/dist/src/core/manifest-helpers.js +0 -120
  468. /package/dist/src/core/{lint-projection.d.ts → patch-lint-projection.d.ts} +0 -0
  469. /package/dist/src/core/{lint-projection.js → patch-lint-projection.js} +0 -0
  470. /package/dist/src/core/{register-test-manifest.d.ts → register-browser-test.d.ts} +0 -0
@@ -5,83 +5,18 @@
5
5
  import { join } from 'node:path';
6
6
  import { GeneralError } from '../errors/base.js';
7
7
  import { pathExists, readText, writeText } from '../utils/fs.js';
8
- import { escapeRegex } from '../utils/regex.js';
9
- import { findAlphabeticalPosition, findAlphabeticalTokenPosition } from './manifest-helpers.js';
10
- import { tokenizeJarMn } from './manifest-tokenizers.js';
11
- import { withParserFallback } from './parser-fallback.js';
8
+ import { insertJarMnEntry } from './moz-manifest-helpers.js';
12
9
  /**
13
10
  * Tokenizer-based implementation for browser content registration.
14
11
  */
15
12
  function registerBrowserContentTokenized(content, fileName, entry, after) {
16
- const lines = content.split('\n');
17
- const tokens = tokenizeJarMn(lines);
18
- let afterFallback = false;
19
- let insertIndex;
20
- let previousEntry;
21
- if (after) {
22
- const afterPattern = new RegExp(`(?:^|/)${escapeRegex(after)}(?:\\s|\\)|$)`);
23
- const afterToken = tokens.find((t) => afterPattern.test(t.raw));
24
- if (afterToken) {
25
- insertIndex = afterToken.lineIndex + 1;
26
- previousEntry = afterToken.raw.trim();
27
- }
28
- else {
29
- afterFallback = true;
30
- ({ insertIndex, previousEntry } = findAlphabeticalTokenPosition(tokens, /content\/browser\/([^\s]+)/, fileName));
31
- }
32
- }
33
- else {
34
- ({ insertIndex, previousEntry } = findAlphabeticalTokenPosition(tokens, /content\/browser\/([^\s]+)/, fileName));
35
- }
36
- if (insertIndex === -1) {
37
- throw new GeneralError('Could not find content/browser/ section in browser/base/jar.mn');
38
- }
39
- lines.splice(insertIndex, 0, entry);
40
- return { result: lines.join('\n'), previousEntry, afterFallback };
41
- }
42
- /**
43
- * Legacy line-based implementation preserved as fallback.
44
- */
45
- function legacyRegisterBrowserContent(content, fileName, entry, after) {
46
- const lines = content.split('\n');
47
- let afterFallback = false;
48
- const extractKey = (line) => {
49
- const match = /content\/browser\/([^\s]+)/.exec(line);
50
- return match?.[1];
51
- };
52
- let sectionStart = -1;
53
- let sectionEnd = lines.length;
54
- for (let i = 0; i < lines.length; i++) {
55
- const line = lines[i];
56
- if (line === undefined)
57
- continue;
58
- if (/^\s+content\/browser\//.test(line)) {
59
- if (sectionStart === -1)
60
- sectionStart = i;
61
- sectionEnd = i + 1;
62
- }
63
- }
64
- if (sectionStart === -1) {
65
- throw new GeneralError('Could not find content/browser/ section in browser/base/jar.mn');
66
- }
67
- let insertIndex;
68
- let previousEntry;
69
- if (after) {
70
- const afterLineIdx = lines.findIndex((l) => l.includes(after));
71
- if (afterLineIdx !== -1) {
72
- insertIndex = afterLineIdx + 1;
73
- previousEntry = lines[afterLineIdx]?.trim();
74
- }
75
- else {
76
- afterFallback = true;
77
- ({ insertIndex, previousEntry } = findAlphabeticalPosition(lines, sectionStart, sectionEnd, fileName, extractKey));
78
- }
79
- }
80
- else {
81
- ({ insertIndex, previousEntry } = findAlphabeticalPosition(lines, sectionStart, sectionEnd, fileName, extractKey));
82
- }
83
- lines.splice(insertIndex, 0, entry);
84
- return { result: lines.join('\n'), previousEntry, afterFallback };
13
+ const { result, previousEntry, afterFallback } = insertJarMnEntry(content, entry, {
14
+ sortPattern: /content\/browser\/([^\s]+)/,
15
+ sortKey: fileName,
16
+ missingSectionMessage: 'Could not find content/browser/ section in browser/base/jar.mn',
17
+ after,
18
+ });
19
+ return { result, previousEntry, afterFallback };
85
20
  }
86
21
  /**
87
22
  * Registers a JS/content file in browser/base/jar.mn.
@@ -102,7 +37,7 @@ export async function registerBrowserContent(engineDir, fileName, after, sourceP
102
37
  if (content.includes(`content/browser/${fileName}`)) {
103
38
  return { manifest, entry, skipped: true };
104
39
  }
105
- const { value } = withParserFallback(() => registerBrowserContentTokenized(content, fileName, entry, after), () => legacyRegisterBrowserContent(content, fileName, entry, after), manifest);
40
+ const value = registerBrowserContentTokenized(content, fileName, entry, after);
106
41
  if (!dryRun) {
107
42
  await writeText(manifestPath, value.result);
108
43
  }
@@ -5,51 +5,16 @@
5
5
  import { join } from 'node:path';
6
6
  import { GeneralError } from '../errors/base.js';
7
7
  import { pathExists, readText, writeText } from '../utils/fs.js';
8
- import { findAlphabeticalMozBuildPosition, findAlphabeticalPosition } from './manifest-helpers.js';
9
- import { tokenizeMozBuildList } from './manifest-tokenizers.js';
10
- import { withParserFallback } from './parser-fallback.js';
8
+ import { insertMozBuildListEntry } from './moz-manifest-helpers.js';
11
9
  /**
12
10
  * Tokenizer-based implementation for test manifest registration.
13
11
  */
14
12
  function registerTestManifestTokenized(content, testDir, entry) {
15
- const lines = content.split('\n');
16
- const listResult = tokenizeMozBuildList(lines, /BROWSER_CHROME_MANIFESTS/);
17
- if (!listResult) {
18
- throw new GeneralError('Could not find BROWSER_CHROME_MANIFESTS in browser/base/moz.build');
19
- }
20
- const { insertIndex, previousEntry } = findAlphabeticalMozBuildPosition(listResult.tokens, `content/test/${testDir}/browser.toml`);
21
- lines.splice(insertIndex, 0, entry);
22
- return { result: lines.join('\n'), previousEntry };
23
- }
24
- /**
25
- * Legacy line-based implementation preserved as fallback.
26
- */
27
- function legacyRegisterTestManifest(content, testDir, entry) {
28
- const lines = content.split('\n');
29
- const extractKey = (line) => {
30
- // Nested manifests (`content/test/a/b/browser.toml`) are supported —
31
- // capture the whole directory chain, not just one segment.
32
- const match = /"content\/test\/(.+)\/browser\.toml"/.exec(line);
33
- return match?.[1];
34
- };
35
- let sectionStart = -1;
36
- let sectionEnd = lines.length;
37
- for (let i = 0; i < lines.length; i++) {
38
- const line = lines[i];
39
- if (line === undefined)
40
- continue;
41
- if (/^\s+"content\/test\/.*browser\.toml"/.test(line)) {
42
- if (sectionStart === -1)
43
- sectionStart = i;
44
- sectionEnd = i + 1;
45
- }
46
- }
47
- if (sectionStart === -1) {
48
- throw new GeneralError('Could not find test manifest section in browser/base/moz.build');
49
- }
50
- const { insertIndex, previousEntry } = findAlphabeticalPosition(lines, sectionStart, sectionEnd, testDir, extractKey);
51
- lines.splice(insertIndex, 0, entry);
52
- return { result: lines.join('\n'), previousEntry };
13
+ return insertMozBuildListEntry(content, entry, {
14
+ listPattern: /BROWSER_CHROME_MANIFESTS/,
15
+ sortKey: `content/test/${testDir}/browser.toml`,
16
+ missingListMessage: 'Could not find BROWSER_CHROME_MANIFESTS in browser/base/moz.build',
17
+ });
53
18
  }
54
19
  /**
55
20
  * Registers a test manifest (browser.toml) in browser/base/moz.build.
@@ -69,7 +34,7 @@ export async function registerTestManifest(engineDir, testDir, dryRun = false) {
69
34
  if (content.includes(`content/test/${testDir}/browser.toml`)) {
70
35
  return { manifest, entry, skipped: true };
71
36
  }
72
- const { value } = withParserFallback(() => registerTestManifestTokenized(content, testDir, entry), () => legacyRegisterTestManifest(content, testDir, entry), manifest);
37
+ const value = registerTestManifestTokenized(content, testDir, entry);
73
38
  if (!dryRun) {
74
39
  await writeText(manifestPath, value.result);
75
40
  }
@@ -5,50 +5,17 @@
5
5
  import { join } from 'node:path';
6
6
  import { GeneralError } from '../errors/base.js';
7
7
  import { pathExists, readText, writeText } from '../utils/fs.js';
8
- import { findAlphabeticalMozBuildPosition, findAlphabeticalPosition } from './manifest-helpers.js';
9
- import { tokenizeMozBuildList } from './manifest-tokenizers.js';
10
- import { withParserFallback } from './parser-fallback.js';
8
+ import { insertMozBuildListEntry } from './moz-manifest-helpers.js';
11
9
  import { scaffoldModuleMozBuild } from './register-scaffold.js';
12
10
  /**
13
11
  * Tokenizer-based implementation for module registration.
14
12
  */
15
13
  function registerFireForgeModuleTokenized(content, fileName, entry) {
16
- const lines = content.split('\n');
17
- const listResult = tokenizeMozBuildList(lines, /EXTRA_JS_MODULES/);
18
- if (!listResult) {
19
- throw new GeneralError('Could not find EXTRA_JS_MODULES in moz.build');
20
- }
21
- const { insertIndex, previousEntry } = findAlphabeticalMozBuildPosition(listResult.tokens, fileName);
22
- lines.splice(insertIndex, 0, entry);
23
- return { result: lines.join('\n'), previousEntry };
24
- }
25
- /**
26
- * Legacy line-based implementation preserved as fallback.
27
- */
28
- function legacyRegisterFireForgeModule(content, fileName, entry, moduleDir) {
29
- const lines = content.split('\n');
30
- const extractKey = (line) => {
31
- const match = /^\s+"([^"]+\.sys\.mjs)"/.exec(line);
32
- return match?.[1];
33
- };
34
- let sectionStart = -1;
35
- let sectionEnd = lines.length;
36
- for (let i = 0; i < lines.length; i++) {
37
- const line = lines[i];
38
- if (line === undefined)
39
- continue;
40
- if (/^\s+"[^"]+\.sys\.mjs"/.test(line)) {
41
- if (sectionStart === -1)
42
- sectionStart = i;
43
- sectionEnd = i + 1;
44
- }
45
- }
46
- if (sectionStart === -1) {
47
- throw new GeneralError(`Could not find module list section in ${moduleDir}/moz.build`);
48
- }
49
- const { insertIndex, previousEntry } = findAlphabeticalPosition(lines, sectionStart, sectionEnd, fileName, extractKey);
50
- lines.splice(insertIndex, 0, entry);
51
- return { result: lines.join('\n'), previousEntry };
14
+ return insertMozBuildListEntry(content, entry, {
15
+ listPattern: /EXTRA_JS_MODULES/,
16
+ sortKey: fileName,
17
+ missingListMessage: 'Could not find EXTRA_JS_MODULES in moz.build',
18
+ });
52
19
  }
53
20
  /**
54
21
  * Registers a module in browser/modules/{binaryName}/moz.build.
@@ -61,9 +28,9 @@ export async function registerFireForgeModule(engineDir, fileName, moduleDir, dr
61
28
  const manifestPath = join(engineDir, manifest);
62
29
  if (!(await pathExists(manifestPath))) {
63
30
  if (createManifest) {
64
- // 0.34.0 field report: registering a module under a directory with
65
- // no moz.build failed with "Manifest not found". Scaffold the
66
- // directory manifest and wire the parent DIRS chain.
31
+ // Registering a module under a directory with no moz.build otherwise
32
+ // fails with "Manifest not found". Scaffold the directory manifest and
33
+ // wire the parent DIRS chain.
67
34
  const scaffoldActions = await scaffoldModuleMozBuild(engineDir, moduleDir, fileName, dryRun);
68
35
  return {
69
36
  manifest,
@@ -80,7 +47,7 @@ export async function registerFireForgeModule(engineDir, fileName, moduleDir, dr
80
47
  if (content.includes(`"${fileName}"`)) {
81
48
  return { manifest, entry, skipped: true };
82
49
  }
83
- const { value } = withParserFallback(() => registerFireForgeModuleTokenized(content, fileName, entry), () => legacyRegisterFireForgeModule(content, fileName, entry, moduleDir), manifest);
50
+ const value = registerFireForgeModuleTokenized(content, fileName, entry);
84
51
  if (!dryRun) {
85
52
  await writeText(manifestPath, value.result);
86
53
  }
@@ -1,13 +1,13 @@
1
1
  /**
2
- * Manifest scaffolding for `fireforge register --create-manifest`
3
- * (0.34.0 field report): registering a module under a directory with no
4
- * moz.build used to fail with "Manifest not found" because `register`
5
- * only inserts into EXISTING manifests. This module owns the two
6
- * scaffolding primitives:
2
+ * Manifest scaffolding for `fireforge register --create-manifest`.
7
3
  *
8
- * - creating a directory `moz.build` (license header + the requested
9
- * list directive) and wiring the parent chain's `DIRS` entries up to
10
- * the nearest existing moz.build;
4
+ * `register` only inserts into EXISTING manifests, so registering a module
5
+ * under a directory with no moz.build fails with "Manifest not found". This
6
+ * module owns the two scaffolding primitives:
7
+ *
8
+ * - creating a directory `moz.build` (license header + the requested list
9
+ * directive) and wiring the parent chain's `DIRS` entries up to the
10
+ * nearest existing moz.build;
11
11
  * - wiring an `XPCSHELL_TESTS_MANIFESTS` entry for a (possibly freshly
12
12
  * created) `xpcshell.toml` into the nearest existing moz.build.
13
13
  *
@@ -1,14 +1,14 @@
1
1
  // SPDX-License-Identifier: EUPL-1.2
2
2
  /**
3
- * Manifest scaffolding for `fireforge register --create-manifest`
4
- * (0.34.0 field report): registering a module under a directory with no
5
- * moz.build used to fail with "Manifest not found" because `register`
6
- * only inserts into EXISTING manifests. This module owns the two
7
- * scaffolding primitives:
3
+ * Manifest scaffolding for `fireforge register --create-manifest`.
8
4
  *
9
- * - creating a directory `moz.build` (license header + the requested
10
- * list directive) and wiring the parent chain's `DIRS` entries up to
11
- * the nearest existing moz.build;
5
+ * `register` only inserts into EXISTING manifests, so registering a module
6
+ * under a directory with no moz.build fails with "Manifest not found". This
7
+ * module owns the two scaffolding primitives:
8
+ *
9
+ * - creating a directory `moz.build` (license header + the requested list
10
+ * directive) and wiring the parent chain's `DIRS` entries up to the
11
+ * nearest existing moz.build;
12
12
  * - wiring an `XPCSHELL_TESTS_MANIFESTS` entry for a (possibly freshly
13
13
  * created) `xpcshell.toml` into the nearest existing moz.build.
14
14
  *
@@ -20,8 +20,8 @@ import { dirname, join } from 'node:path';
20
20
  import { GeneralError } from '../errors/base.js';
21
21
  import { pathExists, readText, writeText } from '../utils/fs.js';
22
22
  import { getLicenseHeader } from './license-headers.js';
23
- import { findAlphabeticalMozBuildPosition } from './manifest-helpers.js';
24
- import { tokenizeMozBuildList } from './manifest-tokenizers.js';
23
+ import { findAlphabeticalMozBuildPosition } from './moz-manifest-helpers.js';
24
+ import { tokenizeMozBuildList } from './moz-manifest-tokenizers.js';
25
25
  /**
26
26
  * moz.build files use Firefox's canonical MPL-2.0 hash-comment header
27
27
  * regardless of the fork's own project license — they live in the engine
@@ -3,19 +3,16 @@
3
3
  */
4
4
  import type { RegisterResult } from './register-result.js';
5
5
  /**
6
- * Measures the column at which the `(source)` parenthesis opens in
7
- * adjacent `skin/classic/browser/<x>.css (...)` entries inside an
8
- * existing jar.inc.mn body, and returns the maximum so a newly inserted
9
- * entry can align its source column to match.
6
+ * Measures the column at which the `(source)` parenthesis opens in adjacent
7
+ * `skin/classic/browser/<x>.css (...)` entries inside an existing
8
+ * jar.inc.mn body, and returns the maximum so a newly inserted entry can
9
+ * align its source column to match.
10
10
  *
11
- * 2026-04-26 eval Finding 3: pre-fix `registerSharedCSS` always emitted
12
- * a four-space gap between the target path and the parenthesis,
13
- * regardless of how the rest of the file was aligned. Adjacent Firefox
14
- * entries are typically padded to a wider column, so a freshly
15
- * registered file landed at the wrong column and produced avoidable
16
- * formatting churn. Returns `undefined` when no existing entries
17
- * provide an alignment signal — callers fall back to the four-space
18
- * default in that case.
11
+ * A fixed four-space gap regardless of the surrounding alignment lands a
12
+ * freshly registered file at the wrong column and produces avoidable
13
+ * formatting churn, since adjacent Firefox entries are typically padded to a
14
+ * wider column. Returns `undefined` when no existing entries provide an
15
+ * alignment signal — callers fall back to the four-space default.
19
16
  */
20
17
  export declare function measureSourceColumn(content: string): number | undefined;
21
18
  /**
@@ -5,101 +5,31 @@
5
5
  import { basename, join } from 'node:path';
6
6
  import { GeneralError } from '../errors/base.js';
7
7
  import { pathExists, readText, writeText } from '../utils/fs.js';
8
- import { escapeRegex } from '../utils/regex.js';
9
- import { findAlphabeticalPosition, findAlphabeticalTokenPosition } from './manifest-helpers.js';
10
- import { tokenizeJarMn } from './manifest-tokenizers.js';
11
- import { withParserFallback } from './parser-fallback.js';
8
+ import { insertJarMnEntry } from './moz-manifest-helpers.js';
12
9
  /**
13
10
  * Tokenizer-based implementation for shared CSS registration.
14
11
  */
15
12
  function registerSharedCSSTokenized(content, name, entry, after) {
16
- const lines = content.split('\n');
17
- const tokens = tokenizeJarMn(lines);
18
- let afterFallback = false;
19
- let insertIndex;
20
- let previousEntry;
21
- if (after) {
22
- const afterPattern = new RegExp(`(?:^|/)${escapeRegex(after)}(?:\\s|\\)|$)`);
23
- const afterToken = tokens.find((t) => afterPattern.test(t.raw));
24
- if (afterToken) {
25
- insertIndex = afterToken.lineIndex + 1;
26
- previousEntry = afterToken.raw.trim();
27
- }
28
- else {
29
- afterFallback = true;
30
- ({ insertIndex, previousEntry } = findAlphabeticalTokenPosition(tokens, /skin\/classic\/browser\/([^.]+)\.css/, name));
31
- }
32
- }
33
- else {
34
- ({ insertIndex, previousEntry } = findAlphabeticalTokenPosition(tokens, /skin\/classic\/browser\/([^.]+)\.css/, name));
35
- }
36
- if (insertIndex === -1) {
37
- throw new GeneralError('Could not find skin/classic/browser/ section in jar.inc.mn');
38
- }
39
- lines.splice(insertIndex, 0, entry);
40
- return { result: lines.join('\n'), insertIndex, previousEntry, afterFallback };
41
- }
42
- /**
43
- * Legacy line-based implementation preserved as fallback.
44
- */
45
- function legacyRegisterSharedCSS(content, name, entry, after) {
46
- const lines = content.split('\n');
47
- let afterFallback = false;
48
- const extractKey = (line) => {
49
- const match = /skin\/classic\/browser\/([^.]+)\.css/.exec(line);
50
- return match?.[1];
51
- };
52
- let insertIndex;
53
- let previousEntry;
54
- // Find skin/classic/browser/ section boundaries
55
- let sectionStart = -1;
56
- let sectionEnd = lines.length;
57
- for (let i = 0; i < lines.length; i++) {
58
- const line = lines[i];
59
- if (line === undefined)
60
- continue;
61
- if (/skin\/classic\/browser\//.test(line)) {
62
- if (sectionStart === -1)
63
- sectionStart = i;
64
- sectionEnd = i + 1;
65
- }
66
- }
67
- if (sectionStart === -1) {
68
- throw new GeneralError('Could not find skin/classic/browser/ section in jar.inc.mn');
69
- }
70
- if (after) {
71
- const afterLineIdx = lines.findIndex((l) => l.includes(after));
72
- if (afterLineIdx !== -1) {
73
- insertIndex = afterLineIdx + 1;
74
- previousEntry = lines[afterLineIdx]?.trim();
75
- }
76
- else {
77
- afterFallback = true;
78
- ({ insertIndex, previousEntry } = findAlphabeticalPosition(lines, sectionStart, sectionEnd, name, extractKey));
79
- }
80
- }
81
- else {
82
- ({ insertIndex, previousEntry } = findAlphabeticalPosition(lines, sectionStart, sectionEnd, name, extractKey));
83
- }
84
- lines.splice(insertIndex, 0, entry);
85
- return { result: lines.join('\n'), previousEntry, afterFallback };
13
+ return insertJarMnEntry(content, entry, {
14
+ sortPattern: /skin\/classic\/browser\/([^.]+)\.css/,
15
+ sortKey: name,
16
+ missingSectionMessage: 'Could not find skin/classic/browser/ section in jar.inc.mn',
17
+ after,
18
+ });
86
19
  }
87
20
  /** Minimum gap between the target path and the source parenthesis. */
88
21
  const MIN_SOURCE_GAP = 4;
89
22
  /**
90
- * Measures the column at which the `(source)` parenthesis opens in
91
- * adjacent `skin/classic/browser/<x>.css (...)` entries inside an
92
- * existing jar.inc.mn body, and returns the maximum so a newly inserted
93
- * entry can align its source column to match.
23
+ * Measures the column at which the `(source)` parenthesis opens in adjacent
24
+ * `skin/classic/browser/<x>.css (...)` entries inside an existing
25
+ * jar.inc.mn body, and returns the maximum so a newly inserted entry can
26
+ * align its source column to match.
94
27
  *
95
- * 2026-04-26 eval Finding 3: pre-fix `registerSharedCSS` always emitted
96
- * a four-space gap between the target path and the parenthesis,
97
- * regardless of how the rest of the file was aligned. Adjacent Firefox
98
- * entries are typically padded to a wider column, so a freshly
99
- * registered file landed at the wrong column and produced avoidable
100
- * formatting churn. Returns `undefined` when no existing entries
101
- * provide an alignment signal — callers fall back to the four-space
102
- * default in that case.
28
+ * A fixed four-space gap regardless of the surrounding alignment lands a
29
+ * freshly registered file at the wrong column and produces avoidable
30
+ * formatting churn, since adjacent Firefox entries are typically padded to a
31
+ * wider column. Returns `undefined` when no existing entries provide an
32
+ * alignment signal — callers fall back to the four-space default.
103
33
  */
104
34
  export function measureSourceColumn(content) {
105
35
  const lines = content.split('\n');
@@ -167,7 +97,7 @@ export async function registerSharedCSS(engineDir, fileName, after, dryRun = fal
167
97
  content.includes(`content/browser/${name}.css`)) {
168
98
  return { manifest, entry, skipped: true };
169
99
  }
170
- const { value } = withParserFallback(() => registerSharedCSSTokenized(content, name, entry, after), () => legacyRegisterSharedCSS(content, name, entry, after), manifest);
100
+ const value = registerSharedCSSTokenized(content, name, entry, after);
171
101
  if (!dryRun) {
172
102
  await writeText(manifestPath, value.result);
173
103
  }
@@ -1,11 +1,10 @@
1
1
  /**
2
- * xpcshell test-file registration (0.34.0 field report): xpcshell test
3
- * files (e.g. `<module-dir>/test/unit/test_*.js`) were rejected by
4
- * `fireforge register` as "Unknown file pattern". This writer inserts the
5
- * `["test_*.js"]` section into the directory's `xpcshell.toml`
6
- * (alphabetically, idempotently) and — with `--create-manifest` — creates
7
- * the manifest and wires `XPCSHELL_TESTS_MANIFESTS` into the nearest
8
- * moz.build.
2
+ * xpcshell test-file registration. Without it, xpcshell test files (e.g.
3
+ * `<module-dir>/test/unit/test_*.js`) are rejected by `fireforge register`
4
+ * as "Unknown file pattern". This writer inserts the `["test_*.js"]` section
5
+ * into the directory's `xpcshell.toml` (alphabetically, idempotently) and —
6
+ * with `--create-manifest` — creates the manifest and wires
7
+ * `XPCSHELL_TESTS_MANIFESTS` into the nearest moz.build.
9
8
  */
10
9
  import type { RegisterResult } from './register-result.js';
11
10
  /**
@@ -1,17 +1,16 @@
1
1
  // SPDX-License-Identifier: EUPL-1.2
2
2
  /**
3
- * xpcshell test-file registration (0.34.0 field report): xpcshell test
4
- * files (e.g. `<module-dir>/test/unit/test_*.js`) were rejected by
5
- * `fireforge register` as "Unknown file pattern". This writer inserts the
6
- * `["test_*.js"]` section into the directory's `xpcshell.toml`
7
- * (alphabetically, idempotently) and — with `--create-manifest` — creates
8
- * the manifest and wires `XPCSHELL_TESTS_MANIFESTS` into the nearest
9
- * moz.build.
3
+ * xpcshell test-file registration. Without it, xpcshell test files (e.g.
4
+ * `<module-dir>/test/unit/test_*.js`) are rejected by `fireforge register`
5
+ * as "Unknown file pattern". This writer inserts the `["test_*.js"]` section
6
+ * into the directory's `xpcshell.toml` (alphabetically, idempotently) and —
7
+ * with `--create-manifest` — creates the manifest and wires
8
+ * `XPCSHELL_TESTS_MANIFESTS` into the nearest moz.build.
10
9
  */
11
10
  import { join } from 'node:path';
12
11
  import { GeneralError } from '../errors/base.js';
13
12
  import { pathExists, readText, writeText } from '../utils/fs.js';
14
- import { mozbuildSortCompare } from './manifest-helpers.js';
13
+ import { mozbuildSortCompare } from './moz-manifest-helpers.js';
15
14
  import { ensureXpcshellManifestWiring } from './register-scaffold.js';
16
15
  function manifestMissingError(manifestRel) {
17
16
  return new GeneralError(`Manifest not found: ${manifestRel}. ` +
@@ -8,11 +8,19 @@
8
8
  * template generator assume the value is safe to interpolate verbatim.
9
9
  */
10
10
  /**
11
- * Characters that must not appear in `sharedFtl`:
12
- * - Backticks close the MJS template literal the scaffold writes.
11
+ * Characters that must not appear in `sharedFtl`.
12
+ *
13
+ * A POLICY rule about what a sensible FTL path looks like, not the safety
14
+ * boundary for the generated `.mjs`: the scaffold escapes the value at its
15
+ * sink with `JSON.stringify` (`commands/furnace/create-templates.ts`), which
16
+ * is what actually makes interpolation safe and what covers the two inputs
17
+ * this rule never catches — a `"` and a raw newline.
18
+ *
19
+ * Kept because each remains a real sign of a malformed path:
13
20
  * - `\` is a path-escape we do not want to interpret.
14
- * - `${` opens a template expression and turns the FTL path into
15
- * executable code.
21
+ * - Backticks and `${` are inert in the current double-quoted sink, but a
22
+ * template-literal sink is one refactor away and they are not valid in a
23
+ * chrome:// FTL path regardless.
16
24
  */
17
25
  const UNSAFE_CHARS = /[`\\]|\$\{/;
18
26
  /**
@@ -2,3 +2,48 @@
2
2
  export declare function withStateFileLock<T>(statePath: string, operation: () => Promise<T>): Promise<T>;
3
3
  /** Renames a state file out of the way while preserving it for later inspection. */
4
4
  export declare function quarantineStateFile(statePath: string, reason?: string): Promise<string | undefined>;
5
+ /**
6
+ * Outcome of a version check on a persisted FireForge document.
7
+ *
8
+ * The distinction that matters is `newer` vs `corrupt`. A document written
9
+ * by a NEWER FireForge is not damaged — the operator simply needs to upgrade
10
+ * — but a check that collapses the two offers destructive remedies. The
11
+ * sharpest case is the tree marker, whose `schemaVersion` check inside a
12
+ * boolean type guard makes a `schemaVersion: 2` marker read as "missing or
13
+ * mistypes a required field"; `tree-guard.ts` is default-deny on corrupt, so
14
+ * a newer FireForge would lock the operator out of every mutating command
15
+ * inside that tree.
16
+ *
17
+ * `furnace.json` is the pattern the rest should follow: it refuses a newer
18
+ * version by name and tells the operator to upgrade (`migrateFurnaceConfig`
19
+ * in `furnace-config.ts`).
20
+ */
21
+ export type DocumentVersionCheck = {
22
+ kind: 'current';
23
+ } | {
24
+ kind: 'older';
25
+ found: number;
26
+ } | {
27
+ kind: 'newer';
28
+ found: number;
29
+ } | {
30
+ kind: 'malformed';
31
+ };
32
+ /**
33
+ * Classifies a persisted document's `version`/`schemaVersion` field.
34
+ *
35
+ * @param raw - The parsed document
36
+ * @param field - Version field name, e.g. `schemaVersion`
37
+ * @param supported - Version this build writes and understands
38
+ * @returns Whether the document is current, older, newer, or malformed
39
+ */
40
+ export declare function checkDocumentVersion(raw: unknown, field: string, supported: number): DocumentVersionCheck;
41
+ /**
42
+ * The refusal shown for a document this build is too old to read.
43
+ *
44
+ * @param label - Operator-facing document name, e.g. `tree marker`
45
+ * @param found - Version found on disk
46
+ * @param supported - Version this build understands
47
+ * @returns A message naming both versions and the remedy
48
+ */
49
+ export declare function describeNewerDocument(label: string, found: number, supported: number): string;
@@ -22,3 +22,37 @@ export async function quarantineStateFile(statePath, reason = 'corrupt') {
22
22
  await rename(statePath, quarantinedPath);
23
23
  return basename(quarantinedPath);
24
24
  }
25
+ /**
26
+ * Classifies a persisted document's `version`/`schemaVersion` field.
27
+ *
28
+ * @param raw - The parsed document
29
+ * @param field - Version field name, e.g. `schemaVersion`
30
+ * @param supported - Version this build writes and understands
31
+ * @returns Whether the document is current, older, newer, or malformed
32
+ */
33
+ export function checkDocumentVersion(raw, field, supported) {
34
+ if (typeof raw !== 'object' || raw === null)
35
+ return { kind: 'malformed' };
36
+ const found = raw[field];
37
+ if (typeof found !== 'number' || !Number.isInteger(found) || found < 1) {
38
+ return { kind: 'malformed' };
39
+ }
40
+ if (found > supported)
41
+ return { kind: 'newer', found };
42
+ if (found < supported)
43
+ return { kind: 'older', found };
44
+ return { kind: 'current' };
45
+ }
46
+ /**
47
+ * The refusal shown for a document this build is too old to read.
48
+ *
49
+ * @param label - Operator-facing document name, e.g. `tree marker`
50
+ * @param found - Version found on disk
51
+ * @param supported - Version this build understands
52
+ * @returns A message naming both versions and the remedy
53
+ */
54
+ export function describeNewerDocument(label, found, supported) {
55
+ return (`the ${label} was written by a newer FireForge (schema version ${found}; ` +
56
+ `this build understands ${supported}). Upgrade FireForge to read it — the file is ` +
57
+ 'not damaged, so do not delete it.');
58
+ }