@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
@@ -1,11 +1,12 @@
1
1
  // SPDX-License-Identifier: EUPL-1.2
2
2
  import { watch as fsWatch } from 'node:fs';
3
- import { getProjectPaths, loadConfig } from '../../core/config.js';
3
+ import { loadConfig } from '../../core/config.js';
4
4
  import { applyAllComponents, computeComponentChecksums } from '../../core/furnace-apply.js';
5
5
  import { logApplyResult } from '../../core/furnace-apply-output.js';
6
- import { furnaceConfigExists, getFurnacePaths, loadFurnaceConfig, } from '../../core/furnace-config.js';
6
+ import { getFurnacePaths } from '../../core/furnace-config.js';
7
7
  import { isComponentSourceFile } from '../../core/furnace-constants.js';
8
8
  import { runFurnaceMutation } from '../../core/furnace-operation.js';
9
+ import { assertFurnaceReady } from '../../core/furnace-precondition.js';
9
10
  import { getPersistableAppliedEntry, persistSingleComponentState, shouldPersistSingleComponentState, } from '../../core/furnace-state-persist.js';
10
11
  import { countEntriesWithBlockingStepErrors } from '../../core/furnace-step-errors.js';
11
12
  import { findOverrideBaseVersionDrift, formatOverrideBaseVersionDriftError, formatOverrideBaseVersionDriftWarning, } from '../../core/furnace-version-drift.js';
@@ -74,11 +75,10 @@ function classifyWatchApplyError(err) {
74
75
  async function runWatchLoop(projectRoot) {
75
76
  const furnacePaths = getFurnacePaths(projectRoot);
76
77
  // Both categories are eligible targets. The set is fixed; only existence
77
- // varies over time — a component dir created AFTER watch started (e.g.
78
- // the user runs `furnace create` in another terminal) must be picked up
79
- // without restarting watch. The prior one-shot `pathExists` check at
80
- // startup captured only the dirs that existed then, leaving any later
81
- // creation invisible.
78
+ // varies over time — a component dir created AFTER watch started (the user
79
+ // running `furnace create` in another terminal) must be picked up without
80
+ // restarting watch. A one-shot `pathExists` check at startup captures only
81
+ // the dirs that existed then, leaving any later creation invisible.
82
82
  const candidateDirs = [furnacePaths.overridesDir, furnacePaths.customDir];
83
83
  const watchDirs = [];
84
84
  const watchers = new Map();
@@ -253,16 +253,7 @@ async function runWatchLoop(projectRoot) {
253
253
  */
254
254
  export async function furnaceApplyCommand(projectRoot, name, options = {}) {
255
255
  intro(name ? `Furnace Apply (${name})` : 'Furnace Apply');
256
- // Verify engine exists
257
- const paths = getProjectPaths(projectRoot);
258
- if (!(await pathExists(paths.engine))) {
259
- throw new FurnaceError('Engine directory not found. Run "fireforge download" first.');
260
- }
261
- // Load furnace config
262
- if (!(await furnaceConfigExists(projectRoot))) {
263
- throw new FurnaceError('No furnace.json found. Run "fireforge furnace create" or "fireforge furnace override" to get started.');
264
- }
265
- const config = await loadFurnaceConfig(projectRoot);
256
+ const { config } = await assertFurnaceReady(projectRoot);
266
257
  const overrideCount = Object.keys(config.overrides).length;
267
258
  const customCount = Object.keys(config.custom).length;
268
259
  if (overrideCount === 0 && customCount === 0) {
@@ -289,12 +280,12 @@ export async function furnaceApplyCommand(projectRoot, name, options = {}) {
289
280
  // `persistState: false` for a NAMED apply is load-bearing: the batch
290
281
  // persist path replaces `appliedChecksums` wholesale with only this
291
282
  // run's entries, and the batch loops filter to the named component —
292
- // so routing a named apply through it persisted a state file
293
- // containing ONLY that component, wiping every other component's
294
- // checksums. Orphan detection and deleted-file undeploy both key on
295
- // that state, so the wiped components' stale engine files became
296
- // invisible to apply AND to `furnace validate`. Named apply merges
297
- // per-component state below, exactly like `furnace deploy <name>`.
283
+ // so routing a named apply through it persists a state file containing
284
+ // ONLY that component, wiping every other component's checksums.
285
+ // Orphan detection and deleted-file undeploy both key on that state,
286
+ // so the wiped components' stale engine files become invisible to
287
+ // apply AND to `furnace validate`. Named apply merges per-component
288
+ // state below, exactly like `furnace deploy <name>`.
298
289
  const applyResult = await applyAllComponents(projectRoot, dryRun, {
299
290
  operationContext: ctx,
300
291
  ...(name !== undefined ? { componentName: name, persistState: false } : {}),
@@ -7,10 +7,11 @@ import { readdir } from 'node:fs/promises';
7
7
  import { join } from 'node:path';
8
8
  import { confirm } from '@clack/prompts';
9
9
  import { loadConfig } from '../../core/config.js';
10
- import { recordFurnaceRollbackFailure, runFurnaceMutation, } from '../../core/furnace-operation.js';
11
- import { createRollbackJournal, restoreRollbackJournalOrThrow, snapshotDir, snapshotFile, } from '../../core/furnace-rollback.js';
10
+ import { stdioIsInteractive } from '../../core/destructive.js';
11
+ import { completeJournalRollback, runFurnaceMutation, } from '../../core/furnace-operation.js';
12
+ import { assertFurnaceEngineReady } from '../../core/furnace-precondition.js';
13
+ import { createRollbackJournal, snapshotDir, snapshotFile } from '../../core/furnace-rollback.js';
12
14
  import { FurnaceError } from '../../errors/furnace.js';
13
- import { toError } from '../../utils/errors.js';
14
15
  import { pathExists, readText, removeDir, removeFile, writeText } from '../../utils/fs.js';
15
16
  import { cancel, info, intro, isCancel, note, outro } from '../../utils/logger.js';
16
17
  import { buildChromeDocPlan, validateChromeDocName } from './chrome-doc.js';
@@ -87,20 +88,12 @@ async function performChromeDocRemoveMutations(args) {
87
88
  await removeEmptyDirIfPresent(join(args.engineDir, 'browser/base/content/test', `${args.binaryName}-xpcshell`), journal);
88
89
  }
89
90
  catch (error) {
90
- // This body owns its rollback end to end, so tell the lifecycle wrapper
91
- // not to restore the same journal again on the way out.
92
- args.operationContext.markRolledBack();
93
- try {
94
- await restoreRollbackJournalOrThrow(journal, `Failed to remove chrome-doc "${args.name}"`);
95
- }
96
- catch (rollbackError) {
97
- // Matches the seven sibling mutation sites: a failed rollback leaves the
98
- // engine in an unknown state, so record the repair breadcrumb and let
99
- // the rollback error win rather than discarding it.
100
- await recordFurnaceRollbackFailure(args.projectRoot, 'chrome-doc-rollback', `chrome-doc "${args.name}": ${toError(rollbackError).message}`);
101
- throw rollbackError;
102
- }
103
- throw error;
91
+ return await completeJournalRollback(args.operationContext, journal, error, {
92
+ projectRoot: args.projectRoot,
93
+ operation: 'chrome-doc-rollback',
94
+ failureMessage: `Failed to remove chrome-doc "${args.name}"`,
95
+ subject: `chrome-doc "${args.name}"`,
96
+ });
104
97
  }
105
98
  return { removedFiles, removedJarEntries, removedTestDir };
106
99
  }
@@ -110,9 +103,9 @@ export async function furnaceChromeDocRemoveCommand(projectRoot, name, options =
110
103
  validateChromeDocName(name);
111
104
  const forgeConfig = await loadConfig(projectRoot);
112
105
  const engineDir = join(projectRoot, 'engine');
113
- if (!(await pathExists(engineDir))) {
114
- throw new FurnaceError('Engine directory not found. Run "fireforge download" first before removing a chrome-doc.');
115
- }
106
+ await assertFurnaceEngineReady(projectRoot, {
107
+ engineMissingSuffix: ' before removing a chrome-doc.',
108
+ });
116
109
  const plan = await buildChromeDocPlan({
117
110
  engineDir,
118
111
  name,
@@ -125,7 +118,7 @@ export async function furnaceChromeDocRemoveCommand(projectRoot, name, options =
125
118
  outro('Dry run complete');
126
119
  return;
127
120
  }
128
- const isInteractive = process.stdin.isTTY && process.stdout.isTTY;
121
+ const isInteractive = stdioIsInteractive();
129
122
  if (!options.yes && !isInteractive) {
130
123
  throw new FurnaceError(`Cannot remove chrome-doc "${name}" in non-interactive mode without --yes flag.`, name);
131
124
  }
@@ -41,23 +41,25 @@
41
41
  */
42
42
  export declare function generateChromeDocXhtml(name: string, withTitlebar: boolean, license: string): string;
43
43
  /**
44
- * browser.xhtml-like scaffold for the document that ships as the fork's
45
- * MAIN BROWSER WINDOW (0.34.0 field report): the generic dialog-shaped
46
- * `<window>` scaffold was wrong for the `tokenHostDocuments[0]` /
47
- * BROWSER_CHROME_URL target — platform C++ reads the root element BEFORE
48
- * any script runs, and expects the `browser.xhtml` shape:
44
+ * browser.xhtml-like scaffold for the document that ships as the fork's MAIN
45
+ * BROWSER WINDOW.
46
+ *
47
+ * The generic dialog-shaped `<window>` scaffold is wrong for the
48
+ * `tokenHostDocuments[0]` / BROWSER_CHROME_URL target: platform C++ reads
49
+ * the root element BEFORE any script runs, and expects the `browser.xhtml`
50
+ * shape:
49
51
  *
50
52
  * - `<html id="main-window">` root (not `<window id="<name>-window">`) —
51
53
  * upstream code from nsXULWindow sizing to session restore looks up
52
54
  * `main-window` by id;
53
55
  * - `windowtype="navigator:browser"`, `chromehidden=""` and the geometry
54
56
  * `persist` allowlist declared as ROOT ATTRIBUTES so the platform's
55
- * pre-script pass (window tracking, XULStore geometry, chrome flags)
56
- * sees them;
57
+ * pre-script pass (window tracking, XULStore geometry, chrome flags) sees
58
+ * them;
57
59
  * - the same head/bootstrap wiring (customElements.js, per-doc subscript,
58
60
  * CSS + Fluent links) and `data-furnace-chrome-doc` sentinel as the
59
- * generic scaffold, so jar.mn registration and the platform-module
60
- * guard pattern are unchanged.
61
+ * generic scaffold, so jar.mn registration and the platform-module guard
62
+ * pattern are unchanged.
61
63
  */
62
64
  export declare function generateBrowserWindowXhtml(name: string, license: string): string;
63
65
  /**
@@ -105,25 +107,23 @@ export declare function jarMnEntriesForChromeDoc(name: string): string[];
105
107
  /**
106
108
  * jar.inc.mn entry that registers the scoped CSS under `content/browser/`.
107
109
  *
108
- * The source path is `../shared/<name>-chrome.css` because `jar.inc.mn`
109
- * is included from each theme-specific manifest (`browser/themes/osx/jar.mn`,
110
- * `browser/themes/linux/jar.mn`, `browser/themes/windows/jar.mn`), and every
111
- * existing entry in those manifests resolves paths relative to the including
112
- * manifest's directory. A bare `(shared/…)` path produced
113
- * `obj-.../browser/themes/osx/shared/<name>-chrome.css` which does not exist;
114
- * `(../shared/…)` matches the upstream pattern and resolves under
115
- * `browser/themes/shared/`.
110
+ * The source path is `../shared/<name>-chrome.css` because `jar.inc.mn` is
111
+ * included from each theme-specific manifest (`browser/themes/osx/jar.mn`,
112
+ * `.../linux/`, `.../windows/`), and every existing entry in those manifests
113
+ * resolves paths relative to the INCLUDING manifest's directory. A bare
114
+ * `(shared/…)` path resolves to
115
+ * `obj-.../browser/themes/osx/shared/<name>-chrome.css`, which does not
116
+ * exist.
116
117
  */
117
118
  export declare function jarIncMnEntryForChromeDoc(name: string): string;
118
119
  /**
119
120
  * locales/jar.mn entry that registers the `.ftl` under the browser locale
120
121
  * bundle. The source path is resolved by mach-locale-jar relative to the
121
- * per-locale root (e.g. `engine/browser/locales/en-US/`), and the FTL
122
- * file is scaffolded at `browser/${name}.ftl` under that root — the `%`
123
- * prefix means "per-locale content" and the `browser/` subdirectory
124
- * matches the subdir the scaffolder writes into. Before this fix the
125
- * entry emitted `(%${name}.ftl)`, which pointed at `en-US/${name}.ftl`
126
- * and broke the first post-scaffold `fireforge build` with
122
+ * per-locale root (e.g. `engine/browser/locales/en-US/`), and the FTL file
123
+ * is scaffolded at `browser/${name}.ftl` under that root — the `%` prefix
124
+ * means "per-locale content" and the `browser/` subdirectory matches where
125
+ * the scaffolder writes. A bare `(%${name}.ftl)` points at
126
+ * `en-US/${name}.ftl` and breaks the first post-scaffold build with
127
127
  * "jar.mn: Cannot find ${name}.ftl".
128
128
  */
129
129
  export declare function localeJarMnEntryForChromeDoc(name: string): string;
@@ -99,23 +99,25 @@ export function generateChromeDocXhtml(name, withTitlebar, license) {
99
99
  `;
100
100
  }
101
101
  /**
102
- * browser.xhtml-like scaffold for the document that ships as the fork's
103
- * MAIN BROWSER WINDOW (0.34.0 field report): the generic dialog-shaped
104
- * `<window>` scaffold was wrong for the `tokenHostDocuments[0]` /
105
- * BROWSER_CHROME_URL target — platform C++ reads the root element BEFORE
106
- * any script runs, and expects the `browser.xhtml` shape:
102
+ * browser.xhtml-like scaffold for the document that ships as the fork's MAIN
103
+ * BROWSER WINDOW.
104
+ *
105
+ * The generic dialog-shaped `<window>` scaffold is wrong for the
106
+ * `tokenHostDocuments[0]` / BROWSER_CHROME_URL target: platform C++ reads
107
+ * the root element BEFORE any script runs, and expects the `browser.xhtml`
108
+ * shape:
107
109
  *
108
110
  * - `<html id="main-window">` root (not `<window id="<name>-window">`) —
109
111
  * upstream code from nsXULWindow sizing to session restore looks up
110
112
  * `main-window` by id;
111
113
  * - `windowtype="navigator:browser"`, `chromehidden=""` and the geometry
112
114
  * `persist` allowlist declared as ROOT ATTRIBUTES so the platform's
113
- * pre-script pass (window tracking, XULStore geometry, chrome flags)
114
- * sees them;
115
+ * pre-script pass (window tracking, XULStore geometry, chrome flags) sees
116
+ * them;
115
117
  * - the same head/bootstrap wiring (customElements.js, per-doc subscript,
116
118
  * CSS + Fluent links) and `data-furnace-chrome-doc` sentinel as the
117
- * generic scaffold, so jar.mn registration and the platform-module
118
- * guard pattern are unchanged.
119
+ * generic scaffold, so jar.mn registration and the platform-module guard
120
+ * pattern are unchanged.
119
121
  */
120
122
  export function generateBrowserWindowXhtml(name, license) {
121
123
  return `<?xml version="1.0"?>
@@ -278,14 +280,13 @@ export function jarMnEntriesForChromeDoc(name) {
278
280
  /**
279
281
  * jar.inc.mn entry that registers the scoped CSS under `content/browser/`.
280
282
  *
281
- * The source path is `../shared/<name>-chrome.css` because `jar.inc.mn`
282
- * is included from each theme-specific manifest (`browser/themes/osx/jar.mn`,
283
- * `browser/themes/linux/jar.mn`, `browser/themes/windows/jar.mn`), and every
284
- * existing entry in those manifests resolves paths relative to the including
285
- * manifest's directory. A bare `(shared/…)` path produced
286
- * `obj-.../browser/themes/osx/shared/<name>-chrome.css` which does not exist;
287
- * `(../shared/…)` matches the upstream pattern and resolves under
288
- * `browser/themes/shared/`.
283
+ * The source path is `../shared/<name>-chrome.css` because `jar.inc.mn` is
284
+ * included from each theme-specific manifest (`browser/themes/osx/jar.mn`,
285
+ * `.../linux/`, `.../windows/`), and every existing entry in those manifests
286
+ * resolves paths relative to the INCLUDING manifest's directory. A bare
287
+ * `(shared/…)` path resolves to
288
+ * `obj-.../browser/themes/osx/shared/<name>-chrome.css`, which does not
289
+ * exist.
289
290
  */
290
291
  export function jarIncMnEntryForChromeDoc(name) {
291
292
  return ` content/browser/${name}-chrome.css (../shared/${name}-chrome.css)`;
@@ -293,12 +294,11 @@ export function jarIncMnEntryForChromeDoc(name) {
293
294
  /**
294
295
  * locales/jar.mn entry that registers the `.ftl` under the browser locale
295
296
  * bundle. The source path is resolved by mach-locale-jar relative to the
296
- * per-locale root (e.g. `engine/browser/locales/en-US/`), and the FTL
297
- * file is scaffolded at `browser/${name}.ftl` under that root — the `%`
298
- * prefix means "per-locale content" and the `browser/` subdirectory
299
- * matches the subdir the scaffolder writes into. Before this fix the
300
- * entry emitted `(%${name}.ftl)`, which pointed at `en-US/${name}.ftl`
301
- * and broke the first post-scaffold `fireforge build` with
297
+ * per-locale root (e.g. `engine/browser/locales/en-US/`), and the FTL file
298
+ * is scaffolded at `browser/${name}.ftl` under that root — the `%` prefix
299
+ * means "per-locale content" and the `browser/` subdirectory matches where
300
+ * the scaffolder writes. A bare `(%${name}.ftl)` points at
301
+ * `en-US/${name}.ftl` and breaks the first post-scaffold build with
302
302
  * "jar.mn: Cannot find ${name}.ftl".
303
303
  */
304
304
  export function localeJarMnEntryForChromeDoc(name) {
@@ -3,30 +3,29 @@
3
3
  * Packaging-verification test templates for
4
4
  * `fireforge furnace chrome-doc create --with-tests`.
5
5
  *
6
- * Motivation: an operator who scaffolds a top-level chrome document wants
7
- * to know "did the file actually land in the packaged bundle?" before
8
- * relying on it at runtime. Both natural test harnesses have gaps for
9
- * this question:
6
+ * An operator who scaffolds a top-level chrome document wants to know "did
7
+ * the file actually land in the packaged bundle?" before relying on it at
8
+ * runtime. Both natural test harnesses have gaps for that question:
10
9
  *
11
10
  * - xpcshell's `chrome://browser/*` URI registration lags what the real
12
11
  * browser loads even with `firefox-appdir = "browser"` set, so
13
- * `NetUtil.asyncFetch("chrome://browser/content/<name>.xhtml")` can
14
- * fail with `NS_ERROR_FILE_NOT_FOUND` against a file that IS
15
- * correctly packaged (the motivating case).
12
+ * `NetUtil.asyncFetch("chrome://browser/content/<name>.xhtml")` can fail
13
+ * with `NS_ERROR_FILE_NOT_FOUND` against a file that IS correctly
14
+ * packaged.
16
15
  * - Browser-chrome mochitests require a `tabbrowser`, which a
17
16
  * fork-authored chrome doc that replaces `browser.xhtml` deliberately
18
- * does not carry (the URILoadingHelper crash path).
17
+ * does not carry.
19
18
  *
20
19
  * This scaffold threads the needle by probing the filesystem directly:
21
- * `Services.dirsvc.get("XCurProcD", Ci.nsIFile)` returns the current
22
- * process directory (the browser app dir when `firefox-appdir = "browser"`),
23
- * and the packaged chrome layout for a jar.mn entry
24
- * `content/browser/<name>.xhtml` is stable across platforms at
25
- * `<AppDir>/chrome/browser/content/browser/<name>.xhtml` on an unpacked
26
- * tree (the default for `mach build` without `MOZ_CHROME_MULTILOCALE`
27
- * / omnijar). A tree that packs omni.ja would need a different probe;
28
- * the scaffold notes that out-of-scope case explicitly rather than
29
- * silently producing a test that fails on packed builds.
20
+ * `Services.dirsvc.get("XCurProcD", Ci.nsIFile)` returns the current process
21
+ * directory (the browser app dir when `firefox-appdir = "browser"`), and the
22
+ * packaged chrome layout for a jar.mn entry `content/browser/<name>.xhtml`
23
+ * is stable across platforms at
24
+ * `<AppDir>/chrome/browser/content/browser/<name>.xhtml` on an unpacked tree
25
+ * (the default for `mach build` without `MOZ_CHROME_MULTILOCALE` / omnijar).
26
+ * A tree that packs omni.ja would need a different probe; the scaffold notes
27
+ * that out-of-scope case explicitly rather than silently producing a test
28
+ * that fails on packed builds.
30
29
  */
31
30
  /**
32
31
  * Returns the canonical xpcshell test basename for a chrome doc packaging
@@ -70,17 +69,16 @@ add_task(async function test_${taskSuffix}_files_packaged() {
70
69
  const appDir = Services.dirsvc.get("XCurProcD", Ci.nsIFile);
71
70
 
72
71
  // Probes a pair of candidate layouts for the same packaged file:
73
- // 1) \`<AppDir>/chrome/browser/…\` — the unpacked layout when
74
- // XCurProcD honours \`firefox-appdir = "browser"\` and resolves
75
- // into \`dist/bin/browser/\`.
76
- // 2) \`<AppDir>/browser/chrome/browser/…\` — the macOS .app bundle
77
- // layout and some ESR configurations, where XCurProcD sits one
78
- // level above \`browser/\` even when the appdir directive is set.
72
+ // 1) \`<AppDir>/chrome/browser/…\` — the unpacked layout when XCurProcD
73
+ // honours \`firefox-appdir = "browser"\` and resolves into
74
+ // \`dist/bin/browser/\`.
75
+ // 2) \`<AppDir>/browser/chrome/browser/…\` — the macOS .app bundle layout
76
+ // and some ESR configurations, where XCurProcD sits one level above
77
+ // \`browser/\` even when the appdir directive is set.
79
78
  // If either path exists the file is packaged; the assertion only fails
80
79
  // when BOTH layouts miss, which is the actual stale-build / missing
81
- // jar.mn entry case. Before this dual probe, the eval on macOS
82
- // consistently failed against layout (2) even though the file was
83
- // packaged correctly.
80
+ // jar.mn entry case. A single-layout probe fails on macOS against layout
81
+ // (2) even though the file is packaged correctly.
84
82
  function probeEither(primary, fallback, description) {
85
83
  const primaryFile = appDir.clone();
86
84
  for (const segment of primary) {
@@ -121,9 +119,8 @@ add_task(async function test_${taskSuffix}_files_packaged() {
121
119
  // \`content/browser/<name>-chrome.css\` (see \`chromeDocJarIncMnCssEntry\`
122
120
  // in \`src/commands/furnace/chrome-doc-templates.ts\`), so the packaged
123
121
  // file lands under \`chrome/browser/content/browser/\`, not under
124
- // \`skin/classic/browser/\`. The 2026-04-21 eval's first
125
- // \`fireforge test --build\` against a scaffolded chrome-doc reported
126
- // a false failure because the probe was looking at the skin layout.
122
+ // \`skin/classic/browser/\`. Probing the skin layout reports a false
123
+ // failure on the first \`fireforge test --build\` after a scaffold.
127
124
  probeEither(
128
125
  ["chrome", "browser", "content", "browser", "${name}-chrome.css"],
129
126
  ["browser", "chrome", "browser", "content", "browser", "${name}-chrome.css"],
@@ -2,18 +2,18 @@
2
2
  * `fireforge furnace chrome-doc create <name>` — scaffolds a top-level
3
3
  * chrome document (xhtml + js + css + ftl + jar.mn registrations).
4
4
  *
5
- * Motivation: `furnace create` covers custom elements under
6
- * `toolkit/content/widgets/`, but top-level chrome documents (the
7
- * `mybrowser.xhtml`-class entry points a fork adds alongside or instead
8
- * of `browser.xhtml`) are today hand-authored with error-prone jar.mn +
9
- * jar.inc.mn + locales/jar.mn glue. The `*` preprocessor flag, the
10
- * macOS titlebar-button carve-out, the startup-topic observer, and the
11
- * Fluent linkage each have silent-break failure modes.
5
+ * `furnace create` covers custom elements under `toolkit/content/widgets/`,
6
+ * but top-level chrome documents — the `mybrowser.xhtml`-class entry points
7
+ * a fork adds alongside or instead of `browser.xhtml` — are otherwise
8
+ * hand-authored with error-prone jar.mn + jar.inc.mn + locales/jar.mn glue.
9
+ * The `*` preprocessor flag, the macOS titlebar-button carve-out, the
10
+ * startup-topic observer, and the Fluent linkage each have silent-break
11
+ * failure modes.
12
12
  *
13
- * This command writes the four source files and appends three jar.mn
14
- * entries under a rollback journal identical in shape to `furnace create`.
15
- * A SIGINT mid-scaffold restores every touched file; a successful run
16
- * leaves the tree ready for `fireforge build`.
13
+ * This command writes the four source files and appends three jar.mn entries
14
+ * under a rollback journal identical in shape to `furnace create`. A SIGINT
15
+ * mid-scaffold restores every touched file; a successful run leaves the tree
16
+ * ready for `fireforge build`.
17
17
  */
18
18
  /** Options for `furnace chrome-doc create`. */
19
19
  export interface FurnaceChromeDocCreateOptions {
@@ -27,12 +27,11 @@ export interface FurnaceChromeDocCreateOptions {
27
27
  /**
28
28
  * Scaffold an xpcshell packaging-verification test alongside the chrome
29
29
  * document. The generated test probes `XCurProcD/chrome/browser/...` on
30
- * disk rather than going through `chrome://` URI resolution — that
31
- * bypasses xpcshell's limited browser-chrome manifest set (the
32
- * motivating failure mode where `NetUtil.asyncFetch` returns
33
- * `NS_ERROR_FILE_NOT_FOUND` against a file that IS packaged).
34
- * Registration in `XPCSHELL_TESTS_MANIFESTS` is left to the operator
35
- * because the owning moz.build depends on the fork's layout.
30
+ * disk rather than going through `chrome://` URI resolution, which
31
+ * bypasses xpcshell's limited browser-chrome manifest set — where
32
+ * `NetUtil.asyncFetch` returns `NS_ERROR_FILE_NOT_FOUND` against a file
33
+ * that IS packaged. Registration in `XPCSHELL_TESTS_MANIFESTS` is left to
34
+ * the operator because the owning moz.build depends on the fork's layout.
36
35
  */
37
36
  withTests?: boolean;
38
37
  /** Print the scaffold plan without writing files. */
@@ -3,29 +3,29 @@
3
3
  * `fireforge furnace chrome-doc create <name>` — scaffolds a top-level
4
4
  * chrome document (xhtml + js + css + ftl + jar.mn registrations).
5
5
  *
6
- * Motivation: `furnace create` covers custom elements under
7
- * `toolkit/content/widgets/`, but top-level chrome documents (the
8
- * `mybrowser.xhtml`-class entry points a fork adds alongside or instead
9
- * of `browser.xhtml`) are today hand-authored with error-prone jar.mn +
10
- * jar.inc.mn + locales/jar.mn glue. The `*` preprocessor flag, the
11
- * macOS titlebar-button carve-out, the startup-topic observer, and the
12
- * Fluent linkage each have silent-break failure modes.
6
+ * `furnace create` covers custom elements under `toolkit/content/widgets/`,
7
+ * but top-level chrome documents — the `mybrowser.xhtml`-class entry points
8
+ * a fork adds alongside or instead of `browser.xhtml` — are otherwise
9
+ * hand-authored with error-prone jar.mn + jar.inc.mn + locales/jar.mn glue.
10
+ * The `*` preprocessor flag, the macOS titlebar-button carve-out, the
11
+ * startup-topic observer, and the Fluent linkage each have silent-break
12
+ * failure modes.
13
13
  *
14
- * This command writes the four source files and appends three jar.mn
15
- * entries under a rollback journal identical in shape to `furnace create`.
16
- * A SIGINT mid-scaffold restores every touched file; a successful run
17
- * leaves the tree ready for `fireforge build`.
14
+ * This command writes the four source files and appends three jar.mn entries
15
+ * under a rollback journal identical in shape to `furnace create`. A SIGINT
16
+ * mid-scaffold restores every touched file; a successful run leaves the tree
17
+ * ready for `fireforge build`.
18
18
  */
19
19
  import { join } from 'node:path';
20
20
  import { loadConfig } from '../../core/config.js';
21
21
  import { furnaceConfigExists, loadFurnaceConfig } from '../../core/furnace-config.js';
22
- import { recordFurnaceRollbackFailure, runFurnaceMutation, } from '../../core/furnace-operation.js';
23
- import { createRollbackJournal, recordCreatedDir, restoreRollbackJournalOrThrow, snapshotFile, } from '../../core/furnace-rollback.js';
22
+ import { completeJournalRollback, runFurnaceMutation, } from '../../core/furnace-operation.js';
23
+ import { assertFurnaceEngineReady } from '../../core/furnace-precondition.js';
24
+ import { createRollbackJournal, recordCreatedDir, snapshotFile, } from '../../core/furnace-rollback.js';
24
25
  import { DEFAULT_LICENSE, getLicenseHeader } from '../../core/license-headers.js';
25
26
  import { InvalidArgumentError } from '../../errors/base.js';
26
27
  import { FurnaceError } from '../../errors/furnace.js';
27
- import { toError } from '../../utils/errors.js';
28
- import { pathExists, readText, writeText } from '../../utils/fs.js';
28
+ import { ensureDir, pathExists, readText, writeText } from '../../utils/fs.js';
29
29
  import { intro, note, outro, warn } from '../../utils/logger.js';
30
30
  import { generateBrowserWindowXhtml, generateChromeDocCss, generateChromeDocFtl, generateChromeDocJs, generateChromeDocXhtml, jarIncMnEntryForChromeDoc, jarMnEntriesForChromeDoc, localeJarMnEntryForChromeDoc, localesFtlWildcardCapturesScaffoldedName, } from './chrome-doc-templates.js';
31
31
  import { chromeDocPackagingTestFileName, generateChromeDocPackagingManifest, generateChromeDocPackagingTest, } from './chrome-doc-tests.js';
@@ -189,7 +189,6 @@ async function performChromeDocMutations(args) {
189
189
  for (const dir of [contentDir, sharedThemeDir, localeDir]) {
190
190
  if (!(await pathExists(dir))) {
191
191
  recordCreatedDir(journal, dir);
192
- const { ensureDir } = await import('../../utils/fs.js');
193
192
  await ensureDir(dir);
194
193
  }
195
194
  }
@@ -230,9 +229,9 @@ async function performChromeDocMutations(args) {
230
229
  // wildcard already pick up the scaffolded FTL automatically — appending
231
230
  // a per-file `locale/...` entry on top is at best dead weight and at
232
231
  // worst a build error when the fork has dropped the `% locale browser`
233
- // registration the per-file entry depends on. The wildcard predicate
234
- // is intentionally narrow: only `%browser/`-rooted globs that end in
235
- // `*.ftl` count as a capture.
232
+ // registration the per-file entry depends on. The wildcard predicate is
233
+ // intentionally narrow: only `%browser/`-rooted globs ending in `*.ftl`
234
+ // count as a capture.
236
235
  if (await pathExists(localeJarMnPath)) {
237
236
  const existingLocaleJar = await readText(localeJarMnPath);
238
237
  if (localesFtlWildcardCapturesScaffoldedName(existingLocaleJar)) {
@@ -256,7 +255,6 @@ async function performChromeDocMutations(args) {
256
255
  if (args.withTests) {
257
256
  const testParentDir = `${args.binaryName}-xpcshell`;
258
257
  const testDir = join(args.engineDir, 'browser/base/content/test', testParentDir, args.name);
259
- const { ensureDir } = await import('../../utils/fs.js');
260
258
  if (!(await pathExists(testDir))) {
261
259
  recordCreatedDir(journal, testDir);
262
260
  }
@@ -274,20 +272,12 @@ async function performChromeDocMutations(args) {
274
272
  }
275
273
  }
276
274
  catch (error) {
277
- // This body owns its rollback end to end, so tell the lifecycle wrapper
278
- // not to restore the same journal again on the way out.
279
- args.operationContext.markRolledBack();
280
- try {
281
- await restoreRollbackJournalOrThrow(journal, `Failed to scaffold chrome-doc "${args.name}"`);
282
- }
283
- catch (rollbackError) {
284
- // Matches the seven sibling mutation sites: when the rollback itself
285
- // fails the engine is in an unknown state, so leave a breadcrumb for
286
- // `doctor --repair-furnace` and let the rollback error win.
287
- await recordFurnaceRollbackFailure(args.projectRoot, 'chrome-doc-rollback', `chrome-doc "${args.name}": ${toError(rollbackError).message}`);
288
- throw rollbackError;
289
- }
290
- throw error;
275
+ return await completeJournalRollback(args.operationContext, journal, error, {
276
+ projectRoot: args.projectRoot,
277
+ operation: 'chrome-doc-rollback',
278
+ failureMessage: `Failed to scaffold chrome-doc "${args.name}"`,
279
+ subject: `chrome-doc "${args.name}"`,
280
+ });
291
281
  }
292
282
  return written;
293
283
  }
@@ -303,18 +293,18 @@ export async function furnaceChromeDocCreateCommand(projectRoot, name, options =
303
293
  const forgeConfig = await loadConfig(projectRoot);
304
294
  const license = forgeConfig.license ?? DEFAULT_LICENSE;
305
295
  const engineDir = join(projectRoot, 'engine');
306
- if (!(await pathExists(engineDir))) {
307
- throw new FurnaceError('Engine directory not found. Run "fireforge download" first to scaffold a chrome-doc.');
308
- }
296
+ await assertFurnaceEngineReady(projectRoot, {
297
+ engineMissingSuffix: ' to scaffold a chrome-doc.',
298
+ });
309
299
  const browserWindow = options.browserWindow ?? false;
310
300
  // The browser-window skeleton always carries its own titlebar markup and
311
301
  // chrome attributes; --no-titlebar only applies to the generic scaffold.
312
302
  const withTitlebar = browserWindow ? true : (options.titlebar ?? true);
313
303
  const withTests = options.withTests ?? false;
314
- // Hint: when the scaffolded document is the configured token-host
315
- // document (the fork's main browser window), the generic dialog-shaped
316
- // scaffold is almost certainly wrong (0.34.0 field report: correct
317
- // jar.mn registrations, wrong document body).
304
+ // Hint: when the scaffolded document is the configured token-host document
305
+ // (the fork's main browser window), the generic dialog-shaped scaffold is
306
+ // almost certainly wrong — correct jar.mn registrations, wrong document
307
+ // body.
318
308
  if (!browserWindow && (await furnaceConfigExists(projectRoot))) {
319
309
  try {
320
310
  const furnaceConfig = await loadFurnaceConfig(projectRoot);
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * Browser-chrome test scaffolding for `furnace create --with-tests`,
3
- * including the 0.34.0 `--test-dir` redirect and collision safety
4
- * (existing manifests are appended to; head.js and test implementations
5
- * are never overwritten). Split out of `create.ts` to keep that command
6
- * file within the per-file line budget.
3
+ * including the `--test-dir` redirect and collision safety (existing
4
+ * manifests are appended to; head.js and test implementations are never
5
+ * overwritten). Split out of `create.ts` to keep that command file within
6
+ * the per-file line budget.
7
7
  */
8
8
  import { type RollbackJournal } from '../../core/furnace-rollback.js';
9
9
  import type { ProjectLicense } from '../../types/config.js';
@@ -1,15 +1,15 @@
1
1
  // SPDX-License-Identifier: EUPL-1.2
2
2
  /**
3
3
  * Browser-chrome test scaffolding for `furnace create --with-tests`,
4
- * including the 0.34.0 `--test-dir` redirect and collision safety
5
- * (existing manifests are appended to; head.js and test implementations
6
- * are never overwritten). Split out of `create.ts` to keep that command
7
- * file within the per-file line budget.
4
+ * including the `--test-dir` redirect and collision safety (existing
5
+ * manifests are appended to; head.js and test implementations are never
6
+ * overwritten). Split out of `create.ts` to keep that command file within
7
+ * the per-file line budget.
8
8
  */
9
9
  import { join } from 'node:path';
10
10
  import { recordCreatedDir, snapshotFile, } from '../../core/furnace-rollback.js';
11
11
  import { getLicenseHeader } from '../../core/license-headers.js';
12
- import { registerTestManifest } from '../../core/manifest-register.js';
12
+ import { registerTestManifest } from '../../core/moz-manifest-register.js';
13
13
  import { InvalidArgumentError } from '../../errors/base.js';
14
14
  import { toError } from '../../utils/errors.js';
15
15
  import { ensureDir, pathExists, readText, writeText } from '../../utils/fs.js';
@@ -74,9 +74,9 @@ export async function scaffoldTestFiles(componentName, license, forgeConfig, pat
74
74
  : strippedName;
75
75
  const underscored = withoutBinaryPrefix.replace(/-/g, '_');
76
76
  const testFileName = `browser_${binaryName}_${underscored}.js`;
77
- // --test-dir redirects the scaffold (0.34.0 field report: the hardcoded
78
- // .../test/<binaryName>/ target collided with a test suite owned by a
79
- // different patch). The manifest-registration name is the path below
77
+ // --test-dir redirects the scaffold: the hardcoded
78
+ // `.../test/<binaryName>/` target can collide with a test suite owned by a
79
+ // different patch. The manifest-registration name is the path below
80
80
  // browser/base/content/test/ (nested manifests are supported).
81
81
  const testDirRel = testDirOverride ?? `${TEST_SCAFFOLD_ROOT}${binaryName}`;
82
82
  const testDirName = testDirRel.slice(TEST_SCAFFOLD_ROOT.length);
@@ -2,13 +2,12 @@
2
2
  * MochiKit (chrome://mochikit) test-harness scaffolder for
3
3
  * `fireforge furnace create --test-style=mochikit`.
4
4
  *
5
- * Motivation: browser-chrome mochitests require a `tabbrowser` to exist in
6
- * the top-level chrome document. Forks with a bespoke chrome document
7
- * (e.g. `mybrowser.xhtml`) that deliberately omits tabbrowser cannot run
8
- * browser-chrome tests today. MochiKit tests load the component module
9
- * directly via `chrome://global/` and assert against `customElements`, so
10
- * they work against any fork that registers the upstream toolkit test
11
- * manifest tree — including those without a tabbrowser.
5
+ * Browser-chrome mochitests require a `tabbrowser` in the top-level chrome
6
+ * document, so forks with a bespoke chrome document that deliberately omits
7
+ * one cannot run them. MochiKit tests load the component module directly via
8
+ * `chrome://global/` and assert against `customElements`, so they work
9
+ * against any fork that registers the upstream toolkit test manifest tree —
10
+ * including those without a tabbrowser.
12
11
  */
13
12
  import { type RollbackJournal } from '../../core/furnace-rollback.js';
14
13
  import type { ProjectLicense } from '../../types/config.js';