@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.
- package/CHANGELOG.md +126 -0
- package/README.md +10 -1
- package/dist/bin/fireforge.d.ts +4 -9
- package/dist/bin/fireforge.js +42 -40
- package/dist/build-info.json +4 -4
- package/dist/src/cli.js +74 -8
- package/dist/src/commands/bootstrap.js +17 -20
- package/dist/src/commands/build.js +25 -32
- package/dist/src/commands/config.js +34 -41
- package/dist/src/commands/discard.js +8 -9
- package/dist/src/commands/doctor-check-core.d.ts +4 -18
- package/dist/src/commands/doctor-check-core.js +8 -35
- package/dist/src/commands/doctor-external-toolchains.js +2 -2
- package/dist/src/commands/doctor-furnace-config-sync.d.ts +18 -0
- package/dist/src/commands/{doctor-furnace-manifest-sync.js → doctor-furnace-config-sync.js} +27 -26
- package/dist/src/commands/doctor-furnace-jar.d.ts +7 -9
- package/dist/src/commands/doctor-furnace-jar.js +7 -9
- package/dist/src/commands/doctor-furnace.js +21 -24
- package/dist/src/commands/doctor-orphaned-harness.d.ts +16 -20
- package/dist/src/commands/doctor-orphaned-harness.js +18 -44
- package/dist/src/commands/doctor-post-rebase-audit.d.ts +2 -0
- package/dist/src/commands/{doctor/post-rebase-audit.js → doctor-post-rebase-audit.js} +3 -3
- package/dist/src/commands/doctor-working-tree.d.ts +10 -12
- package/dist/src/commands/doctor-working-tree.js +11 -18
- package/dist/src/commands/doctor.js +35 -53
- package/dist/src/commands/download.js +32 -48
- package/dist/src/commands/export-all.js +29 -33
- package/dist/src/commands/export-flow.js +6 -6
- package/dist/src/commands/export-placement-conflicts.js +10 -9
- package/dist/src/commands/export-placement-gate.js +5 -5
- package/dist/src/commands/export-shared.d.ts +30 -33
- package/dist/src/commands/export-shared.js +45 -43
- package/dist/src/commands/export.js +21 -27
- package/dist/src/commands/furnace/apply.js +14 -23
- package/dist/src/commands/furnace/chrome-doc-remove.js +14 -21
- package/dist/src/commands/furnace/chrome-doc-templates.d.ts +23 -23
- package/dist/src/commands/furnace/chrome-doc-templates.js +23 -23
- package/dist/src/commands/furnace/chrome-doc-tests.js +26 -29
- package/dist/src/commands/furnace/chrome-doc.d.ts +16 -17
- package/dist/src/commands/furnace/chrome-doc.js +31 -41
- package/dist/src/commands/furnace/create-browser-test.d.ts +4 -4
- package/dist/src/commands/furnace/create-browser-test.js +8 -8
- package/dist/src/commands/furnace/create-mochikit.d.ts +6 -7
- package/dist/src/commands/furnace/create-mochikit.js +8 -9
- package/dist/src/commands/furnace/create-readback.d.ts +12 -13
- package/dist/src/commands/furnace/create-readback.js +12 -13
- package/dist/src/commands/furnace/create-templates.d.ts +22 -28
- package/dist/src/commands/furnace/create-templates.js +35 -30
- package/dist/src/commands/furnace/create-xpcshell.js +2 -2
- package/dist/src/commands/furnace/create.js +33 -23
- package/dist/src/commands/furnace/deploy.js +16 -24
- package/dist/src/commands/furnace/diff.js +9 -9
- package/dist/src/commands/furnace/init.js +33 -36
- package/dist/src/commands/furnace/override.js +23 -25
- package/dist/src/commands/furnace/preview.js +47 -67
- package/dist/src/commands/furnace/refresh.js +12 -16
- package/dist/src/commands/furnace/remove-mutations.d.ts +3 -6
- package/dist/src/commands/furnace/remove-mutations.js +9 -16
- package/dist/src/commands/furnace/remove-state.js +1 -1
- package/dist/src/commands/furnace/remove.js +33 -38
- package/dist/src/commands/furnace/rename-xpcshell.d.ts +8 -11
- package/dist/src/commands/furnace/rename-xpcshell.js +8 -11
- package/dist/src/commands/furnace/rename.js +59 -69
- package/dist/src/commands/furnace/scan.js +19 -33
- package/dist/src/commands/furnace/status.js +12 -9
- package/dist/src/commands/furnace/sync.js +9 -16
- package/dist/src/commands/furnace/validate.js +20 -20
- package/dist/src/commands/import.js +42 -35
- package/dist/src/commands/lint-per-patch.js +15 -10
- package/dist/src/commands/lint-per-run-checkjs.d.ts +13 -13
- package/dist/src/commands/lint-per-run-checkjs.js +13 -13
- package/dist/src/commands/lint-report.js +6 -7
- package/dist/src/commands/lint.d.ts +15 -16
- package/dist/src/commands/lint.js +86 -102
- package/dist/src/commands/package.js +6 -11
- package/dist/src/commands/patch/compact.js +1 -1
- package/dist/src/commands/patch/delete.js +24 -33
- package/dist/src/commands/patch/index.d.ts +5 -6
- package/dist/src/commands/patch/index.js +10 -12
- package/dist/src/commands/patch/lint-ignore.js +14 -13
- package/dist/src/commands/patch/move-files-create.d.ts +6 -6
- package/dist/src/commands/patch/move-files-create.js +8 -8
- package/dist/src/commands/patch/move-files-into.d.ts +6 -6
- package/dist/src/commands/patch/move-files-into.js +8 -8
- package/dist/src/commands/patch/patch-context.d.ts +2 -3
- package/dist/src/commands/patch/patch-context.js +2 -3
- package/dist/src/commands/patch/rename.d.ts +10 -11
- package/dist/src/commands/patch/rename.js +11 -12
- package/dist/src/commands/patch/reorder.js +8 -9
- package/dist/src/commands/patch/split-plan.js +1 -1
- package/dist/src/commands/patch/split.d.ts +8 -10
- package/dist/src/commands/patch/split.js +9 -11
- package/dist/src/commands/patch/staged-dependency-validate.js +8 -8
- package/dist/src/commands/patch/staged-dependency.js +7 -3
- package/dist/src/commands/patch/tier.d.ts +9 -9
- package/dist/src/commands/patch/tier.js +18 -15
- package/dist/src/commands/re-export-adjacent.js +9 -8
- package/dist/src/commands/re-export-bulk-scan.d.ts +9 -9
- package/dist/src/commands/re-export-bulk-scan.js +22 -21
- package/dist/src/commands/re-export-drift.js +10 -10
- package/dist/src/commands/re-export-files.d.ts +6 -7
- package/dist/src/commands/re-export-files.js +34 -44
- package/dist/src/commands/re-export-lint.d.ts +10 -13
- package/dist/src/commands/re-export-lint.js +16 -14
- package/dist/src/commands/re-export-options.d.ts +6 -6
- package/dist/src/commands/re-export-options.js +6 -6
- package/dist/src/commands/re-export-register.d.ts +4 -10
- package/dist/src/commands/re-export-register.js +5 -11
- package/dist/src/commands/re-export-scan.js +1 -1
- package/dist/src/commands/re-export-single.d.ts +3 -3
- package/dist/src/commands/re-export-single.js +33 -25
- package/dist/src/commands/re-export.js +13 -21
- package/dist/src/commands/rebase/abort.js +3 -3
- package/dist/src/commands/rebase/confirm.js +2 -1
- package/dist/src/commands/rebase/continue.d.ts +1 -1
- package/dist/src/commands/rebase/continue.js +14 -9
- package/dist/src/commands/rebase/index.js +11 -11
- package/dist/src/commands/rebase/patch-loop.d.ts +7 -1
- package/dist/src/commands/rebase/patch-loop.js +60 -39
- package/dist/src/commands/rebase/summary.js +1 -1
- package/dist/src/commands/register.js +5 -7
- package/dist/src/commands/reset.js +2 -1
- package/dist/src/commands/resolve.d.ts +16 -13
- package/dist/src/commands/resolve.js +30 -33
- package/dist/src/commands/run.js +33 -35
- package/dist/src/commands/setup-support.js +15 -19
- package/dist/src/commands/setup.js +13 -9
- package/dist/src/commands/status-check.d.ts +6 -6
- package/dist/src/commands/status-json.d.ts +6 -6
- package/dist/src/commands/status-json.js +5 -0
- package/dist/src/commands/status-output.d.ts +5 -5
- package/dist/src/commands/status-output.js +6 -6
- package/dist/src/commands/status-ownership.d.ts +16 -14
- package/dist/src/commands/status-ownership.js +16 -14
- package/dist/src/commands/status.js +42 -34
- package/dist/src/commands/test-build-phase.js +26 -13
- package/dist/src/commands/test-diagnose.js +44 -44
- package/dist/src/commands/test-register.js +1 -0
- package/dist/src/commands/test-run.d.ts +14 -16
- package/dist/src/commands/test-run.js +21 -13
- package/dist/src/commands/test-stale-gate.d.ts +15 -16
- package/dist/src/commands/test-stale-gate.js +15 -16
- package/dist/src/commands/test-verdict.d.ts +20 -3
- package/dist/src/commands/test-verdict.js +30 -0
- package/dist/src/commands/test.js +83 -76
- package/dist/src/commands/token-coverage.js +3 -4
- package/dist/src/commands/token.js +16 -18
- package/dist/src/commands/tree.js +47 -31
- package/dist/src/commands/typecheck.d.ts +10 -12
- package/dist/src/commands/typecheck.js +24 -27
- package/dist/src/commands/verify.js +13 -15
- package/dist/src/commands/watch.js +21 -23
- package/dist/src/commands/wire.js +52 -62
- package/dist/src/core/ast-utils.d.ts +8 -7
- package/dist/src/core/ast-utils.js +8 -7
- package/dist/src/core/branding.d.ts +9 -14
- package/dist/src/core/branding.js +7 -11
- package/dist/src/core/browser-wire.d.ts +1 -1
- package/dist/src/core/browser-wire.js +14 -19
- package/dist/src/core/build-audit-platform.js +25 -33
- package/dist/src/core/build-audit-registration.js +17 -25
- package/dist/src/core/build-audit-resolve.d.ts +15 -17
- package/dist/src/core/build-audit-resolve.js +27 -33
- package/dist/src/core/build-audit-transforms.js +18 -19
- package/dist/src/core/build-audit.js +28 -42
- package/dist/src/core/build-baseline-types.d.ts +29 -35
- package/dist/src/core/build-baseline.d.ts +5 -4
- package/dist/src/core/build-baseline.js +14 -14
- package/dist/src/core/build-overwrite-guard.d.ts +7 -14
- package/dist/src/core/build-overwrite-guard.js +17 -27
- package/dist/src/core/build-prepare.d.ts +2 -2
- package/dist/src/core/build-prepare.js +8 -9
- package/dist/src/core/config-state.js +12 -4
- package/dist/src/core/config-validate.js +8 -5
- package/dist/src/core/config.d.ts +5 -8
- package/dist/src/core/config.js +7 -16
- package/dist/src/core/coverage-extend.d.ts +15 -13
- package/dist/src/core/coverage-extend.js +15 -13
- package/dist/src/core/destructive.d.ts +31 -9
- package/dist/src/core/destructive.js +29 -26
- package/dist/src/core/diff-hunks.js +10 -12
- package/dist/src/core/discard-baseline.d.ts +8 -8
- package/dist/src/core/discard-baseline.js +16 -15
- package/dist/src/core/display-state.d.ts +12 -14
- package/dist/src/core/display-state.js +12 -14
- package/dist/src/core/engine-changes.d.ts +2 -4
- package/dist/src/core/engine-changes.js +2 -4
- package/dist/src/core/engine-precondition.d.ts +28 -13
- package/dist/src/core/engine-precondition.js +25 -10
- package/dist/src/core/engine-session-lock.d.ts +47 -21
- package/dist/src/core/engine-session-lock.js +168 -33
- package/dist/src/core/export-moved-code-shape.d.ts +10 -10
- package/dist/src/core/export-moved-code-shape.js +10 -10
- package/dist/src/core/file-lock.d.ts +62 -5
- package/dist/src/core/file-lock.js +196 -59
- package/dist/src/core/firefox-cache.js +1 -3
- package/dist/src/core/firefox-extract.js +10 -14
- package/dist/src/core/firefox.d.ts +7 -5
- package/dist/src/core/firefox.js +4 -5
- package/dist/src/core/furnace-apply-dry-run.d.ts +2 -2
- package/dist/src/core/furnace-apply-dry-run.js +3 -2
- package/dist/src/core/furnace-apply-ftl.d.ts +7 -9
- package/dist/src/core/furnace-apply-ftl.js +12 -12
- package/dist/src/core/furnace-apply-helpers.d.ts +7 -7
- package/dist/src/core/furnace-apply-helpers.js +19 -16
- package/dist/src/core/furnace-apply-overwrite-warn.d.ts +8 -9
- package/dist/src/core/furnace-apply-overwrite-warn.js +8 -9
- package/dist/src/core/furnace-apply-undeploy-actions.d.ts +3 -4
- package/dist/src/core/furnace-apply-undeploy-actions.js +3 -4
- package/dist/src/core/furnace-apply.d.ts +5 -8
- package/dist/src/core/furnace-apply.js +19 -24
- package/dist/src/core/furnace-checksum-utils.d.ts +14 -0
- package/dist/src/core/furnace-checksum-utils.js +16 -0
- package/dist/src/core/furnace-config.d.ts +21 -30
- package/dist/src/core/furnace-config.js +32 -54
- package/dist/src/core/furnace-constants.d.ts +8 -0
- package/dist/src/core/furnace-constants.js +10 -2
- package/dist/src/core/furnace-css-fragments.d.ts +5 -5
- package/dist/src/core/furnace-css-fragments.js +5 -5
- package/dist/src/core/furnace-jsconfig.d.ts +11 -12
- package/dist/src/core/furnace-jsconfig.js +11 -12
- package/dist/src/core/furnace-marker.d.ts +7 -8
- package/dist/src/core/furnace-marker.js +7 -8
- package/dist/src/core/furnace-operation.d.ts +31 -0
- package/dist/src/core/furnace-operation.js +54 -17
- package/dist/src/core/furnace-precondition.d.ts +61 -0
- package/dist/src/core/furnace-precondition.js +67 -0
- package/dist/src/core/furnace-registration-remove.d.ts +5 -6
- package/dist/src/core/furnace-registration-remove.js +6 -7
- package/dist/src/core/furnace-registration-validate.d.ts +13 -0
- package/dist/src/core/furnace-registration-validate.js +20 -1
- package/dist/src/core/furnace-registration.d.ts +5 -6
- package/dist/src/core/furnace-registration.js +10 -12
- package/dist/src/core/furnace-rollback.js +7 -7
- package/dist/src/core/furnace-scanner.d.ts +1 -0
- package/dist/src/core/furnace-scanner.js +1 -2
- package/dist/src/core/furnace-stale-export.d.ts +10 -10
- package/dist/src/core/furnace-stale-export.js +10 -10
- package/dist/src/core/furnace-state-persist.d.ts +6 -8
- package/dist/src/core/furnace-state-persist.js +6 -8
- package/dist/src/core/furnace-validate-accessibility.d.ts +22 -0
- package/dist/src/core/furnace-validate-accessibility.js +310 -1
- package/dist/src/core/furnace-validate-compatibility.js +141 -1
- package/dist/src/core/furnace-validate-helpers.d.ts +5 -116
- package/dist/src/core/furnace-validate-helpers.js +0 -491
- package/dist/src/core/furnace-validate-registration.d.ts +7 -0
- package/dist/src/core/furnace-validate-registration.js +115 -41
- package/dist/src/core/furnace-validate.d.ts +16 -0
- package/dist/src/core/furnace-validate.js +188 -145
- package/dist/src/core/furnace-version-drift.d.ts +10 -11
- package/dist/src/core/furnace-version-drift.js +10 -11
- package/dist/src/core/git-base.d.ts +7 -9
- package/dist/src/core/git-base.js +7 -9
- package/dist/src/core/git-diff.d.ts +20 -9
- package/dist/src/core/git-diff.js +148 -63
- package/dist/src/core/git-file-ops.d.ts +19 -19
- package/dist/src/core/git-file-ops.js +19 -19
- package/dist/src/core/git-readonly-index.d.ts +53 -19
- package/dist/src/core/git-readonly-index.js +75 -31
- package/dist/src/core/git-status.d.ts +5 -6
- package/dist/src/core/git-status.js +5 -6
- package/dist/src/core/git.d.ts +9 -10
- package/dist/src/core/git.js +54 -70
- package/dist/src/core/license-headers.d.ts +17 -23
- package/dist/src/core/license-headers.js +17 -23
- package/dist/src/core/mach-build-artifacts.d.ts +9 -9
- package/dist/src/core/mach-build-artifacts.js +57 -19
- package/dist/src/core/mach-error-hints.js +42 -29
- package/dist/src/core/mach-known-noise-filter.d.ts +15 -16
- package/dist/src/core/mach-known-noise-filter.js +18 -20
- package/dist/src/core/mach-mozconfig.d.ts +14 -0
- package/dist/src/core/mach-mozconfig.js +30 -0
- package/dist/src/core/mach-resource-shim.d.ts +43 -58
- package/dist/src/core/mach-resource-shim.js +50 -67
- package/dist/src/core/mach.d.ts +37 -41
- package/dist/src/core/mach.js +50 -51
- package/dist/src/core/marionette-port.d.ts +36 -1
- package/dist/src/core/marionette-port.js +96 -31
- package/dist/src/core/marionette-preflight.d.ts +8 -12
- package/dist/src/core/marionette-preflight.js +86 -52
- package/dist/src/core/mochitest-server-port.d.ts +42 -0
- package/dist/src/core/mochitest-server-port.js +119 -0
- package/dist/src/core/module-resolution-preflight.d.ts +9 -11
- package/dist/src/core/module-resolution-preflight.js +9 -11
- package/dist/src/core/moz-manifest-helpers.d.ts +79 -0
- package/dist/src/core/moz-manifest-helpers.js +163 -0
- package/dist/src/core/{manifest-register.d.ts → moz-manifest-register.d.ts} +1 -1
- package/dist/src/core/{manifest-register.js → moz-manifest-register.js} +13 -28
- package/dist/src/core/{manifest-rules.d.ts → moz-manifest-rules.d.ts} +10 -1
- package/dist/src/core/{manifest-rules.js → moz-manifest-rules.js} +31 -24
- package/dist/src/core/{manifest-tokenizers.d.ts → moz-manifest-tokenizers.d.ts} +3 -5
- package/dist/src/core/{manifest-tokenizers.js → moz-manifest-tokenizers.js} +9 -12
- package/dist/src/core/ownership-table.d.ts +14 -16
- package/dist/src/core/ownership-table.js +14 -16
- package/dist/src/core/parser-fallback.d.ts +15 -1
- package/dist/src/core/parser-fallback.js +22 -3
- package/dist/src/core/patch-apply-fuzz.d.ts +10 -12
- package/dist/src/core/patch-apply-fuzz.js +15 -18
- package/dist/src/core/patch-apply.d.ts +13 -34
- package/dist/src/core/patch-apply.js +16 -76
- package/dist/src/core/patch-artifact-normalize.d.ts +13 -15
- package/dist/src/core/patch-artifact-normalize.js +13 -15
- package/dist/src/core/patch-export-metadata.d.ts +12 -2
- package/dist/src/core/patch-export-metadata.js +13 -4
- package/dist/src/core/patch-export-update.d.ts +13 -1
- package/dist/src/core/patch-export-update.js +25 -8
- package/dist/src/core/patch-export.d.ts +15 -8
- package/dist/src/core/patch-export.js +10 -11
- package/dist/src/core/patch-files.d.ts +5 -6
- package/dist/src/core/patch-files.js +5 -6
- package/dist/src/core/patch-identifier-suggest.d.ts +7 -12
- package/dist/src/core/patch-identifier-suggest.js +14 -19
- package/dist/src/core/patch-lint-binary.d.ts +51 -0
- package/dist/src/core/patch-lint-binary.js +39 -0
- package/dist/src/core/{lint-cache.d.ts → patch-lint-cache.d.ts} +5 -5
- package/dist/src/core/{lint-cache.js → patch-lint-cache.js} +21 -23
- package/dist/src/core/patch-lint-checkjs.d.ts +16 -16
- package/dist/src/core/patch-lint-checkjs.js +16 -16
- package/dist/src/core/patch-lint-chrome-jsdoc.d.ts +6 -9
- package/dist/src/core/patch-lint-chrome-jsdoc.js +10 -14
- package/dist/src/core/patch-lint-creators.d.ts +8 -8
- package/dist/src/core/patch-lint-creators.js +8 -8
- package/dist/src/core/patch-lint-cross.d.ts +17 -20
- package/dist/src/core/patch-lint-cross.js +16 -16
- package/dist/src/core/patch-lint-css.d.ts +3 -5
- package/dist/src/core/patch-lint-css.js +17 -22
- package/dist/src/core/patch-lint-diff-tag.d.ts +14 -16
- package/dist/src/core/patch-lint-diff-tag.js +14 -16
- package/dist/src/core/patch-lint-jsdoc.d.ts +7 -8
- package/dist/src/core/patch-lint-jsdoc.js +26 -19
- package/dist/src/core/patch-lint-mozbuild.js +20 -20
- package/dist/src/core/patch-lint-observer.d.ts +7 -7
- package/dist/src/core/patch-lint-observer.js +7 -7
- package/dist/src/core/patch-lint.d.ts +38 -29
- package/dist/src/core/patch-lint.js +89 -121
- package/dist/src/core/patch-lock.d.ts +1 -1
- package/dist/src/core/patch-lock.js +45 -9
- package/dist/src/core/patch-manifest-consistency.d.ts +2 -1
- package/dist/src/core/patch-manifest-consistency.js +25 -27
- package/dist/src/core/patch-manifest-io.js +14 -18
- package/dist/src/core/patch-manifest-resolve.d.ts +9 -12
- package/dist/src/core/patch-manifest-resolve.js +9 -12
- package/dist/src/core/patch-manifest-validate.d.ts +6 -1
- package/dist/src/core/patch-manifest-validate.js +25 -13
- package/dist/src/core/patch-parse.d.ts +24 -13
- package/dist/src/core/patch-parse.js +19 -14
- package/dist/src/core/patch-policy.d.ts +2 -2
- package/dist/src/core/patch-policy.js +2 -2
- package/dist/src/core/patch-registration-refs.d.ts +7 -8
- package/dist/src/core/patch-registration-refs.js +9 -9
- package/dist/src/core/process-cpu-time.d.ts +12 -0
- package/dist/src/core/process-cpu-time.js +52 -0
- package/dist/src/core/rebase-session.d.ts +38 -26
- package/dist/src/core/rebase-session.js +55 -28
- package/dist/src/core/register-browser-content.js +9 -74
- package/dist/src/core/{register-test-manifest.js → register-browser-test.js} +7 -42
- package/dist/src/core/register-module.js +10 -43
- package/dist/src/core/register-scaffold.d.ts +8 -8
- package/dist/src/core/register-scaffold.js +10 -10
- package/dist/src/core/register-shared-css.d.ts +9 -12
- package/dist/src/core/register-shared-css.js +17 -87
- package/dist/src/core/register-xpcshell-test.d.ts +6 -7
- package/dist/src/core/register-xpcshell-test.js +7 -8
- package/dist/src/core/shared-ftl.js +12 -4
- package/dist/src/core/state-file.d.ts +45 -0
- package/dist/src/core/state-file.js +34 -0
- package/dist/src/core/status-binary.d.ts +18 -11
- package/dist/src/core/status-binary.js +19 -12
- package/dist/src/core/status-classify.d.ts +30 -36
- package/dist/src/core/status-classify.js +21 -26
- package/dist/src/core/test-changed-prefs.d.ts +30 -0
- package/dist/src/core/test-changed-prefs.js +78 -0
- package/dist/src/core/test-harness-crash.d.ts +25 -63
- package/dist/src/core/test-harness-crash.js +121 -142
- package/dist/src/core/test-harness-signature.d.ts +18 -0
- package/dist/src/core/test-harness-signature.js +13 -0
- package/dist/src/core/test-path-scope.d.ts +12 -15
- package/dist/src/core/test-path-scope.js +15 -18
- package/dist/src/core/test-stale-check.d.ts +17 -17
- package/dist/src/core/test-stale-check.js +50 -43
- package/dist/src/core/test-stall-triage.d.ts +51 -0
- package/dist/src/core/test-stall-triage.js +126 -0
- package/dist/src/core/token-category.js +5 -7
- package/dist/src/core/token-coverage.js +9 -9
- package/dist/src/core/token-dark-mode.d.ts +9 -11
- package/dist/src/core/token-dark-mode.js +9 -11
- package/dist/src/core/token-docs.d.ts +2 -0
- package/dist/src/core/token-docs.js +2 -0
- package/dist/src/core/token-manager.d.ts +10 -2
- package/dist/src/core/token-manager.js +17 -8
- package/dist/src/core/token-scaffold.d.ts +7 -7
- package/dist/src/core/token-scaffold.js +7 -7
- package/dist/src/core/token-variant.d.ts +4 -4
- package/dist/src/core/token-variant.js +4 -4
- package/dist/src/core/toolchain-preflight.d.ts +20 -21
- package/dist/src/core/toolchain-preflight.js +28 -31
- package/dist/src/core/tree-guard.js +12 -2
- package/dist/src/core/tree-store.d.ts +41 -27
- package/dist/src/core/tree-store.js +63 -42
- package/dist/src/core/typecheck-shim.d.ts +23 -24
- package/dist/src/core/typecheck-shim.js +23 -24
- package/dist/src/core/typecheck.js +8 -8
- package/dist/src/core/wire-destroy.d.ts +3 -3
- package/dist/src/core/wire-destroy.js +7 -15
- package/dist/src/core/wire-dom-fragment.d.ts +9 -17
- package/dist/src/core/wire-dom-fragment.js +11 -44
- package/dist/src/core/wire-init.d.ts +2 -3
- package/dist/src/core/wire-init.js +8 -19
- package/dist/src/core/wire-subscript.d.ts +2 -3
- package/dist/src/core/wire-subscript.js +4 -13
- package/dist/src/core/wire-utils.d.ts +7 -8
- package/dist/src/core/wire-utils.js +7 -8
- package/dist/src/core/xpcshell-appdir.d.ts +38 -45
- package/dist/src/core/xpcshell-appdir.js +38 -45
- package/dist/src/errors/base.d.ts +37 -16
- package/dist/src/errors/base.js +37 -16
- package/dist/src/errors/build.d.ts +13 -1
- package/dist/src/errors/build.js +14 -2
- package/dist/src/errors/codes.d.ts +16 -0
- package/dist/src/errors/codes.js +16 -0
- package/dist/src/errors/furnace.d.ts +4 -4
- package/dist/src/errors/git.d.ts +6 -10
- package/dist/src/errors/git.js +6 -10
- package/dist/src/errors/patch.d.ts +7 -7
- package/dist/src/errors/patch.js +7 -7
- package/dist/src/errors/rebase.d.ts +4 -4
- package/dist/src/errors/rebase.js +4 -4
- package/dist/src/index.d.ts +7 -1
- package/dist/src/index.js +5 -0
- package/dist/src/types/commands/index.d.ts +2 -2
- package/dist/src/types/commands/options.d.ts +88 -70
- package/dist/src/types/commands/patches.d.ts +24 -34
- package/dist/src/types/commands/project.d.ts +5 -34
- package/dist/src/types/config.d.ts +25 -23
- package/dist/src/types/config.js +6 -1
- package/dist/src/types/furnace.d.ts +37 -13
- package/dist/src/types/furnace.js +19 -1
- package/dist/src/types/index.d.ts +3 -3
- package/dist/src/utils/build-info.d.ts +7 -8
- package/dist/src/utils/build-info.js +12 -11
- package/dist/src/utils/errors.d.ts +6 -8
- package/dist/src/utils/errors.js +6 -8
- package/dist/src/utils/logger.d.ts +27 -10
- package/dist/src/utils/logger.js +28 -16
- package/dist/src/utils/machine-output.d.ts +12 -0
- package/dist/src/utils/machine-output.js +33 -0
- package/dist/src/utils/options.d.ts +31 -14
- package/dist/src/utils/options.js +86 -30
- package/dist/src/utils/paths.d.ts +10 -8
- package/dist/src/utils/paths.js +10 -8
- package/dist/src/utils/platform.d.ts +0 -25
- package/dist/src/utils/platform.js +1 -42
- package/dist/src/utils/process-group.d.ts +9 -4
- package/dist/src/utils/process-group.js +19 -5
- package/dist/src/utils/process.d.ts +42 -7
- package/dist/src/utils/process.js +44 -17
- package/dist/src/utils/ps-duration.d.ts +31 -0
- package/dist/src/utils/ps-duration.js +70 -0
- package/dist/src/utils/regex.d.ts +9 -10
- package/dist/src/utils/regex.js +9 -10
- package/dist/src/utils/validation.d.ts +58 -28
- package/dist/src/utils/validation.js +60 -33
- package/package.json +2 -2
- package/dist/src/commands/doctor/post-rebase-audit.d.ts +0 -2
- package/dist/src/commands/doctor-furnace-manifest-sync.d.ts +0 -18
- package/dist/src/core/manifest-helpers.d.ts +0 -38
- package/dist/src/core/manifest-helpers.js +0 -120
- /package/dist/src/core/{lint-projection.d.ts → patch-lint-projection.d.ts} +0 -0
- /package/dist/src/core/{lint-projection.js → patch-lint-projection.js} +0 -0
- /package/dist/src/core/{register-test-manifest.d.ts → register-browser-test.d.ts} +0 -0
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
2
|
import { join, resolve } from 'node:path';
|
|
3
3
|
import { getProjectPaths, loadConfig } from '../core/config.js';
|
|
4
|
+
import { assertEngineExists } from '../core/engine-precondition.js';
|
|
4
5
|
import { assertEngineGenerationUnchanged, snapshotEngineGeneration, } from '../core/engine-session-lock.js';
|
|
5
6
|
import { hasBuildArtifacts, hasRunnableBundle } from '../core/mach.js';
|
|
6
7
|
import { assertBuildArtifacts } from '../core/mach-build-artifacts.js';
|
|
7
8
|
import { assertMarionettePortAvailable, ensureLaunchableBrowserNotRunning, ensureMarionettePortAvailable, extractForwardedMarionettePort, forwardedMachArgsIncludeMarionetteClient, shouldAutoForwardMarionettePortToMach, } from '../core/marionette-port.js';
|
|
8
9
|
import { formatMarionettePreflightLine, reportMarionettePreflight, runMarionettePreflight, } from '../core/marionette-preflight.js';
|
|
10
|
+
import { ensureMochitestServerPortAvailable } from '../core/mochitest-server-port.js';
|
|
9
11
|
import { createPostRebuildFailureContext } from '../core/test-harness-output.js';
|
|
10
12
|
import { analyzeTestPathScopes, formatScopeNotice, } from '../core/test-path-scope.js';
|
|
11
13
|
import { assertObjdirMatchesTreeMarker } from '../core/tree-store.js';
|
|
12
14
|
import { GeneralError } from '../errors/base.js';
|
|
13
15
|
import { BuildError } from '../errors/build.js';
|
|
14
16
|
import { pathExists } from '../utils/fs.js';
|
|
15
|
-
import { info, intro, notice, outro,
|
|
17
|
+
import { info, intro, notice, outro, verbose } from '../utils/logger.js';
|
|
16
18
|
import { stripEnginePrefix } from '../utils/paths.js';
|
|
17
19
|
import { runTestBuildPhase } from './test-build-phase.js';
|
|
18
20
|
import { diagnoseShardOutcome, finalizeSingleRunOutcome } from './test-diagnose.js';
|
|
@@ -36,8 +38,8 @@ async function assertTestPathsExist(engineDir, testPaths) {
|
|
|
36
38
|
* Picks the mach dispatch target for a (non-mixed) run. A single-suite run
|
|
37
39
|
* auto-routes to the suite-specific command (`mach xpcshell-test` /
|
|
38
40
|
* `mach mochitest`), which degrades a broken host resource monitor to a
|
|
39
|
-
* warning instead of crashing generic `mach test` at startup
|
|
40
|
-
*
|
|
41
|
+
* warning instead of crashing generic `mach test` at startup. Mixed runs are
|
|
42
|
+
* rejected before this point; a path-less "run all" or an explicit
|
|
41
43
|
* `--generic-mach-test` opt-out stays on the generic command.
|
|
42
44
|
*/
|
|
43
45
|
function resolveTestSuite(classification, forceGeneric) {
|
|
@@ -102,27 +104,30 @@ function logTestSelection(scopes) {
|
|
|
102
104
|
*/
|
|
103
105
|
async function runDoctorPreflight(args) {
|
|
104
106
|
const { engineDir, effectivePort, hasTestPaths, objDir, binaryName, launchablePath } = args;
|
|
105
|
-
//
|
|
106
|
-
//
|
|
107
|
-
//
|
|
108
|
-
//
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
107
|
+
// Non-TTY captures need the banner even if clack's renderer defers output
|
|
108
|
+
// in pipe mode; TTY users need the clack framing. Gated rather than
|
|
109
|
+
// written twice — the unconditional pair printed the same line twice on a
|
|
110
|
+
// terminal.
|
|
111
|
+
if (process.stdout.isTTY) {
|
|
112
|
+
info('Running marionette preflight...');
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
process.stdout.write('Running marionette preflight...\n');
|
|
116
|
+
}
|
|
112
117
|
const preflight = effectivePort !== undefined
|
|
113
118
|
? await runMarionettePreflight(engineDir, { port: effectivePort })
|
|
114
119
|
: await runMarionettePreflight(engineDir);
|
|
115
|
-
//
|
|
116
|
-
//
|
|
117
|
-
//
|
|
118
|
-
//
|
|
119
|
-
//
|
|
120
|
-
//
|
|
121
|
-
//
|
|
122
|
-
// matter what clack does on top. The clack-rendered banner
|
|
123
|
-
// (`info`/`warn`) is retained so TTY users keep the visual framing.
|
|
120
|
+
// The authoritative PASS/FAIL line is written with `process.stdout.write`
|
|
121
|
+
// as the first output after the probe returns, because clack's renderer
|
|
122
|
+
// can drop the summary under non-TTY capture.
|
|
123
|
+
//
|
|
124
|
+
// Gated on non-TTY: unconditional, it stacks with the two clack renderings
|
|
125
|
+
// below and the same line appears THREE times on a terminal. Captured
|
|
126
|
+
// streams are exactly where this branch still fires.
|
|
124
127
|
const directLine = formatMarionettePreflightLine(preflight);
|
|
125
|
-
process.stdout.
|
|
128
|
+
if (!process.stdout.isTTY) {
|
|
129
|
+
process.stdout.write(`${directLine}\n`);
|
|
130
|
+
}
|
|
126
131
|
process.stdout.write(`Marionette preflight environment: objdir=${objDir ?? '(none)'}; binary=${binaryName}; app=${launchablePath ? `engine/${launchablePath}` : '(unknown)'}; port=${effectivePort ?? 2828}; elapsed=${preflight.durationMs}ms\n`);
|
|
127
132
|
reportMarionettePreflight(preflight);
|
|
128
133
|
if (!hasTestPaths) {
|
|
@@ -130,7 +135,6 @@ async function runDoctorPreflight(args) {
|
|
|
130
135
|
emitFailVerdict('preflight');
|
|
131
136
|
throw new GeneralError('Marionette preflight reported FAIL — see output above.');
|
|
132
137
|
}
|
|
133
|
-
success(directLine);
|
|
134
138
|
// Doctor-only runs end here, so they carry their own verdict line
|
|
135
139
|
// (reason=preflight on failure); with test paths the verdict comes
|
|
136
140
|
// from the actual harness run downstream.
|
|
@@ -152,19 +156,19 @@ async function runDoctorPreflight(args) {
|
|
|
152
156
|
* Mutates `extraArgs` in place.
|
|
153
157
|
*/
|
|
154
158
|
function appendMarionetteForwardingArgs(extraArgs, options, forwardedPort, xpcshellOnly = false) {
|
|
155
|
-
// Auto-forward the Marionette port to mach when `--marionette-port` is
|
|
156
|
-
//
|
|
157
|
-
//
|
|
158
|
-
//
|
|
159
|
-
//
|
|
159
|
+
// Auto-forward the Marionette port to mach when `--marionette-port` is set.
|
|
160
|
+
// `--setpref=marionette.port=<n>` configures where the browser listener
|
|
161
|
+
// binds; `--marionette=127.0.0.1:<n>` tells the mochitest harness client to
|
|
162
|
+
// connect there (default client is 127.0.0.1:2828). xpcshell ignores both
|
|
163
|
+
// for browser Marionette.
|
|
160
164
|
//
|
|
161
165
|
// Skip setpref forwarding when the operator already supplied an equivalent
|
|
162
|
-
// arg via `--mach-arg` — duplicates would
|
|
163
|
-
// semantics. Skip when mach args explicitly request `--flavor=xpcshell`
|
|
164
|
-
//
|
|
165
|
-
//
|
|
166
|
-
//
|
|
167
|
-
//
|
|
166
|
+
// arg via `--mach-arg` — duplicates would confuse without changing
|
|
167
|
+
// semantics. Skip when mach args explicitly request `--flavor=xpcshell` (or
|
|
168
|
+
// `xpcshell-tests`): the preflight still honours `--marionette-port`, but
|
|
169
|
+
// mach does not use the marionette.port pref on that harness. Any other arg
|
|
170
|
+
// shape still forwards so toolkit widget paths and mixed suites stay
|
|
171
|
+
// aligned with the probe without duplicate `--mach-arg` flags.
|
|
168
172
|
//
|
|
169
173
|
// Skip auto `--marionette=...` when `--mach-arg` already includes a client
|
|
170
174
|
// `--marionette=...` (or two-token `--marionette host:port`).
|
|
@@ -172,9 +176,8 @@ function appendMarionetteForwardingArgs(extraArgs, options, forwardedPort, xpcsh
|
|
|
172
176
|
return;
|
|
173
177
|
if (xpcshellOnly) {
|
|
174
178
|
// Manifest classification says every requested path is xpcshell —
|
|
175
|
-
// xpcshell ignores the browser Marionette path entirely, and
|
|
176
|
-
// mochitest client flags
|
|
177
|
-
// the dispatch.
|
|
179
|
+
// xpcshell ignores the browser Marionette path entirely, and forwarding
|
|
180
|
+
// the mochitest client flags here makes mach reject the dispatch.
|
|
178
181
|
info(`--marionette-port=${options.marionettePort} applied to the preflight probe only: the requested paths are xpcshell-only, and xpcshell ignores the browser Marionette port. Not forwarding --setpref=marionette.port or --marionette to mach.`);
|
|
179
182
|
return;
|
|
180
183
|
}
|
|
@@ -201,8 +204,8 @@ async function ensureTestMarionettePortAvailable(port, binaryName, options, skip
|
|
|
201
204
|
// This also recognizes a fork-branded browser via binaryName.
|
|
202
205
|
if (skip.xpcshellOnly && !skip.doctor) {
|
|
203
206
|
// xpcshell does not bind the browser Marionette port, so a developer's
|
|
204
|
-
// interactive browser holding 2828 must not kill an xpcshell run
|
|
205
|
-
|
|
207
|
+
// interactive browser holding 2828 must not kill an xpcshell run.
|
|
208
|
+
// --doctor keeps the preflight: its probe launches a
|
|
206
209
|
// Marionette browser regardless of the requested harness.
|
|
207
210
|
const message = 'Skipping the Marionette stale-port preflight: all requested paths are xpcshell ' +
|
|
208
211
|
'(xpcshell does not bind the browser Marionette port).';
|
|
@@ -229,6 +232,15 @@ async function ensureTestBrowserEnvironment(engineDir, launchablePath, xpcshellO
|
|
|
229
232
|
killStaleBrowser: options.killStaleMarionette === true,
|
|
230
233
|
});
|
|
231
234
|
}
|
|
235
|
+
// A zombie mochitest httpd squatting the server port makes a fresh
|
|
236
|
+
// browser connect to a server that cannot serve this run's manifest,
|
|
237
|
+
// which surfaces as a 370s "Ran 0 checks" stall naming nothing. xpcshell
|
|
238
|
+
// does not use the httpd, so an xpcshell-only run is never blocked by it.
|
|
239
|
+
if (!xpcshellOnly) {
|
|
240
|
+
await ensureMochitestServerPortAvailable(undefined, {
|
|
241
|
+
killStaleServer: options.killStaleMarionette === true,
|
|
242
|
+
});
|
|
243
|
+
}
|
|
232
244
|
const forwardedPort = options.machArg
|
|
233
245
|
? extractForwardedMarionettePort(options.machArg)
|
|
234
246
|
: undefined;
|
|
@@ -292,9 +304,7 @@ async function verifyEngineGenerationOrEmitInconclusive(engineDir, before) {
|
|
|
292
304
|
async function runTestCommandBody(projectRoot, testPaths, options = {}) {
|
|
293
305
|
const paths = getProjectPaths(projectRoot);
|
|
294
306
|
// Check if engine exists
|
|
295
|
-
|
|
296
|
-
throw new GeneralError('Firefox source not found. Run "fireforge download" first.');
|
|
297
|
-
}
|
|
307
|
+
await assertEngineExists(paths.engine);
|
|
298
308
|
assertPathlessTestMode(testPaths, options);
|
|
299
309
|
const buildCheck = await hasBuildArtifacts(paths.engine);
|
|
300
310
|
assertBuildArtifacts(paths.engine, buildCheck, TEST_BUILD_PREFLIGHT);
|
|
@@ -307,14 +317,14 @@ async function runTestCommandBody(projectRoot, testPaths, options = {}) {
|
|
|
307
317
|
const projectConfig = await loadConfig(projectRoot);
|
|
308
318
|
const canaryPath = resolveCanaryPath(options, projectConfig);
|
|
309
319
|
assertTestModeCombinations(testPaths, options, canaryPath);
|
|
310
|
-
// `hasBuildArtifacts` only confirms `obj-*/dist/` exists; a partial
|
|
311
|
-
//
|
|
312
|
-
//
|
|
313
|
-
//
|
|
314
|
-
//
|
|
315
|
-
//
|
|
316
|
-
//
|
|
317
|
-
//
|
|
320
|
+
// `hasBuildArtifacts` only confirms `obj-*/dist/` exists; a partial build
|
|
321
|
+
// (linker failed, packaging step interrupted) can satisfy that check
|
|
322
|
+
// without ever writing the launchable binary the marionette preflight
|
|
323
|
+
// needs to spawn. `fireforge run` already uses `hasRunnableBundle` to fail
|
|
324
|
+
// fast with a precise message; mirroring it here makes `test --doctor`
|
|
325
|
+
// against an incomplete build surface the missing-bundle path instead of a
|
|
326
|
+
// cryptic `Browser process exited during spawn (exit code 1, signal none).
|
|
327
|
+
// stderr tail: (empty)`.
|
|
318
328
|
const launchablePath = await resolveLaunchablePathForTests(paths.engine, projectConfig.binaryName, buildCheck.objDir);
|
|
319
329
|
const harnessRetries = options.harnessRetries ?? DEFAULT_HARNESS_RETRIES;
|
|
320
330
|
// Normalized engine-relative request paths, hoisted above the build/stale
|
|
@@ -338,9 +348,9 @@ async function runTestCommandBody(projectRoot, testPaths, options = {}) {
|
|
|
338
348
|
// 3. fall back to `DEFAULT_MARIONETTE_PORT` semantics inside the probes
|
|
339
349
|
// (passed as `undefined`).
|
|
340
350
|
// Without (2), an operator working around a stale listener via the
|
|
341
|
-
// documented `--mach-arg --marionette-port=NNNN`
|
|
342
|
-
//
|
|
343
|
-
//
|
|
351
|
+
// documented `--mach-arg --marionette-port=NNNN` route still hits the
|
|
352
|
+
// wrapper preflight refusing on 2828 before the forwarded arg reaches
|
|
353
|
+
// mach.
|
|
344
354
|
const { forwardedPort, effectivePort } = await ensureTestBrowserEnvironment(paths.engine, launchablePath, xpcshellOnly, projectConfig.binaryName, options);
|
|
345
355
|
if (options.doctor) {
|
|
346
356
|
const doctorOutcome = await runDoctorPreflight({
|
|
@@ -371,7 +381,7 @@ async function runTestCommandBody(projectRoot, testPaths, options = {}) {
|
|
|
371
381
|
}
|
|
372
382
|
// --mach-arg is a verbatim passthrough for upstream mach/xpcshell/mochitest
|
|
373
383
|
// flags FireForge does not model directly (see the xpcshell appdir hint
|
|
374
|
-
// above for
|
|
384
|
+
// above for why). Appended AFTER --headless so mach sees
|
|
375
385
|
// the FireForge-managed flags first and the escape-valve ones last, which
|
|
376
386
|
// keeps the override precedence predictable.
|
|
377
387
|
if (forwardedMachArgs.length > 0) {
|
|
@@ -380,16 +390,14 @@ async function runTestCommandBody(projectRoot, testPaths, options = {}) {
|
|
|
380
390
|
appendMarionetteForwardingArgs(extraArgs, options, forwardedPort, xpcshellOnly);
|
|
381
391
|
// Directory arguments mean EXACTLY that directory: mozbuild's test
|
|
382
392
|
// resolver matches paths by string prefix, so a bare directory arg
|
|
383
|
-
// silently
|
|
384
|
-
// `…/test/hominis
|
|
385
|
-
//
|
|
386
|
-
//
|
|
387
|
-
//
|
|
388
|
-
//
|
|
389
|
-
//
|
|
390
|
-
//
|
|
391
|
-
// is visible. Classification above intentionally used the raw
|
|
392
|
-
// argument forms; only the mach dispatch needs the exact-match shape.
|
|
393
|
+
// silently sweeps in prefix-named siblings — `…/test/hominis` also running
|
|
394
|
+
// `…/test/hominis-tiles`, with no indication the scope widened. Each
|
|
395
|
+
// directory argument therefore dispatches as its enumerated explicit
|
|
396
|
+
// test-file list, which cannot prefix-match a sibling; a trailing-`/`
|
|
397
|
+
// normalization does not work, as mach still sweeps the sibling in. Any
|
|
398
|
+
// prefix-siblings are echoed so the narrowed scope is visible.
|
|
399
|
+
// Classification above intentionally used the raw argument forms; only the
|
|
400
|
+
// mach dispatch needs the exact-match shape.
|
|
393
401
|
const scopes = await analyzeTestPathScopes(paths.engine, normalizedPaths);
|
|
394
402
|
const dispatchGroups = scopes.map((scope) => ({
|
|
395
403
|
label: scope.requestedPath,
|
|
@@ -419,17 +427,16 @@ async function runTestCommandBody(projectRoot, testPaths, options = {}) {
|
|
|
419
427
|
const postRebuildContext = options.build
|
|
420
428
|
? createPostRebuildFailureContext('fireforge test --build', normalizedPaths)
|
|
421
429
|
: undefined;
|
|
422
|
-
// Multi-argument requests shard into sequential harness runs by default
|
|
423
|
-
//
|
|
424
|
-
//
|
|
425
|
-
//
|
|
426
|
-
//
|
|
427
|
-
//
|
|
428
|
-
//
|
|
429
|
-
//
|
|
430
|
-
//
|
|
431
|
-
//
|
|
432
|
-
// what sharding does and does not exercise.
|
|
430
|
+
// Multi-argument requests shard into sequential harness runs by default:
|
|
431
|
+
// one shared mochitest profile across files bleeds pref/media-query state
|
|
432
|
+
// into later files. Sharding is per path ARGUMENT — a directory argument
|
|
433
|
+
// keeps its enumerated files together in one invocation, preserving the
|
|
434
|
+
// one-browser-instance semantics of a directory run. `--no-shard` restores
|
|
435
|
+
// the combined invocation. The default must not be SILENT: a cross-file
|
|
436
|
+
// pollution repro otherwise "passes" because the comparison run was
|
|
437
|
+
// sharded without saying so, misattributing a suite-context bug upstream.
|
|
438
|
+
// Hence the one-line notice stating what sharding does and does not
|
|
439
|
+
// exercise.
|
|
433
440
|
if (canaryPath === undefined && dispatchGroups.length > 1 && options.shard !== false) {
|
|
434
441
|
notice(`Sharding: running ${dispatchGroups.length} test path arguments in isolated browser instances ` +
|
|
435
442
|
'(one mach invocation per argument; a directory argument keeps its files in one instance). ' +
|
|
@@ -468,9 +475,9 @@ async function runTestCommandBody(projectRoot, testPaths, options = {}) {
|
|
|
468
475
|
finalizeSingleRunOutcome(outcome, normalizedPaths, projectConfig.binaryName, postRebuildContext, options.headless === true);
|
|
469
476
|
}
|
|
470
477
|
/**
|
|
471
|
-
* Builds the perf-sample env contract for the harness run
|
|
472
|
-
*
|
|
473
|
-
*
|
|
478
|
+
* Builds the perf-sample env contract for the harness run:
|
|
479
|
+
* `--perf-samples <path>` exports `<BINARYNAME>_PERF_SAMPLE_JSON` naming the
|
|
480
|
+
* artifact file a budget checker consumes after the run.
|
|
474
481
|
*/
|
|
475
482
|
function buildPerfSampleEnv(projectRoot, binaryName, perfSamples) {
|
|
476
483
|
if (!perfSamples)
|
|
@@ -34,10 +34,9 @@ export async function tokenCoverageCommand(projectRoot) {
|
|
|
34
34
|
.map((f) => f.file);
|
|
35
35
|
// Also scan CSS files deployed by Furnace custom components. Deployed
|
|
36
36
|
// files can be committed (and therefore absent from `git status`) while
|
|
37
|
-
// still being the primary surface where token adoption matters
|
|
38
|
-
//
|
|
39
|
-
//
|
|
40
|
-
// into the engine and they are already tracked.
|
|
37
|
+
// still being the primary surface where token adoption matters; looking
|
|
38
|
+
// only at modified files silently undercounts projects where Furnace
|
|
39
|
+
// writes many component-CSS files into the engine.
|
|
41
40
|
const furnaceCssFiles = await collectFurnaceCustomCssFiles(projectRoot, paths.engine, tokensCssPath);
|
|
42
41
|
// De-dupe so a file that is both a custom deploy target AND modified is
|
|
43
42
|
// scanned exactly once.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { Command, Option } from 'commander';
|
|
3
3
|
import { loadConfig } from '../core/config.js';
|
|
4
4
|
import { furnaceConfigExists, loadFurnaceConfig } from '../core/furnace-config.js';
|
|
5
|
-
import { addToken, getTokensCssPath, validateTokenAdd, } from '../core/token-manager.js';
|
|
5
|
+
import { addToken, getTokensCssPath, isTokenMode, TOKEN_MODES, validateTokenAdd, } from '../core/token-manager.js';
|
|
6
6
|
import { InvalidArgumentError } from '../errors/base.js';
|
|
7
7
|
import { FurnaceError } from '../errors/furnace.js';
|
|
8
8
|
import { toError } from '../utils/errors.js';
|
|
@@ -45,13 +45,12 @@ async function normalizeTokenNameForProject(projectRoot, rawTokenName) {
|
|
|
45
45
|
*/
|
|
46
46
|
export async function tokenAddCommand(projectRoot, tokenName, value, options) {
|
|
47
47
|
intro('Token Add');
|
|
48
|
-
//
|
|
49
|
-
//
|
|
50
|
-
//
|
|
51
|
-
//
|
|
52
|
-
//
|
|
53
|
-
//
|
|
54
|
-
// front before the generic "file not found" error fires.
|
|
48
|
+
// A fresh project without furnace.json otherwise fails deep inside the
|
|
49
|
+
// token-manager's `assertTokenCategoryExists` with "Token CSS file not
|
|
50
|
+
// found: browser/themes/shared/<binary>-tokens.css" — technically correct,
|
|
51
|
+
// but the operator's actual next step is to initialize Furnace, which
|
|
52
|
+
// scaffolds the tokens CSS file. Catching the uninitialized case here
|
|
53
|
+
// gives the right guidance before the generic "file not found" error.
|
|
55
54
|
if (!(await furnaceConfigExists(projectRoot))) {
|
|
56
55
|
throw new FurnaceError('Token management requires Furnace to be initialized. ' +
|
|
57
56
|
'Tokens live in the Furnace-managed tokens CSS file, which `fireforge furnace init` scaffolds alongside the rest of the Furnace workspace.\n\n' +
|
|
@@ -60,10 +59,10 @@ export async function tokenAddCommand(projectRoot, tokenName, value, options) {
|
|
|
60
59
|
// Normalize token name using the configured Furnace token prefix when the
|
|
61
60
|
// user supplied a bare token name like "canvas-gap".
|
|
62
61
|
tokenName = await normalizeTokenNameForProject(projectRoot, tokenName);
|
|
63
|
-
// Validate mode
|
|
64
|
-
|
|
65
|
-
if (!
|
|
66
|
-
throw new InvalidArgumentError(`Invalid mode "${options.mode}". Must be one of: ${
|
|
62
|
+
// Validate mode. The guard IS the runtime proof, so the three `as
|
|
63
|
+
// TokenMode` casts this replaced are gone with it.
|
|
64
|
+
if (!isTokenMode(options.mode)) {
|
|
65
|
+
throw new InvalidArgumentError(`Invalid mode "${options.mode}". Must be one of: ${TOKEN_MODES.join(', ')}`, 'mode');
|
|
67
66
|
}
|
|
68
67
|
if (options.dryRun) {
|
|
69
68
|
await validateTokenAdd(projectRoot, {
|
|
@@ -131,12 +130,11 @@ export function registerToken(program, { getProjectRoot, withErrorHandling }) {
|
|
|
131
130
|
const token = program
|
|
132
131
|
.command('token')
|
|
133
132
|
.description('Design token management')
|
|
134
|
-
// Match `fireforge furnace`'s no-args contract: print the group's help
|
|
135
|
-
// exit 0. Without this default action, commander routes
|
|
136
|
-
// (no subcommand) through its own help-then-exit-1
|
|
137
|
-
//
|
|
138
|
-
//
|
|
139
|
-
// would otherwise print, but returns successfully.
|
|
133
|
+
// Match `fireforge furnace`'s no-args contract: print the group's help
|
|
134
|
+
// and exit 0. Without this default action, commander routes
|
|
135
|
+
// `fireforge token` (no subcommand) through its own help-then-exit-1
|
|
136
|
+
// path, so scripts probing the CLI surface see a misleading non-zero
|
|
137
|
+
// exit for a purely informational invocation.
|
|
140
138
|
.action(() => {
|
|
141
139
|
token.outputHelp();
|
|
142
140
|
});
|
|
@@ -2,21 +2,23 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* `fireforge tree` — copy-on-write verification clones.
|
|
4
4
|
*
|
|
5
|
-
* Trees enable concurrent READ-MOSTLY verification (lint, typecheck,
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
5
|
+
* Trees enable concurrent READ-MOSTLY verification (lint, typecheck, status,
|
|
6
|
+
* verify, doctor, export dry-runs) beside a busy primary tree. Exports and
|
|
7
|
+
* every other mutation stay strictly serial in the primary — a tree's
|
|
8
|
+
* patches/components are snapshots with no merge model, and the tree guard
|
|
9
|
+
* (cli.ts preAction + core/tree-guard.ts) refuses mutating commands inside a
|
|
10
|
+
* tree.
|
|
11
|
+
*
|
|
12
|
+
* `create --with-objdir` additionally clones the primary's built obj-*
|
|
13
|
+
* directory, rewrites its mozinfo.json to the tree, and runs `mach configure`
|
|
14
|
+
* inside the tree so the remaining configure output (config.status,
|
|
15
|
+
* backend.mk, Makefile, config/autoconf.mk) stops naming the primary. That is
|
|
16
|
+
* fail-closed by design — mach objdirs embed absolute source paths, and an
|
|
17
|
+
* unrelocated clone would silently operate against the primary — and it is
|
|
18
|
+
* what admits build-less `fireforge test` inside that tree.
|
|
18
19
|
*/
|
|
19
20
|
import { spawn } from 'node:child_process';
|
|
21
|
+
import { mkdir, rm } from 'node:fs/promises';
|
|
20
22
|
import { join } from 'node:path';
|
|
21
23
|
import { Command } from 'commander';
|
|
22
24
|
import { withEngineSessionLock } from '../core/engine-session-lock.js';
|
|
@@ -24,11 +26,13 @@ import { hasBuildArtifacts, runMach, withBuildLock } from '../core/mach.js';
|
|
|
24
26
|
import { assertBuildArtifacts, findObjdirRelocationViolation, } from '../core/mach-build-artifacts.js';
|
|
25
27
|
import { detectCowSupport } from '../core/tree-cow.js';
|
|
26
28
|
import { cloneTree, listTrees, removeTree } from '../core/tree-store.js';
|
|
27
|
-
import { assertValidTreeName, computePrimaryFingerprint, getTreeMarkerPath, getTreesDir,
|
|
28
|
-
import { GeneralError } from '../errors/base.js';
|
|
29
|
+
import { assertValidTreeName, computePrimaryFingerprint, getTreeMarkerPath, getTreesDir, readTreeMarker, withTreeLifecycleLock, } from '../core/tree-store.js';
|
|
30
|
+
import { GeneralError, InvalidArgumentError } from '../errors/base.js';
|
|
29
31
|
import { BuildError } from '../errors/build.js';
|
|
32
|
+
import { toError } from '../utils/errors.js';
|
|
30
33
|
import { pathExists } from '../utils/fs.js';
|
|
31
34
|
import { info, intro, outro, setMachineOutputMode, setStdoutSealed, success, warn, } from '../utils/logger.js';
|
|
35
|
+
import { emitMachineError, MACHINE_OUTPUT_SCHEMA_VERSION } from '../utils/machine-output.js';
|
|
32
36
|
import { addWaitLockOption, resolveWaitLockSeconds } from '../utils/options.js';
|
|
33
37
|
function assertPosix() {
|
|
34
38
|
if (process.platform === 'win32') {
|
|
@@ -100,7 +104,7 @@ export async function treeCreateCommand(projectRoot, name, options = {}) {
|
|
|
100
104
|
// A marker we cannot parse still means "something claims this is a tree", so
|
|
101
105
|
// it must block nesting too — otherwise a corrupt marker is a licence to
|
|
102
106
|
// clone a snapshot into itself.
|
|
103
|
-
const markerState = await
|
|
107
|
+
const markerState = await readTreeMarker(projectRoot);
|
|
104
108
|
if (markerState.kind !== 'absent') {
|
|
105
109
|
throw new GeneralError(markerState.kind === 'valid'
|
|
106
110
|
? 'Verification trees cannot be nested: run tree create in the primary tree.'
|
|
@@ -113,7 +117,6 @@ export async function treeCreateCommand(projectRoot, name, options = {}) {
|
|
|
113
117
|
if (await pathExists(treeRoot)) {
|
|
114
118
|
throw new GeneralError(`A tree named "${name}" already exists. Remove it first (fireforge tree remove ${name}) — refresh is remove + create.`);
|
|
115
119
|
}
|
|
116
|
-
const { mkdir } = await import('node:fs/promises');
|
|
117
120
|
await mkdir(treesDir, { recursive: true });
|
|
118
121
|
const capability = await detectCowSupport(treesDir);
|
|
119
122
|
if (capability === 'none' && options.forceCopy !== true) {
|
|
@@ -162,7 +165,6 @@ export async function treeCreateCommand(projectRoot, name, options = {}) {
|
|
|
162
165
|
: await clone();
|
|
163
166
|
}
|
|
164
167
|
catch (error) {
|
|
165
|
-
const { rm } = await import('node:fs/promises');
|
|
166
168
|
await rm(treeRoot, { recursive: true, force: true });
|
|
167
169
|
throw error;
|
|
168
170
|
}
|
|
@@ -184,9 +186,21 @@ export async function treeListCommand(projectRoot, options = {}) {
|
|
|
184
186
|
// any diagnostic — including a listTrees failure rendered later by
|
|
185
187
|
// withErrorHandling, which also resets the mode — routes to stderr.
|
|
186
188
|
setMachineOutputMode(true);
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
189
|
+
try {
|
|
190
|
+
const trees = await listTrees(projectRoot);
|
|
191
|
+
process.stdout.write(`${JSON.stringify({ schemaVersion: MACHINE_OUTPUT_SCHEMA_VERSION, trees }, null, 2)}\n`);
|
|
192
|
+
// Payload written: stdout is now spoken for. See docs/machine-output.md.
|
|
193
|
+
setStdoutSealed(true);
|
|
194
|
+
}
|
|
195
|
+
catch (error) {
|
|
196
|
+
// Same failure envelope `status --json` emits. Without it a scripted
|
|
197
|
+
// consumer got a parseable refusal from one command and a bare
|
|
198
|
+
// non-zero exit from the other. See docs/machine-output.md.
|
|
199
|
+
emitMachineError('tree-list-failed', toError(error).message);
|
|
200
|
+
}
|
|
201
|
+
finally {
|
|
202
|
+
setMachineOutputMode(false);
|
|
203
|
+
}
|
|
190
204
|
return;
|
|
191
205
|
}
|
|
192
206
|
const trees = await listTrees(projectRoot);
|
|
@@ -206,7 +220,7 @@ export async function treeRemoveCommand(projectRoot, name, options = {}) {
|
|
|
206
220
|
assertPosix();
|
|
207
221
|
intro('FireForge Tree Remove');
|
|
208
222
|
if (options.all !== true && name === undefined) {
|
|
209
|
-
throw new
|
|
223
|
+
throw new InvalidArgumentError('Pass a tree name, or --all to remove every tree.', '--all');
|
|
210
224
|
}
|
|
211
225
|
await withTreeLifecycleLock(projectRoot, async () => {
|
|
212
226
|
const targets = options.all === true ? (await listTrees(projectRoot)).map((t) => t.name) : [name ?? ''];
|
|
@@ -226,7 +240,7 @@ async function treeExecCommand(projectRoot, name, args) {
|
|
|
226
240
|
assertPosix();
|
|
227
241
|
assertValidTreeName(name);
|
|
228
242
|
const treeRoot = join(getTreesDir(projectRoot), name);
|
|
229
|
-
const state = await
|
|
243
|
+
const state = await readTreeMarker(treeRoot);
|
|
230
244
|
if (state.kind === 'corrupt') {
|
|
231
245
|
// Collapsing corrupt into "no such tree" misdiagnoses: the directory IS
|
|
232
246
|
// there, claiming to be a tree, and "no tree named X" points the operator
|
|
@@ -237,6 +251,9 @@ async function treeExecCommand(projectRoot, name, args) {
|
|
|
237
251
|
if (state.kind === 'absent') {
|
|
238
252
|
throw new GeneralError(`No verification tree named "${name}". List trees with: fireforge tree list`);
|
|
239
253
|
}
|
|
254
|
+
if (state.kind === 'unsupported') {
|
|
255
|
+
throw new GeneralError(`Cannot inspect tree "${name}": ${state.reason}`);
|
|
256
|
+
}
|
|
240
257
|
const marker = state.marker;
|
|
241
258
|
const current = await computePrimaryFingerprint(projectRoot);
|
|
242
259
|
if (marker.engineHead !== current.engineHead) {
|
|
@@ -263,14 +280,13 @@ async function treeExecCommand(projectRoot, name, args) {
|
|
|
263
280
|
resolvePromise(code ?? 1);
|
|
264
281
|
});
|
|
265
282
|
}).finally(() => {
|
|
266
|
-
// With `stdio: 'inherit'` the child owned stdout — including
|
|
267
|
-
//
|
|
268
|
-
//
|
|
269
|
-
//
|
|
270
|
-
//
|
|
271
|
-
//
|
|
272
|
-
//
|
|
273
|
-
// clears the seal.
|
|
283
|
+
// With `stdio: 'inherit'` the child owned stdout — including any
|
|
284
|
+
// FIREFORGE-VERDICT line it emitted as its LAST stdout write. From here
|
|
285
|
+
// on the parent must not write stdout again, or its own refusal text
|
|
286
|
+
// (the GeneralError below, rendered by withErrorHandling) prints AFTER
|
|
287
|
+
// the child's verdict and breaks the "verdict is the run's last stdout
|
|
288
|
+
// line" contract at the tree-exec boundary. Sealing routes the parent's
|
|
289
|
+
// remaining output to stderr; withErrorHandling's finally clears it.
|
|
274
290
|
setStdoutSealed(true);
|
|
275
291
|
});
|
|
276
292
|
if (exitCode !== 0) {
|
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `fireforge typecheck` — whole-project TypeScript type checking
|
|
3
|
-
*
|
|
2
|
+
* `fireforge typecheck` — whole-project TypeScript type checking driven by
|
|
3
|
+
* user-supplied jsconfig.json paths.
|
|
4
4
|
*
|
|
5
|
-
* Distinct from `patchLint.checkJs`: that pass is patch-hygiene
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* typecheck for a reason the operator could not have inferred from
|
|
12
|
-
* the docs.
|
|
5
|
+
* Distinct from `patchLint.checkJs`: that pass is patch-hygiene (scoped to
|
|
6
|
+
* patch-owned `.sys.mjs`, run automatically by `fireforge lint`); this
|
|
7
|
+
* command is CI-grade — it runs whole projects with the user's own compiler
|
|
8
|
+
* options. The two share their Firefox-globals shim and the same
|
|
9
|
+
* suppressed-diagnostic set so a file that lints clean cannot fail typecheck
|
|
10
|
+
* for a reason the operator could not have inferred from the docs.
|
|
13
11
|
*
|
|
14
|
-
* Exits non-zero on any error-severity diagnostic. Warnings print
|
|
15
|
-
*
|
|
12
|
+
* Exits non-zero on any error-severity diagnostic. Warnings print but do not
|
|
13
|
+
* fail.
|
|
16
14
|
*/
|
|
17
15
|
import { Command } from 'commander';
|
|
18
16
|
import type { CommandContext } from '../types/cli.js';
|