@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,9 +5,9 @@
5
5
  * AST-based implementation: finds onUnload()/uninit() method body and
6
6
  * inserts the destroy block at the top (LIFO ordering).
7
7
  *
8
- * `marker` is prefixed to the generated comment so wire-generated
9
- * edits carry the patch-lint `// <MARKER>:` signature
10
- * `lintModificationComments` looks for (eval 1 Finding #9).
8
+ * `marker` is prefixed to the generated comment so wire-generated edits
9
+ * carry the patch-lint `// <MARKER>:` signature `lintModificationComments`
10
+ * looks for.
11
11
  */
12
12
  export declare function addDestroyAST(content: string, expression: string, marker?: string): string;
13
13
  /**
@@ -9,7 +9,7 @@ import { BuildError } from '../errors/build.js';
9
9
  import { pathExists, readText, writeText } from '../utils/fs.js';
10
10
  import { escapeRegex } from '../utils/regex.js';
11
11
  import { asEstree, detectIndent, parseScript } from './ast-utils.js';
12
- import { withParserFallback } from './parser-fallback.js';
12
+ import { isInternalInvariantFailure, withParserFallback } from './parser-fallback.js';
13
13
  import { assertBraceBalancePreserved, coerceToCall, extractNameFromExpression, findMethodBody, findMethodBraceIndex, validateWireName, } from './wire-utils.js';
14
14
  const BROWSER_INIT_JS = 'browser/base/content/browser-init.js';
15
15
  const DEFAULT_MARKER = 'FIREFORGE:';
@@ -17,9 +17,9 @@ const DEFAULT_MARKER = 'FIREFORGE:';
17
17
  * AST-based implementation: finds onUnload()/uninit() method body and
18
18
  * inserts the destroy block at the top (LIFO ordering).
19
19
  *
20
- * `marker` is prefixed to the generated comment so wire-generated
21
- * edits carry the patch-lint `// <MARKER>:` signature
22
- * `lintModificationComments` looks for (eval 1 Finding #9).
20
+ * `marker` is prefixed to the generated comment so wire-generated edits
21
+ * carry the patch-lint `// <MARKER>:` signature `lintModificationComments`
22
+ * looks for.
23
23
  */
24
24
  export function addDestroyAST(content, expression, marker = DEFAULT_MARKER) {
25
25
  const name = extractNameFromExpression(expression);
@@ -110,22 +110,14 @@ export async function addDestroyToBrowserInit(engineDir, expression, marker = DE
110
110
  const content = await readText(filePath);
111
111
  // Idempotency check — look for the coerced (call) form because that is
112
112
  // what the emitter writes. Matching against the raw input would miss a
113
- // previous `EvalStartup.destroy` invocation that the 0.16.0 coercion
114
- // already persisted as `EvalStartup.destroy()`.
113
+ // bare `X.destroy` invocation that coercion already persisted as
114
+ // `X.destroy()`.
115
115
  const callExpression = coerceToCall(expression);
116
116
  const destroyPattern = new RegExp(`(?:^|\\W)${escapeRegex(callExpression)}\\s*;?\\s*$`, 'm');
117
117
  if (destroyPattern.test(content)) {
118
118
  return false;
119
119
  }
120
- const { value, usedFallback } = withParserFallback(() => addDestroyAST(content, expression, marker), () => legacyAddDestroy(content, expression, marker), BROWSER_INIT_JS,
121
- // Rethrow only the internal-invariant GeneralErrors ("Unexpected empty
122
- // …array"): those are programming bugs, and retrying the legacy scanner
123
- // cannot fix a broken invariant — it just buries the stack. Everything
124
- // else still falls back, which is load-bearing: the AST path raises a raw
125
- // acorn SyntaxError on chrome sources acorn cannot parse (preprocessor
126
- // directives), and BuildError when the file's shape is unexpected. Both
127
- // are exactly what the legacy scanner is here to handle.
128
- (error) => error instanceof GeneralError);
120
+ const { value, usedFallback } = withParserFallback(() => addDestroyAST(content, expression, marker), () => legacyAddDestroy(content, expression, marker), BROWSER_INIT_JS, isInternalInvariantFailure);
129
121
  if (usedFallback) {
130
122
  assertBraceBalancePreserved(content, value, BROWSER_INIT_JS);
131
123
  }
@@ -13,24 +13,16 @@ export declare const DEFAULT_DOM_TARGET = "browser/base/content/browser.xhtml";
13
13
  */
14
14
  export declare function addDomFragmentTokenized(content: string, includeDirective: string): string;
15
15
  /**
16
- * Legacy line-based implementation preserved as fallback.
17
- */
18
- export declare function legacyAddDomFragment(content: string, includeDirective: string): string;
19
- /**
20
- * Dry-run precheck for `addDomFragment`. Reads the resolved chrome
21
- * document and verifies it either already contains the `#include`
22
- * directive (the idempotent-skip case) OR offers a locatable insertion
23
- * point via {@link addDomFragmentTokenized} / {@link legacyAddDomFragment}.
24
- * Throws the same `Could not find insertion point in chrome document`
25
- * error the real run would throw when neither condition holds.
16
+ * Dry-run precheck for `addDomFragment`. Reads the resolved chrome document
17
+ * and verifies it either already contains the `#include` directive (the
18
+ * idempotent-skip case) OR offers a locatable insertion point via
19
+ * {@link addDomFragmentTokenized} / {@link legacyAddDomFragment}. Throws the
20
+ * same `Could not find insertion point in chrome document` error the real
21
+ * run would throw when neither condition holds.
26
22
  *
27
- * Motivating case (2026-04-21 eval, Finding #12): `fireforge wire ...
28
- * --dry-run` previewed a plausible mutation plan against
29
- * `tokenHostDocuments[0]`, then `fireforge wire ...` without
30
- * `--dry-run` threw `Could not find insertion point in chrome document`
31
- * on the same arguments. The real run had always called the insertion
32
- * helpers; dry-run did not. This helper runs the same check in the
33
- * preview pass so plan and execution disagree less.
23
+ * Without it, `wire --dry-run` previews a plausible mutation plan while the
24
+ * real run throws on the same arguments, because only the real run called
25
+ * the insertion helpers.
34
26
  */
35
27
  export declare function probeDomFragmentInsertionPoint(engineDir: string, domFilePath: string, targetPath?: string): Promise<void>;
36
28
  /**
@@ -13,7 +13,6 @@ import { GeneralError } from '../errors/base.js';
13
13
  import { pathExists, readText, writeText } from '../utils/fs.js';
14
14
  import { toRootRelativePath } from '../utils/paths.js';
15
15
  import { escapeRegex } from '../utils/regex.js';
16
- import { withParserFallback } from './parser-fallback.js';
17
16
  import { tokenizeXhtml } from './wire-utils.js';
18
17
  export const DEFAULT_DOM_TARGET = 'browser/base/content/browser.xhtml';
19
18
  /**
@@ -48,48 +47,16 @@ export function addDomFragmentTokenized(content, includeDirective) {
48
47
  return lines.join('\n');
49
48
  }
50
49
  /**
51
- * Legacy line-based implementation preserved as fallback.
52
- */
53
- export function legacyAddDomFragment(content, includeDirective) {
54
- const lines = content.split('\n');
55
- let insertIndex = -1;
56
- for (let i = 0; i < lines.length; i++) {
57
- const line = lines[i] ?? '';
58
- if (/browser-sets\.inc/.test(line)) {
59
- insertIndex = i;
60
- break;
61
- }
62
- }
63
- if (insertIndex === -1) {
64
- for (let i = 0; i < lines.length; i++) {
65
- const line = lines[i] ?? '';
66
- if (/<html:body/.test(line)) {
67
- insertIndex = i + 1;
68
- break;
69
- }
70
- }
71
- }
72
- if (insertIndex === -1) {
73
- throw new GeneralError('Could not find insertion point in chrome document');
74
- }
75
- lines.splice(insertIndex, 0, includeDirective);
76
- return lines.join('\n');
77
- }
78
- /**
79
- * Dry-run precheck for `addDomFragment`. Reads the resolved chrome
80
- * document and verifies it either already contains the `#include`
81
- * directive (the idempotent-skip case) OR offers a locatable insertion
82
- * point via {@link addDomFragmentTokenized} / {@link legacyAddDomFragment}.
83
- * Throws the same `Could not find insertion point in chrome document`
84
- * error the real run would throw when neither condition holds.
50
+ * Dry-run precheck for `addDomFragment`. Reads the resolved chrome document
51
+ * and verifies it either already contains the `#include` directive (the
52
+ * idempotent-skip case) OR offers a locatable insertion point via
53
+ * {@link addDomFragmentTokenized} / {@link legacyAddDomFragment}. Throws the
54
+ * same `Could not find insertion point in chrome document` error the real
55
+ * run would throw when neither condition holds.
85
56
  *
86
- * Motivating case (2026-04-21 eval, Finding #12): `fireforge wire ...
87
- * --dry-run` previewed a plausible mutation plan against
88
- * `tokenHostDocuments[0]`, then `fireforge wire ...` without
89
- * `--dry-run` threw `Could not find insertion point in chrome document`
90
- * on the same arguments. The real run had always called the insertion
91
- * helpers; dry-run did not. This helper runs the same check in the
92
- * preview pass so plan and execution disagree less.
57
+ * Without it, `wire --dry-run` previews a plausible mutation plan while the
58
+ * real run throws on the same arguments, because only the real run called
59
+ * the insertion helpers.
93
60
  */
94
61
  export async function probeDomFragmentInsertionPoint(engineDir, domFilePath, targetPath = DEFAULT_DOM_TARGET) {
95
62
  const targetAbsPath = join(engineDir, targetPath);
@@ -113,7 +80,7 @@ export async function probeDomFragmentInsertionPoint(engineDir, domFilePath, tar
113
80
  // Check the tokenised and legacy insertion paths symmetrically with
114
81
  // the real run. Either helper returning without throwing is sufficient
115
82
  // evidence that the real run can land the directive.
116
- withParserFallback(() => addDomFragmentTokenized(content, includeDirective), () => legacyAddDomFragment(content, includeDirective), targetPath);
83
+ addDomFragmentTokenized(content, includeDirective);
117
84
  }
118
85
  /**
119
86
  * Inserts a `#include` directive for an `.inc.xhtml` file into the top-level
@@ -177,7 +144,7 @@ export async function addDomFragment(engineDir, domFilePath, targetPath = DEFAUL
177
144
  }
178
145
  }
179
146
  // Normal insertion
180
- const { value } = withParserFallback(() => addDomFragmentTokenized(content, includeDirective), () => legacyAddDomFragment(content, includeDirective), targetPath);
147
+ const value = addDomFragmentTokenized(content, includeDirective);
181
148
  await writeText(targetAbsPath, value);
182
149
  return true;
183
150
  }
@@ -8,9 +8,8 @@
8
8
  *
9
9
  * `marker` is prepended (uppercased) to the generated comment line so the
10
10
  * emitted block carries the patch-lint `// <MARKER>:` signature that
11
- * `lintModificationComments` looks for. Otherwise the first export after
12
- * `wire` trips `missing-modification-comment` on wire-generated edits —
13
- * exactly the eval 1 Finding #9 regression.
11
+ * `lintModificationComments` looks for; otherwise the first export after
12
+ * `wire` trips `missing-modification-comment` on wire-generated edits.
14
13
  */
15
14
  export declare function addInitAST(content: string, expression: string, after?: string, marker?: string): string;
16
15
  /**
@@ -9,7 +9,7 @@ import { BuildError } from '../errors/build.js';
9
9
  import { pathExists, readText, writeText } from '../utils/fs.js';
10
10
  import { escapeRegex } from '../utils/regex.js';
11
11
  import { asEstree, detectIndent, getNodeSource, parseScript, } from './ast-utils.js';
12
- import { withParserFallback } from './parser-fallback.js';
12
+ import { isInternalInvariantFailure, withParserFallback } from './parser-fallback.js';
13
13
  import { assertBraceBalancePreserved, coerceToCall, extractNameFromExpression, findInsertionAfterFireforgeBlocks, findMethodBody, findMethodBraceIndex, validateWireName, walkToTryBlockEnd, } from './wire-utils.js';
14
14
  const BROWSER_INIT_JS = 'browser/base/content/browser-init.js';
15
15
  /**
@@ -23,10 +23,9 @@ const DEFAULT_MARKER = 'FIREFORGE:';
23
23
  * the top of the method body when there is none.
24
24
  *
25
25
  * Both callers below — the `--after`-target-not-found fallthrough and the
26
- * no-`--after` default — ran a character-for-character copy of this ladder,
27
- * including both throw guards. `browser-init.js` is written through those two
28
- * independent paths and they MUST emit identical blocks, so having one
29
- * implementation enforces the invariant rather than merely tidying.
26
+ * no-`--after` default — must emit identical blocks, since `browser-init.js`
27
+ * is written through both paths. One implementation enforces that invariant
28
+ * rather than merely tidying.
30
29
  */
31
30
  function resolveDefaultInsertion(content, body, fireforgeBlocks) {
32
31
  if (fireforgeBlocks.length > 0) {
@@ -49,9 +48,8 @@ function resolveDefaultInsertion(content, body, fireforgeBlocks) {
49
48
  *
50
49
  * `marker` is prepended (uppercased) to the generated comment line so the
51
50
  * emitted block carries the patch-lint `// <MARKER>:` signature that
52
- * `lintModificationComments` looks for. Otherwise the first export after
53
- * `wire` trips `missing-modification-comment` on wire-generated edits —
54
- * exactly the eval 1 Finding #9 regression.
51
+ * `lintModificationComments` looks for; otherwise the first export after
52
+ * `wire` trips `missing-modification-comment` on wire-generated edits.
55
53
  */
56
54
  export function addInitAST(content, expression, after, marker = DEFAULT_MARKER) {
57
55
  const name = extractNameFromExpression(expression);
@@ -206,22 +204,13 @@ export async function addInitToBrowserInit(engineDir, expression, after, marker
206
204
  const content = await readText(filePath);
207
205
  // Idempotency check — look for the coerced (call) form because that is
208
206
  // what the emitter writes. Matching against the raw input would miss a
209
- // previous `EvalStartup.init` invocation that the 0.16.0 coercion
210
- // already persisted as `EvalStartup.init()`.
207
+ // bare `X.init` invocation that coercion already persisted as `X.init()`.
211
208
  const callExpression = coerceToCall(expression);
212
209
  const initPattern = new RegExp(`(?:^|\\W)${escapeRegex(callExpression)}\\s*;?\\s*$`, 'm');
213
210
  if (initPattern.test(content)) {
214
211
  return false;
215
212
  }
216
- const { value, usedFallback } = withParserFallback(() => addInitAST(content, expression, after, marker), () => legacyAddInit(content, expression, after, marker), BROWSER_INIT_JS,
217
- // Rethrow only the internal-invariant GeneralErrors ("Unexpected empty
218
- // …array"): those are programming bugs, and retrying the legacy scanner
219
- // cannot fix a broken invariant — it just buries the stack. Everything
220
- // else still falls back, which is load-bearing: the AST path raises a raw
221
- // acorn SyntaxError on chrome sources acorn cannot parse (preprocessor
222
- // directives), and BuildError when the file's shape is unexpected. Both
223
- // are exactly what the legacy scanner is here to handle.
224
- (error) => error instanceof GeneralError);
213
+ const { value, usedFallback } = withParserFallback(() => addInitAST(content, expression, after, marker), () => legacyAddInit(content, expression, after, marker), BROWSER_INIT_JS, isInternalInvariantFailure);
225
214
  if (usedFallback) {
226
215
  assertBraceBalancePreserved(content, value, BROWSER_INIT_JS);
227
216
  }
@@ -5,9 +5,8 @@
5
5
  * AST-based implementation: finds the last try/catch containing
6
6
  * `loadSubScript` and inserts a new try/catch block after it.
7
7
  *
8
- * The inserted block carries a `// <MARKER>: wire-subscript ...` comment
9
- * so the emitted edit satisfies `lintModificationComments` (eval 1
10
- * Finding #9).
8
+ * The inserted block carries a `// <MARKER>: wire-subscript ...` comment so
9
+ * the emitted edit satisfies `lintModificationComments`.
11
10
  */
12
11
  export declare function addSubscriptAST(content: string, name: string, marker?: string): string;
13
12
  /**
@@ -8,7 +8,7 @@ import { GeneralError } from '../errors/base.js';
8
8
  import { BuildError } from '../errors/build.js';
9
9
  import { pathExists, readText, writeText } from '../utils/fs.js';
10
10
  import { asEstree, detectIndent, getNodeSource, parseScript, walkAST, } from './ast-utils.js';
11
- import { withParserFallback } from './parser-fallback.js';
11
+ import { isInternalInvariantFailure, withParserFallback } from './parser-fallback.js';
12
12
  import { assertBraceBalancePreserved, findNearestTryLine, validateWireName, walkToTryBlockEnd, } from './wire-utils.js';
13
13
  const BROWSER_MAIN_JS = 'browser/base/content/browser-main.js';
14
14
  const DEFAULT_MARKER = 'FIREFORGE:';
@@ -16,9 +16,8 @@ const DEFAULT_MARKER = 'FIREFORGE:';
16
16
  * AST-based implementation: finds the last try/catch containing
17
17
  * `loadSubScript` and inserts a new try/catch block after it.
18
18
  *
19
- * The inserted block carries a `// <MARKER>: wire-subscript ...` comment
20
- * so the emitted edit satisfies `lintModificationComments` (eval 1
21
- * Finding #9).
19
+ * The inserted block carries a `// <MARKER>: wire-subscript ...` comment so
20
+ * the emitted edit satisfies `lintModificationComments`.
22
21
  */
23
22
  export function addSubscriptAST(content, name, marker = DEFAULT_MARKER) {
24
23
  const ast = parseScript(content);
@@ -137,15 +136,7 @@ export async function addSubscriptToBrowserMain(engineDir, name, marker = DEFAUL
137
136
  if (content.includes(`content/${name}.js"`)) {
138
137
  return false;
139
138
  }
140
- const { value, usedFallback } = withParserFallback(() => addSubscriptAST(content, name, marker), () => legacyAddSubscript(content, name, marker), BROWSER_MAIN_JS,
141
- // Rethrow only the internal-invariant GeneralErrors ("Unexpected empty
142
- // …array"): those are programming bugs, and retrying the legacy scanner
143
- // cannot fix a broken invariant — it just buries the stack. Everything
144
- // else still falls back, which is load-bearing: the AST path raises a raw
145
- // acorn SyntaxError on chrome sources acorn cannot parse (preprocessor
146
- // directives), and BuildError when the file's shape is unexpected. Both
147
- // are exactly what the legacy scanner is here to handle.
148
- (error) => error instanceof GeneralError);
139
+ const { value, usedFallback } = withParserFallback(() => addSubscriptAST(content, name, marker), () => legacyAddSubscript(content, name, marker), BROWSER_MAIN_JS, isInternalInvariantFailure);
149
140
  if (usedFallback) {
150
141
  assertBraceBalancePreserved(content, value, BROWSER_MAIN_JS);
151
142
  }
@@ -9,15 +9,14 @@ export declare function validateWireName(value: string, label: string): void;
9
9
  * Coerces an init/destroy expression into a function call by appending `()`
10
10
  * when the caller passed a bare property chain. Idempotent: an expression
11
11
  * already ending in `()` is returned unchanged, so operators can pass either
12
- * `EvalStartup.init` or `EvalStartup.init()` and get the same wired output.
12
+ * `Startup.init` or `Startup.init()` and get the same wired output.
13
13
  *
14
- * Motivation (eval finding 8): `validateWireName` accepts both shapes, but
15
- * the generated block interpolated the expression verbatim inside
16
- * `${expression};`. When a caller passed `EvalStartup.init`, the emitted
17
- * code was `EvalStartup.init;` — a plain property reference that never
18
- * invoked the lifecycle hook. The symptom was silent: `wire` reported
19
- * success and the browser-init block looked plausible, but the hook
20
- * never fired at runtime. Coercion at the template site closes that gap.
14
+ * `validateWireName` accepts both shapes, but the generated block
15
+ * interpolates the expression verbatim inside `${expression};` — so a bare
16
+ * `Startup.init` emits `Startup.init;`, a plain property reference that
17
+ * never invokes the lifecycle hook. The symptom is silent: `wire` reports
18
+ * success and the browser-init block looks plausible, but the hook never
19
+ * fires at runtime.
21
20
  */
22
21
  export declare function coerceToCall(expression: string): string;
23
22
  /**
@@ -21,15 +21,14 @@ export function validateWireName(value, label) {
21
21
  * Coerces an init/destroy expression into a function call by appending `()`
22
22
  * when the caller passed a bare property chain. Idempotent: an expression
23
23
  * already ending in `()` is returned unchanged, so operators can pass either
24
- * `EvalStartup.init` or `EvalStartup.init()` and get the same wired output.
24
+ * `Startup.init` or `Startup.init()` and get the same wired output.
25
25
  *
26
- * Motivation (eval finding 8): `validateWireName` accepts both shapes, but
27
- * the generated block interpolated the expression verbatim inside
28
- * `${expression};`. When a caller passed `EvalStartup.init`, the emitted
29
- * code was `EvalStartup.init;` — a plain property reference that never
30
- * invoked the lifecycle hook. The symptom was silent: `wire` reported
31
- * success and the browser-init block looked plausible, but the hook
32
- * never fired at runtime. Coercion at the template site closes that gap.
26
+ * `validateWireName` accepts both shapes, but the generated block
27
+ * interpolates the expression verbatim inside `${expression};` — so a bare
28
+ * `Startup.init` emits `Startup.init;`, a plain property reference that
29
+ * never invokes the lifecycle hook. The symptom is silent: `wire` reports
30
+ * success and the browser-init block looks plausible, but the hook never
31
+ * fires at runtime.
33
32
  */
34
33
  export function coerceToCall(expression) {
35
34
  return expression.endsWith('()') ? expression : `${expression}()`;
@@ -8,33 +8,32 @@
8
8
  * The upstream xpcshell harness computes the manifest key for the appdir
9
9
  * override as `mozInfo["appname"] + "-appdir"`. On a stock Firefox build the
10
10
  * key is `firefox-appdir`, so the very common `firefox-appdir = "browser"`
11
- * directive is honoured. On a rebranded fork (appname=`mybrowser`, …) the
12
- * harness looks for `mybrowser-appdir`
13
- * — the literal `firefox-appdir` line is silently ignored, `appPath` falls
14
- * back to `xrePath`, and every `resource:///modules/…` import throws
15
- * `Failed to load resource:///modules/<name>.sys.mjs` because xpcshell now
16
- * resolves the `resource:///` prefix one level above the real app root.
11
+ * directive is honoured. On a rebranded fork (appname=`mybrowser`) the
12
+ * harness looks for `mybrowser-appdir` — the literal `firefox-appdir` line
13
+ * is silently ignored, `appPath` falls back to `xrePath`, and every
14
+ * `resource:///modules/…` import throws `Failed to load
15
+ * resource:///modules/<name>.sys.mjs` because xpcshell resolves the
16
+ * `resource:///` prefix one level above the real app root.
17
17
  *
18
18
  * ## Strategy
19
19
  *
20
20
  * 1. For each test path the operator handed us, find the nearest
21
21
  * `xpcshell.toml`. If none exists, the test is not an xpcshell test and
22
- * nothing to inject.
22
+ * there is nothing to inject.
23
23
  * 2. Read the manifest's `[DEFAULT]` section. Look for `<appname>-appdir`
24
- * first — if present, the harness already finds it and there's nothing to
25
- * do. Fall back to `firefox-appdir`. This ordering matches upstream
26
- * precedence and avoids overriding an operator who already migrated.
24
+ * first — if present, the harness already finds it. Fall back to
25
+ * `firefox-appdir`. This ordering matches upstream precedence and avoids
26
+ * overriding an operator who already migrated.
27
27
  * 3. If only `firefox-appdir` is present and `appname != "firefox"`, compute
28
- * the absolute app dir path against the active `obj-X/dist` tree
29
- * (probing `dist/bin/<value>` first, then any `dist/<bundle>.app/Contents/
30
- * Resources/<value>` for the macOS packaged layout) and return it as
31
- * the value to pass to `--app-path`.
32
- * 4. If multiple test paths disagree on the resolved value (e.g. one
33
- * manifest sets `browser`, another sets `xulrunner`), refuse injection
28
+ * the absolute app dir path against the active `obj-X/dist` tree (probing
29
+ * `dist/bin/<value>` first, then any
30
+ * `dist/<bundle>.app/Contents/Resources/<value>` for the macOS packaged
31
+ * layout) and return it as the value to pass to `--app-path`.
32
+ * 4. If multiple test paths disagree on the resolved value, refuse injection
34
33
  * and return null — the operator can drop down to `--mach-arg`.
35
34
  *
36
- * Operator escape hatches: `--mach-arg=--app-path=…` always wins (handled in
37
- * test.ts; we skip injection when `--app-path=` already appears in the
35
+ * Operator escape hatch: `--mach-arg=--app-path=…` always wins (handled in
36
+ * test.ts, which skips injection when `--app-path=` already appears in the
38
37
  * forwarded args).
39
38
  */
40
39
  /**
@@ -75,15 +74,14 @@ export declare function parseAppdirFromToml(tomlText: string, key: string): {
75
74
  * returns the absolute path of the first sibling `xpcshell.toml` found.
76
75
  * Stops at `engineDir` (inclusive) and returns null on miss.
77
76
  *
78
- * Special-cases `startPath` itself when it already ends with
79
- * `xpcshell.toml` — operators sometimes pass a manifest path directly.
77
+ * Special-cases `startPath` itself when it already ends with `xpcshell.toml`
78
+ * — operators sometimes pass a manifest path directly.
80
79
  *
81
80
  * When `startPath` is a DIRECTORY, the walk starts at the directory itself
82
- * (checking `<dir>/xpcshell.toml` first) rather than at its parent. Field
83
- * report (0.34.0 cycle): a directory whose own manifest is an
84
- * `xpcshell.toml` was classified non-xpcshell — the walk began at the
85
- * parent, missed the manifest, and `fireforge test <dir>` dispatched to
86
- * the mochitest runner, which found no mochitests.
81
+ * (checking `<dir>/xpcshell.toml` first) rather than at its parent.
82
+ * Starting at the parent misses a directory's own manifest, so
83
+ * `fireforge test <dir>` classifies it non-xpcshell and dispatches to the
84
+ * mochitest runner, which finds no mochitests.
87
85
  */
88
86
  export declare function findNearestXpcshellManifest(engineDir: string, startPath: string): Promise<string | null>;
89
87
  /**
@@ -96,32 +94,27 @@ export declare function findNearestXpcshellManifest(engineDir: string, startPath
96
94
  */
97
95
  export declare function readMozinfoAppname(objDirPath: string): Promise<string>;
98
96
  /**
99
- * Probes the obj-dir's `dist/` subtree for the absolute path that the
100
- * harness would have computed if the manifest key had been honoured.
101
- * Returns null when no candidate exists — better to skip injection
102
- * silently than to point the harness at a path that doesn't exist
103
- * (which fails with a different error than the original `firefox-appdir`
104
- * symptom and confuses triage).
97
+ * Probes the obj-dir's `dist/` subtree for the absolute path the harness
98
+ * would have computed if the manifest key had been honoured. Returns null
99
+ * when no candidate exists — better to skip injection silently than to point
100
+ * the harness at a path that does not exist, which fails with a different
101
+ * error than the original symptom and confuses triage.
105
102
  *
106
103
  * Probe order differs by host platform:
107
104
  *
108
- * - **macOS (`darwin`)**: prefer `<objDir>/dist/<App>.app/Contents/Resources/
109
- * <value>` FIRST, then fall back to `<objDir>/dist/bin/<value>`.
110
- * 2026-04-24 eval Finding 8: on macOS `dist/bin` is symlinked to
105
+ * - **macOS (`darwin`)**: prefer
106
+ * `<objDir>/dist/<App>.app/Contents/Resources/<value>` FIRST, then fall
107
+ * back to `<objDir>/dist/bin/<value>`. On macOS `dist/bin` is symlinked to
111
108
  * `dist/<App>.app/Contents/MacOS/` (the *binaries* directory), so
112
- * `dist/bin/browser` actually resolves to `<App>.app/Contents/MacOS/
113
- * browser/`. That is NOT where `resource:///modules/` is rooted — on
114
- * macOS, `-a` for xpcshell must point at the `.app/Contents/Resources/
115
- * <value>` subtree where modules / chrome.manifest live. Returning
116
- * `dist/bin/browser` caused the injected `--app-path` to look
117
- * successful (the info log showed it) but pointed at a directory
118
- * without the modules tree, so every `resource:///modules/…` import
119
- * still threw.
120
- * - **non-macOS**: keep the historical order — `dist/bin/<value>` first,
109
+ * `dist/bin/browser` resolves to `<App>.app/Contents/MacOS/browser/` —
110
+ * NOT where `resource:///modules/` is rooted. Injecting that path looks
111
+ * successful in the log but points at a directory with no modules tree, so
112
+ * every `resource:///modules/…` import still throws.
113
+ * - **non-macOS**: `dist/bin/<value>` first,
121
114
  * `.app/Contents/Resources/<value>` as fallback.
122
115
  *
123
- * On both platforms the final `.app` fallback iterates every `*.app`
124
- * entry because a rebranded fork may pick an arbitrary app name.
116
+ * On both platforms the final `.app` fallback iterates every `*.app` entry
117
+ * because a rebranded fork may pick an arbitrary app name.
125
118
  */
126
119
  export declare function resolveAbsoluteAppPath(objDirAbs: string, relativeAppdir: string): Promise<string | null>;
127
120
  /**
@@ -9,33 +9,32 @@
9
9
  * The upstream xpcshell harness computes the manifest key for the appdir
10
10
  * override as `mozInfo["appname"] + "-appdir"`. On a stock Firefox build the
11
11
  * key is `firefox-appdir`, so the very common `firefox-appdir = "browser"`
12
- * directive is honoured. On a rebranded fork (appname=`mybrowser`, …) the
13
- * harness looks for `mybrowser-appdir`
14
- * — the literal `firefox-appdir` line is silently ignored, `appPath` falls
15
- * back to `xrePath`, and every `resource:///modules/…` import throws
16
- * `Failed to load resource:///modules/<name>.sys.mjs` because xpcshell now
17
- * resolves the `resource:///` prefix one level above the real app root.
12
+ * directive is honoured. On a rebranded fork (appname=`mybrowser`) the
13
+ * harness looks for `mybrowser-appdir` — the literal `firefox-appdir` line
14
+ * is silently ignored, `appPath` falls back to `xrePath`, and every
15
+ * `resource:///modules/…` import throws `Failed to load
16
+ * resource:///modules/<name>.sys.mjs` because xpcshell resolves the
17
+ * `resource:///` prefix one level above the real app root.
18
18
  *
19
19
  * ## Strategy
20
20
  *
21
21
  * 1. For each test path the operator handed us, find the nearest
22
22
  * `xpcshell.toml`. If none exists, the test is not an xpcshell test and
23
- * nothing to inject.
23
+ * there is nothing to inject.
24
24
  * 2. Read the manifest's `[DEFAULT]` section. Look for `<appname>-appdir`
25
- * first — if present, the harness already finds it and there's nothing to
26
- * do. Fall back to `firefox-appdir`. This ordering matches upstream
27
- * precedence and avoids overriding an operator who already migrated.
25
+ * first — if present, the harness already finds it. Fall back to
26
+ * `firefox-appdir`. This ordering matches upstream precedence and avoids
27
+ * overriding an operator who already migrated.
28
28
  * 3. If only `firefox-appdir` is present and `appname != "firefox"`, compute
29
- * the absolute app dir path against the active `obj-X/dist` tree
30
- * (probing `dist/bin/<value>` first, then any `dist/<bundle>.app/Contents/
31
- * Resources/<value>` for the macOS packaged layout) and return it as
32
- * the value to pass to `--app-path`.
33
- * 4. If multiple test paths disagree on the resolved value (e.g. one
34
- * manifest sets `browser`, another sets `xulrunner`), refuse injection
29
+ * the absolute app dir path against the active `obj-X/dist` tree (probing
30
+ * `dist/bin/<value>` first, then any
31
+ * `dist/<bundle>.app/Contents/Resources/<value>` for the macOS packaged
32
+ * layout) and return it as the value to pass to `--app-path`.
33
+ * 4. If multiple test paths disagree on the resolved value, refuse injection
35
34
  * and return null — the operator can drop down to `--mach-arg`.
36
35
  *
37
- * Operator escape hatches: `--mach-arg=--app-path=…` always wins (handled in
38
- * test.ts; we skip injection when `--app-path=` already appears in the
36
+ * Operator escape hatch: `--mach-arg=--app-path=…` always wins (handled in
37
+ * test.ts, which skips injection when `--app-path=` already appears in the
39
38
  * forwarded args).
40
39
  */
41
40
  import { readdir, stat } from 'node:fs/promises';
@@ -106,15 +105,14 @@ function stripQuotes(raw) {
106
105
  * returns the absolute path of the first sibling `xpcshell.toml` found.
107
106
  * Stops at `engineDir` (inclusive) and returns null on miss.
108
107
  *
109
- * Special-cases `startPath` itself when it already ends with
110
- * `xpcshell.toml` — operators sometimes pass a manifest path directly.
108
+ * Special-cases `startPath` itself when it already ends with `xpcshell.toml`
109
+ * — operators sometimes pass a manifest path directly.
111
110
  *
112
111
  * When `startPath` is a DIRECTORY, the walk starts at the directory itself
113
- * (checking `<dir>/xpcshell.toml` first) rather than at its parent. Field
114
- * report (0.34.0 cycle): a directory whose own manifest is an
115
- * `xpcshell.toml` was classified non-xpcshell — the walk began at the
116
- * parent, missed the manifest, and `fireforge test <dir>` dispatched to
117
- * the mochitest runner, which found no mochitests.
112
+ * (checking `<dir>/xpcshell.toml` first) rather than at its parent.
113
+ * Starting at the parent misses a directory's own manifest, so
114
+ * `fireforge test <dir>` classifies it non-xpcshell and dispatches to the
115
+ * mochitest runner, which finds no mochitests.
118
116
  */
119
117
  export async function findNearestXpcshellManifest(engineDir, startPath) {
120
118
  const absStart = resolve(engineDir, startPath);
@@ -164,32 +162,27 @@ export async function readMozinfoAppname(objDirPath) {
164
162
  return 'firefox';
165
163
  }
166
164
  /**
167
- * Probes the obj-dir's `dist/` subtree for the absolute path that the
168
- * harness would have computed if the manifest key had been honoured.
169
- * Returns null when no candidate exists — better to skip injection
170
- * silently than to point the harness at a path that doesn't exist
171
- * (which fails with a different error than the original `firefox-appdir`
172
- * symptom and confuses triage).
165
+ * Probes the obj-dir's `dist/` subtree for the absolute path the harness
166
+ * would have computed if the manifest key had been honoured. Returns null
167
+ * when no candidate exists — better to skip injection silently than to point
168
+ * the harness at a path that does not exist, which fails with a different
169
+ * error than the original symptom and confuses triage.
173
170
  *
174
171
  * Probe order differs by host platform:
175
172
  *
176
- * - **macOS (`darwin`)**: prefer `<objDir>/dist/<App>.app/Contents/Resources/
177
- * <value>` FIRST, then fall back to `<objDir>/dist/bin/<value>`.
178
- * 2026-04-24 eval Finding 8: on macOS `dist/bin` is symlinked to
173
+ * - **macOS (`darwin`)**: prefer
174
+ * `<objDir>/dist/<App>.app/Contents/Resources/<value>` FIRST, then fall
175
+ * back to `<objDir>/dist/bin/<value>`. On macOS `dist/bin` is symlinked to
179
176
  * `dist/<App>.app/Contents/MacOS/` (the *binaries* directory), so
180
- * `dist/bin/browser` actually resolves to `<App>.app/Contents/MacOS/
181
- * browser/`. That is NOT where `resource:///modules/` is rooted — on
182
- * macOS, `-a` for xpcshell must point at the `.app/Contents/Resources/
183
- * <value>` subtree where modules / chrome.manifest live. Returning
184
- * `dist/bin/browser` caused the injected `--app-path` to look
185
- * successful (the info log showed it) but pointed at a directory
186
- * without the modules tree, so every `resource:///modules/…` import
187
- * still threw.
188
- * - **non-macOS**: keep the historical order — `dist/bin/<value>` first,
177
+ * `dist/bin/browser` resolves to `<App>.app/Contents/MacOS/browser/` —
178
+ * NOT where `resource:///modules/` is rooted. Injecting that path looks
179
+ * successful in the log but points at a directory with no modules tree, so
180
+ * every `resource:///modules/…` import still throws.
181
+ * - **non-macOS**: `dist/bin/<value>` first,
189
182
  * `.app/Contents/Resources/<value>` as fallback.
190
183
  *
191
- * On both platforms the final `.app` fallback iterates every `*.app`
192
- * entry because a rebranded fork may pick an arbitrary app name.
184
+ * On both platforms the final `.app` fallback iterates every `*.app` entry
185
+ * because a rebranded fork may pick an arbitrary app name.
193
186
  */
194
187
  export async function resolveAbsoluteAppPath(objDirAbs, relativeAppdir) {
195
188
  const distBinCandidate = join(objDirAbs, 'dist', 'bin', relativeAppdir);