@hominis/fireforge 0.46.0 → 0.46.2
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 +381 -498
- package/dist/bin/fireforge.d.ts +1 -1
- package/dist/bin/fireforge.js +17 -17
- package/dist/build-info.json +4 -4
- package/dist/src/cli-usage-error.d.ts +9 -9
- package/dist/src/cli-usage-error.js +12 -12
- package/dist/src/cli.d.ts +3 -2
- package/dist/src/cli.js +29 -28
- package/dist/src/commands/bootstrap-checks.js +2 -1
- package/dist/src/commands/bootstrap.js +2 -2
- package/dist/src/commands/build.js +12 -11
- package/dist/src/commands/config.js +9 -9
- package/dist/src/commands/destructive-decision.d.ts +4 -4
- package/dist/src/commands/destructive-decision.js +4 -4
- package/dist/src/commands/discard.js +5 -5
- package/dist/src/commands/doctor-check-core.d.ts +4 -4
- package/dist/src/commands/doctor-external-toolchains.js +2 -2
- package/dist/src/commands/doctor-furnace-config-sync.d.ts +2 -2
- package/dist/src/commands/doctor-furnace-config-sync.js +20 -20
- package/dist/src/commands/doctor-furnace-jar.d.ts +1 -1
- package/dist/src/commands/doctor-furnace-jar.js +1 -1
- package/dist/src/commands/doctor-furnace.js +22 -22
- package/dist/src/commands/doctor-orphaned-harness.d.ts +10 -11
- package/dist/src/commands/doctor-orphaned-harness.js +10 -11
- package/dist/src/commands/doctor-patch-manifest.d.ts +2 -1
- package/dist/src/commands/doctor-patch-manifest.js +7 -6
- package/dist/src/commands/doctor-post-rebase-audit.js +2 -2
- package/dist/src/commands/doctor-source-pin.d.ts +12 -12
- package/dist/src/commands/doctor-source-pin.js +14 -14
- package/dist/src/commands/doctor-working-tree.d.ts +3 -3
- package/dist/src/commands/doctor-working-tree.js +3 -3
- package/dist/src/commands/doctor.d.ts +2 -2
- package/dist/src/commands/doctor.js +9 -9
- package/dist/src/commands/download.js +15 -13
- package/dist/src/commands/export-all.js +8 -8
- package/dist/src/commands/export-flow.d.ts +5 -5
- package/dist/src/commands/export-flow.js +14 -14
- package/dist/src/commands/export-placement-conflicts.d.ts +3 -3
- package/dist/src/commands/export-placement-conflicts.js +9 -9
- package/dist/src/commands/export-placement-gate.d.ts +2 -2
- package/dist/src/commands/export-placement-gate.js +5 -5
- package/dist/src/commands/export-placement-policy.d.ts +1 -1
- package/dist/src/commands/export-placement-policy.js +1 -1
- package/dist/src/commands/export-shared.d.ts +10 -10
- package/dist/src/commands/export-shared.js +13 -13
- package/dist/src/commands/export.js +4 -4
- package/dist/src/commands/furnace/apply.js +16 -16
- package/dist/src/commands/furnace/chrome-doc-remove.d.ts +1 -1
- package/dist/src/commands/furnace/chrome-doc-remove.js +1 -1
- package/dist/src/commands/furnace/chrome-doc-templates.d.ts +14 -14
- package/dist/src/commands/furnace/chrome-doc-templates.js +17 -17
- package/dist/src/commands/furnace/chrome-doc-tests.d.ts +2 -2
- package/dist/src/commands/furnace/chrome-doc-tests.js +4 -4
- package/dist/src/commands/furnace/chrome-doc.d.ts +8 -8
- package/dist/src/commands/furnace/chrome-doc.js +18 -18
- package/dist/src/commands/furnace/create-browser-test.d.ts +1 -1
- package/dist/src/commands/furnace/create-browser-test.js +4 -4
- package/dist/src/commands/furnace/create-dry-run.d.ts +4 -4
- package/dist/src/commands/furnace/create-dry-run.js +4 -4
- package/dist/src/commands/furnace/create-features.d.ts +2 -2
- package/dist/src/commands/furnace/create-features.js +2 -2
- package/dist/src/commands/furnace/create-mochikit.d.ts +4 -4
- package/dist/src/commands/furnace/create-mochikit.js +7 -7
- package/dist/src/commands/furnace/create-templates.d.ts +14 -14
- package/dist/src/commands/furnace/create-templates.js +18 -18
- package/dist/src/commands/furnace/create-xpcshell.d.ts +5 -5
- package/dist/src/commands/furnace/create-xpcshell.js +8 -8
- package/dist/src/commands/furnace/create.d.ts +1 -1
- package/dist/src/commands/furnace/create.js +10 -10
- package/dist/src/commands/furnace/deploy.js +4 -4
- package/dist/src/commands/furnace/diff.js +7 -7
- package/dist/src/commands/furnace/index.js +1 -1
- package/dist/src/commands/furnace/init.js +15 -15
- package/dist/src/commands/furnace/list.js +2 -2
- package/dist/src/commands/furnace/override.d.ts +1 -1
- package/dist/src/commands/furnace/override.js +15 -15
- package/dist/src/commands/furnace/preview.js +17 -17
- package/dist/src/commands/furnace/refresh.js +6 -6
- package/dist/src/commands/furnace/remove-mutations.d.ts +3 -3
- package/dist/src/commands/furnace/remove-mutations.js +19 -18
- package/dist/src/commands/furnace/remove-state.d.ts +1 -1
- package/dist/src/commands/furnace/remove-state.js +1 -1
- package/dist/src/commands/furnace/remove.js +2 -2
- package/dist/src/commands/furnace/rename-browser-test.js +9 -8
- package/dist/src/commands/furnace/rename-xpcshell.d.ts +2 -2
- package/dist/src/commands/furnace/rename-xpcshell.js +3 -3
- package/dist/src/commands/furnace/rename.js +9 -9
- package/dist/src/commands/furnace/scan.js +3 -3
- package/dist/src/commands/furnace/status.js +7 -7
- package/dist/src/commands/furnace/sync.js +6 -6
- package/dist/src/commands/furnace/test-file-name.d.ts +2 -2
- package/dist/src/commands/furnace/test-file-name.js +2 -2
- package/dist/src/commands/furnace/validate.js +11 -12
- package/dist/src/commands/import.js +20 -20
- package/dist/src/commands/lint-per-patch.js +8 -8
- package/dist/src/commands/lint-per-run-checkjs.d.ts +12 -13
- package/dist/src/commands/lint-per-run-checkjs.js +14 -15
- package/dist/src/commands/lint-report.d.ts +3 -3
- package/dist/src/commands/lint-report.js +4 -4
- package/dist/src/commands/lint.d.ts +3 -3
- package/dist/src/commands/lint.js +35 -35
- package/dist/src/commands/manifest.d.ts +4 -4
- package/dist/src/commands/package.js +2 -2
- package/dist/src/commands/patch/compact.d.ts +2 -2
- package/dist/src/commands/patch/compact.js +8 -8
- package/dist/src/commands/patch/delete.d.ts +1 -1
- package/dist/src/commands/patch/delete.js +8 -8
- package/dist/src/commands/patch/lint-ignore.d.ts +3 -4
- package/dist/src/commands/patch/lint-ignore.js +14 -15
- package/dist/src/commands/patch/move-files-create.d.ts +2 -2
- package/dist/src/commands/patch/move-files-create.js +5 -5
- package/dist/src/commands/patch/move-files-into.d.ts +2 -2
- package/dist/src/commands/patch/move-files-into.js +3 -3
- package/dist/src/commands/patch/move-files.js +1 -1
- package/dist/src/commands/patch/patch-context.d.ts +1 -1
- package/dist/src/commands/patch/rename.d.ts +4 -4
- package/dist/src/commands/patch/rename.js +8 -8
- package/dist/src/commands/patch/reorder.js +10 -10
- package/dist/src/commands/patch/split-plan.d.ts +3 -3
- package/dist/src/commands/patch/split-plan.js +6 -5
- package/dist/src/commands/patch/split.d.ts +2 -2
- package/dist/src/commands/patch/split.js +5 -5
- package/dist/src/commands/patch/staged-dependency-validate.d.ts +1 -1
- package/dist/src/commands/patch/staged-dependency-validate.js +3 -3
- package/dist/src/commands/patch/staged-dependency.d.ts +1 -1
- package/dist/src/commands/patch/staged-dependency.js +6 -6
- package/dist/src/commands/patch/tier.d.ts +2 -2
- package/dist/src/commands/patch/tier.js +5 -5
- package/dist/src/commands/patch-rename-map.d.ts +1 -1
- package/dist/src/commands/patch-rename-map.js +1 -1
- package/dist/src/commands/pending-resolution.d.ts +5 -5
- package/dist/src/commands/pending-resolution.js +5 -5
- package/dist/src/commands/re-export-adjacent.d.ts +3 -3
- package/dist/src/commands/re-export-adjacent.js +8 -8
- package/dist/src/commands/re-export-bulk-scan.d.ts +3 -3
- package/dist/src/commands/re-export-bulk-scan.js +17 -17
- package/dist/src/commands/re-export-drift.d.ts +10 -10
- package/dist/src/commands/re-export-drift.js +29 -29
- package/dist/src/commands/re-export-files.js +14 -15
- package/dist/src/commands/re-export-lint.d.ts +26 -26
- package/dist/src/commands/re-export-lint.js +27 -27
- package/dist/src/commands/re-export-options.d.ts +1 -1
- package/dist/src/commands/re-export-options.js +1 -1
- package/dist/src/commands/re-export-register.d.ts +1 -1
- package/dist/src/commands/re-export-register.js +1 -1
- package/dist/src/commands/re-export-scan.d.ts +1 -1
- package/dist/src/commands/re-export-scan.js +7 -7
- package/dist/src/commands/re-export-single.d.ts +1 -1
- package/dist/src/commands/re-export-single.js +20 -20
- package/dist/src/commands/re-export.js +7 -6
- package/dist/src/commands/rebase/abort.js +6 -6
- package/dist/src/commands/rebase/continue.js +8 -7
- package/dist/src/commands/rebase/index.d.ts +1 -1
- package/dist/src/commands/rebase/index.js +3 -3
- package/dist/src/commands/rebase/patch-loop.js +18 -17
- package/dist/src/commands/register.js +5 -5
- package/dist/src/commands/reset.js +1 -1
- package/dist/src/commands/resolve.d.ts +2 -2
- package/dist/src/commands/resolve.js +3 -3
- package/dist/src/commands/run.js +26 -26
- package/dist/src/commands/setup-support.js +4 -4
- package/dist/src/commands/setup.js +1 -1
- package/dist/src/commands/source.js +1 -1
- package/dist/src/commands/status-check.d.ts +3 -3
- package/dist/src/commands/status-check.js +4 -4
- package/dist/src/commands/status-json.d.ts +14 -13
- package/dist/src/commands/status-json.js +9 -8
- package/dist/src/commands/status-output.d.ts +3 -3
- package/dist/src/commands/status-output.js +3 -3
- package/dist/src/commands/status-ownership.d.ts +3 -3
- package/dist/src/commands/status-ownership.js +3 -3
- package/dist/src/commands/status.js +22 -22
- package/dist/src/commands/test-build-phase.d.ts +1 -1
- package/dist/src/commands/test-build-phase.js +17 -17
- package/dist/src/commands/test-diagnose.d.ts +1 -1
- package/dist/src/commands/test-diagnose.js +20 -20
- package/dist/src/commands/test-modes.d.ts +2 -2
- package/dist/src/commands/test-modes.js +4 -4
- package/dist/src/commands/test-run.d.ts +11 -11
- package/dist/src/commands/test-run.js +15 -15
- package/dist/src/commands/test-stale-gate.d.ts +12 -12
- package/dist/src/commands/test-stale-gate.js +13 -13
- package/dist/src/commands/test-verdict.d.ts +6 -6
- package/dist/src/commands/test-verdict.js +11 -11
- package/dist/src/commands/test.d.ts +3 -3
- package/dist/src/commands/test.js +36 -36
- package/dist/src/commands/token-coverage.js +3 -3
- package/dist/src/commands/token-list.js +5 -5
- package/dist/src/commands/token.js +9 -9
- package/dist/src/commands/tree.js +19 -19
- package/dist/src/commands/typecheck.d.ts +6 -6
- package/dist/src/commands/typecheck.js +7 -7
- package/dist/src/commands/verify.d.ts +3 -3
- package/dist/src/commands/verify.js +10 -10
- package/dist/src/commands/watch.js +11 -11
- package/dist/src/commands/wire.js +13 -13
- package/dist/src/core/ast-utils.d.ts +7 -7
- package/dist/src/core/ast-utils.js +8 -8
- package/dist/src/core/branding.d.ts +5 -5
- package/dist/src/core/branding.js +3 -3
- package/dist/src/core/browser-wire.d.ts +1 -1
- package/dist/src/core/browser-wire.js +4 -4
- package/dist/src/core/build-audit-platform.d.ts +6 -6
- package/dist/src/core/build-audit-platform.js +26 -26
- package/dist/src/core/build-audit-registration.d.ts +5 -5
- package/dist/src/core/build-audit-registration.js +7 -7
- package/dist/src/core/build-audit-resolve.d.ts +5 -5
- package/dist/src/core/build-audit-resolve.js +6 -6
- package/dist/src/core/build-audit-skip.d.ts +8 -8
- package/dist/src/core/build-audit-skip.js +12 -12
- package/dist/src/core/build-audit-transforms.d.ts +2 -2
- package/dist/src/core/build-audit-transforms.js +3 -3
- package/dist/src/core/build-audit.d.ts +8 -8
- package/dist/src/core/build-audit.js +39 -37
- package/dist/src/core/build-baseline-types.d.ts +19 -18
- package/dist/src/core/build-baseline-types.js +1 -1
- package/dist/src/core/build-baseline.d.ts +8 -8
- package/dist/src/core/build-baseline.js +14 -14
- package/dist/src/core/build-jar-escalation.d.ts +8 -8
- package/dist/src/core/build-jar-escalation.js +15 -15
- package/dist/src/core/build-overwrite-guard.d.ts +4 -4
- package/dist/src/core/build-overwrite-guard.js +13 -13
- package/dist/src/core/build-prepare.d.ts +4 -4
- package/dist/src/core/build-prepare.js +16 -15
- package/dist/src/core/config-mutate.js +4 -4
- package/dist/src/core/config-state.js +2 -2
- package/dist/src/core/config-validate-build-audit.js +3 -3
- package/dist/src/core/config-validate-file-size.d.ts +1 -1
- package/dist/src/core/config-validate-file-size.js +2 -2
- package/dist/src/core/config-validate.js +8 -9
- package/dist/src/core/config.d.ts +10 -10
- package/dist/src/core/config.js +10 -10
- package/dist/src/core/coverage-extend.d.ts +16 -16
- package/dist/src/core/coverage-extend.js +16 -16
- package/dist/src/core/destructive.d.ts +14 -14
- package/dist/src/core/destructive.js +9 -9
- package/dist/src/core/diff-hunks.d.ts +2 -2
- package/dist/src/core/diff-hunks.js +7 -7
- package/dist/src/core/discard-baseline.d.ts +10 -10
- package/dist/src/core/discard-baseline.js +15 -16
- package/dist/src/core/display-state.d.ts +11 -11
- package/dist/src/core/display-state.js +12 -12
- package/dist/src/core/engine-changes.d.ts +2 -2
- package/dist/src/core/engine-changes.js +2 -2
- package/dist/src/core/engine-precondition.d.ts +4 -4
- package/dist/src/core/engine-precondition.js +2 -2
- package/dist/src/core/engine-session-lock.d.ts +18 -18
- package/dist/src/core/engine-session-lock.js +37 -37
- package/dist/src/core/export-moved-code-shape.d.ts +7 -7
- package/dist/src/core/export-moved-code-shape.js +8 -8
- package/dist/src/core/file-lock-owner.d.ts +11 -11
- package/dist/src/core/file-lock-owner.js +18 -18
- package/dist/src/core/file-lock.d.ts +12 -12
- package/dist/src/core/file-lock.js +52 -39
- package/dist/src/core/firefox-cache.d.ts +1 -1
- package/dist/src/core/firefox-cache.js +10 -10
- package/dist/src/core/firefox-download.d.ts +3 -3
- package/dist/src/core/firefox-download.js +6 -6
- package/dist/src/core/firefox-extract.d.ts +2 -2
- package/dist/src/core/firefox-extract.js +13 -13
- package/dist/src/core/firefox.d.ts +5 -5
- package/dist/src/core/firefox.js +8 -8
- package/dist/src/core/furnace-apply-dry-run.js +1 -1
- package/dist/src/core/furnace-apply-ftl.d.ts +5 -5
- package/dist/src/core/furnace-apply-ftl.js +8 -8
- package/dist/src/core/furnace-apply-helpers.d.ts +9 -9
- package/dist/src/core/furnace-apply-helpers.js +21 -21
- package/dist/src/core/furnace-apply-output.js +1 -1
- package/dist/src/core/furnace-apply-overwrite-warn.d.ts +9 -9
- package/dist/src/core/furnace-apply-overwrite-warn.js +9 -9
- package/dist/src/core/furnace-apply-undeploy-actions.d.ts +1 -1
- package/dist/src/core/furnace-apply-undeploy-actions.js +1 -1
- package/dist/src/core/furnace-apply.d.ts +3 -3
- package/dist/src/core/furnace-apply.js +22 -21
- package/dist/src/core/furnace-checksum-utils.d.ts +5 -5
- package/dist/src/core/furnace-checksum-utils.js +5 -5
- package/dist/src/core/furnace-config-custom.d.ts +1 -1
- package/dist/src/core/furnace-config-custom.js +2 -2
- package/dist/src/core/furnace-config-order.js +1 -1
- package/dist/src/core/furnace-config-tokens.d.ts +3 -3
- package/dist/src/core/furnace-config-tokens.js +3 -3
- package/dist/src/core/furnace-config-validate.js +2 -2
- package/dist/src/core/furnace-config.d.ts +4 -4
- package/dist/src/core/furnace-config.js +18 -18
- package/dist/src/core/furnace-constants.d.ts +6 -6
- package/dist/src/core/furnace-constants.js +6 -6
- package/dist/src/core/furnace-css-fragments.d.ts +6 -6
- package/dist/src/core/furnace-css-fragments.js +11 -11
- package/dist/src/core/furnace-dir-entry.d.ts +1 -1
- package/dist/src/core/furnace-dir-entry.js +1 -1
- package/dist/src/core/furnace-jsconfig.d.ts +7 -7
- package/dist/src/core/furnace-jsconfig.js +22 -20
- package/dist/src/core/furnace-operation.d.ts +21 -20
- package/dist/src/core/furnace-operation.js +36 -34
- package/dist/src/core/furnace-precondition.d.ts +10 -10
- package/dist/src/core/furnace-precondition.js +8 -8
- package/dist/src/core/furnace-refresh.js +2 -2
- package/dist/src/core/furnace-registration-ast.d.ts +2 -2
- package/dist/src/core/furnace-registration-ast.js +9 -9
- package/dist/src/core/furnace-registration-remove.d.ts +4 -4
- package/dist/src/core/furnace-registration-remove.js +6 -6
- package/dist/src/core/furnace-registration-validate.d.ts +2 -2
- package/dist/src/core/furnace-registration-validate.js +2 -2
- package/dist/src/core/furnace-registration.d.ts +5 -5
- package/dist/src/core/furnace-registration.js +7 -7
- package/dist/src/core/furnace-rollback.d.ts +1 -1
- package/dist/src/core/furnace-rollback.js +5 -5
- package/dist/src/core/furnace-stale-export.d.ts +17 -16
- package/dist/src/core/furnace-stale-export.js +16 -15
- package/dist/src/core/furnace-staleness.d.ts +2 -2
- package/dist/src/core/furnace-staleness.js +2 -2
- package/dist/src/core/furnace-state-persist.d.ts +10 -10
- package/dist/src/core/furnace-state-persist.js +10 -10
- package/dist/src/core/furnace-step-errors.d.ts +6 -6
- package/dist/src/core/furnace-step-errors.js +6 -6
- package/dist/src/core/furnace-validate-accessibility.js +14 -14
- package/dist/src/core/furnace-validate-compatibility.js +9 -9
- package/dist/src/core/furnace-validate-registration.d.ts +2 -2
- package/dist/src/core/furnace-validate-registration.js +13 -13
- package/dist/src/core/furnace-validate-structure.d.ts +1 -1
- package/dist/src/core/furnace-validate-structure.js +4 -4
- package/dist/src/core/furnace-validate.js +9 -9
- package/dist/src/core/furnace-version-drift.d.ts +5 -5
- package/dist/src/core/furnace-version-drift.js +5 -5
- package/dist/src/core/git-base.d.ts +4 -4
- package/dist/src/core/git-base.js +9 -9
- package/dist/src/core/git-diff-new-file.d.ts +4 -4
- package/dist/src/core/git-diff-new-file.js +8 -8
- package/dist/src/core/git-diff.d.ts +4 -4
- package/dist/src/core/git-diff.js +35 -34
- package/dist/src/core/git-file-ops.d.ts +6 -6
- package/dist/src/core/git-file-ops.js +7 -7
- package/dist/src/core/git-readonly-index.d.ts +12 -12
- package/dist/src/core/git-readonly-index.js +12 -12
- package/dist/src/core/git-status.d.ts +4 -4
- package/dist/src/core/git-status.js +4 -4
- package/dist/src/core/git.d.ts +3 -3
- package/dist/src/core/git.js +14 -14
- package/dist/src/core/harness-orphans.d.ts +17 -17
- package/dist/src/core/harness-orphans.js +20 -20
- package/dist/src/core/history-log.d.ts +3 -3
- package/dist/src/core/history-log.js +3 -3
- package/dist/src/core/license-headers.d.ts +19 -18
- package/dist/src/core/license-headers.js +29 -28
- package/dist/src/core/mach-build-artifacts.d.ts +21 -21
- package/dist/src/core/mach-build-artifacts.js +23 -23
- package/dist/src/core/mach-error-hints.d.ts +5 -5
- package/dist/src/core/mach-error-hints.js +13 -13
- package/dist/src/core/mach-known-noise-filter.d.ts +41 -38
- package/dist/src/core/mach-known-noise-filter.js +53 -50
- package/dist/src/core/mach-mozconfig.d.ts +6 -6
- package/dist/src/core/mach-mozconfig.js +15 -15
- package/dist/src/core/mach-python.d.ts +2 -1
- package/dist/src/core/mach-python.js +4 -3
- package/dist/src/core/mach-resource-shim.d.ts +12 -12
- package/dist/src/core/mach-resource-shim.js +20 -20
- package/dist/src/core/mach.d.ts +23 -23
- package/dist/src/core/mach.js +36 -36
- package/dist/src/core/marionette-port.d.ts +15 -13
- package/dist/src/core/marionette-port.js +34 -31
- package/dist/src/core/marionette-preflight.d.ts +6 -6
- package/dist/src/core/marionette-preflight.js +23 -23
- package/dist/src/core/markdown-table.d.ts +9 -9
- package/dist/src/core/markdown-table.js +14 -14
- package/dist/src/core/mochitest-server-port.d.ts +8 -8
- package/dist/src/core/mochitest-server-port.js +14 -14
- package/dist/src/core/module-resolution-preflight.d.ts +8 -8
- package/dist/src/core/module-resolution-preflight.js +11 -11
- package/dist/src/core/moz-manifest-helpers.d.ts +7 -7
- package/dist/src/core/moz-manifest-helpers.js +7 -7
- package/dist/src/core/moz-manifest-register.d.ts +1 -1
- package/dist/src/core/moz-manifest-register.js +2 -2
- package/dist/src/core/moz-manifest-rules.js +11 -11
- package/dist/src/core/moz-manifest-tokenizers.js +1 -1
- package/dist/src/core/ownership-table.d.ts +5 -5
- package/dist/src/core/ownership-table.js +7 -7
- package/dist/src/core/parser-fallback.d.ts +3 -3
- package/dist/src/core/parser-fallback.js +3 -3
- package/dist/src/core/patch-apply-fuzz.d.ts +5 -5
- package/dist/src/core/patch-apply-fuzz.js +9 -9
- package/dist/src/core/patch-apply.d.ts +9 -9
- package/dist/src/core/patch-apply.js +30 -30
- package/dist/src/core/patch-export-update.d.ts +4 -4
- package/dist/src/core/patch-export-update.js +3 -3
- package/dist/src/core/patch-export.d.ts +10 -10
- package/dist/src/core/patch-export.js +13 -13
- package/dist/src/core/patch-identifier-suggest.d.ts +1 -1
- package/dist/src/core/patch-identifier-suggest.js +4 -4
- package/dist/src/core/patch-lint-binary.d.ts +7 -7
- package/dist/src/core/patch-lint-cache.d.ts +2 -2
- package/dist/src/core/patch-lint-cache.js +13 -13
- package/dist/src/core/patch-lint-checkjs.d.ts +26 -26
- package/dist/src/core/patch-lint-checkjs.js +42 -41
- package/dist/src/core/patch-lint-chrome-jsdoc.d.ts +8 -9
- package/dist/src/core/patch-lint-chrome-jsdoc.js +10 -11
- package/dist/src/core/patch-lint-creators.d.ts +3 -3
- package/dist/src/core/patch-lint-creators.js +3 -3
- package/dist/src/core/patch-lint-cross.d.ts +13 -13
- package/dist/src/core/patch-lint-cross.js +21 -21
- package/dist/src/core/patch-lint-css.d.ts +1 -1
- package/dist/src/core/patch-lint-css.js +5 -5
- package/dist/src/core/patch-lint-diff-tag.d.ts +5 -5
- package/dist/src/core/patch-lint-diff-tag.js +5 -5
- package/dist/src/core/patch-lint-diff.d.ts +4 -4
- package/dist/src/core/patch-lint-diff.js +4 -4
- package/dist/src/core/patch-lint-file-size.d.ts +3 -3
- package/dist/src/core/patch-lint-file-size.js +3 -3
- package/dist/src/core/patch-lint-forward-registration.d.ts +4 -4
- package/dist/src/core/patch-lint-forward-registration.js +12 -12
- package/dist/src/core/patch-lint-jsdoc.d.ts +2 -2
- package/dist/src/core/patch-lint-jsdoc.js +11 -11
- package/dist/src/core/patch-lint-module-registration.d.ts +1 -1
- package/dist/src/core/patch-lint-module-registration.js +1 -1
- package/dist/src/core/patch-lint-mozbuild.d.ts +1 -1
- package/dist/src/core/patch-lint-mozbuild.js +10 -10
- package/dist/src/core/patch-lint-observer.d.ts +3 -3
- package/dist/src/core/patch-lint-observer.js +7 -7
- package/dist/src/core/patch-lint-ownership.d.ts +6 -6
- package/dist/src/core/patch-lint-ownership.js +6 -6
- package/dist/src/core/patch-lint-prettier.d.ts +6 -6
- package/dist/src/core/patch-lint-prettier.js +6 -6
- package/dist/src/core/patch-lint-queue-types.d.ts +1 -1
- package/dist/src/core/patch-lint-queue-types.js +1 -1
- package/dist/src/core/patch-lint-staged-registration.d.ts +2 -2
- package/dist/src/core/patch-lint-staged-registration.js +6 -6
- package/dist/src/core/patch-lint-unmanaged-companion.d.ts +23 -23
- package/dist/src/core/patch-lint-unmanaged-companion.js +26 -26
- package/dist/src/core/patch-lint.d.ts +27 -26
- package/dist/src/core/patch-lint.js +48 -46
- package/dist/src/core/patch-lock.d.ts +1 -1
- package/dist/src/core/patch-lock.js +8 -8
- package/dist/src/core/patch-manifest-consistency.d.ts +7 -7
- package/dist/src/core/patch-manifest-consistency.js +16 -17
- package/dist/src/core/patch-manifest-files-affected.d.ts +1 -1
- package/dist/src/core/patch-manifest-files-affected.js +3 -3
- package/dist/src/core/patch-manifest-io.d.ts +14 -14
- package/dist/src/core/patch-manifest-io.js +27 -27
- package/dist/src/core/patch-manifest-query.d.ts +1 -1
- package/dist/src/core/patch-manifest-query.js +4 -4
- package/dist/src/core/patch-manifest-resolve.d.ts +5 -5
- package/dist/src/core/patch-manifest-resolve.js +7 -7
- package/dist/src/core/patch-manifest-validate.js +3 -3
- package/dist/src/core/patch-manifest.d.ts +2 -2
- package/dist/src/core/patch-manifest.js +2 -2
- package/dist/src/core/patch-parse.d.ts +14 -14
- package/dist/src/core/patch-parse.js +16 -16
- package/dist/src/core/patch-registration-refs.d.ts +4 -4
- package/dist/src/core/patch-registration-refs.js +7 -7
- package/dist/src/core/patch-transform.d.ts +8 -8
- package/dist/src/core/patch-transform.js +13 -13
- package/dist/src/core/process-cpu-time.d.ts +1 -1
- package/dist/src/core/process-cpu-time.js +5 -5
- package/dist/src/core/rebase-session.d.ts +7 -7
- package/dist/src/core/rebase-session.js +8 -8
- package/dist/src/core/register-result.d.ts +1 -1
- package/dist/src/core/register-result.js +1 -1
- package/dist/src/core/register-scaffold.d.ts +2 -2
- package/dist/src/core/register-scaffold.js +3 -3
- package/dist/src/core/register-shared-css.d.ts +3 -3
- package/dist/src/core/register-shared-css.js +4 -4
- package/dist/src/core/register-xpcshell-test.d.ts +2 -2
- package/dist/src/core/register-xpcshell-test.js +2 -2
- package/dist/src/core/run-log-redact.d.ts +12 -12
- package/dist/src/core/run-log-redact.js +16 -16
- package/dist/src/core/run-log.d.ts +9 -9
- package/dist/src/core/run-log.js +14 -14
- package/dist/src/core/shared-ftl.d.ts +2 -2
- package/dist/src/core/shared-ftl.js +6 -6
- package/dist/src/core/signal-critical.d.ts +2 -2
- package/dist/src/core/signal-critical.js +2 -2
- package/dist/src/core/smoke-patterns.d.ts +5 -5
- package/dist/src/core/smoke-patterns.js +9 -9
- package/dist/src/core/state-file.d.ts +3 -3
- package/dist/src/core/status-binary.d.ts +8 -8
- package/dist/src/core/status-binary.js +12 -12
- package/dist/src/core/status-classify.d.ts +17 -17
- package/dist/src/core/status-classify.js +11 -11
- package/dist/src/core/test-changed-prefs.d.ts +12 -12
- package/dist/src/core/test-changed-prefs.js +15 -15
- package/dist/src/core/test-harness-crash.d.ts +39 -39
- package/dist/src/core/test-harness-crash.js +67 -67
- package/dist/src/core/test-harness-output.d.ts +7 -7
- package/dist/src/core/test-harness-output.js +7 -7
- package/dist/src/core/test-harness-verdict-notes.d.ts +13 -14
- package/dist/src/core/test-harness-verdict-notes.js +4 -4
- package/dist/src/core/test-path-scope.d.ts +8 -8
- package/dist/src/core/test-path-scope.js +11 -11
- package/dist/src/core/test-stale-check.d.ts +22 -21
- package/dist/src/core/test-stale-check.js +29 -28
- package/dist/src/core/test-stale-symlink.d.ts +1 -1
- package/dist/src/core/test-stale-symlink.js +1 -1
- package/dist/src/core/test-stall-triage.d.ts +9 -9
- package/dist/src/core/test-stall-triage.js +22 -22
- package/dist/src/core/token-category.d.ts +4 -4
- package/dist/src/core/token-category.js +13 -12
- package/dist/src/core/token-coverage.js +4 -5
- package/dist/src/core/token-dark-mode.d.ts +17 -9
- package/dist/src/core/token-dark-mode.js +41 -28
- package/dist/src/core/token-docs.d.ts +1 -1
- package/dist/src/core/token-inventory.d.ts +6 -6
- package/dist/src/core/token-inventory.js +7 -7
- package/dist/src/core/token-manager.d.ts +3 -3
- package/dist/src/core/token-manager.js +21 -21
- package/dist/src/core/token-scaffold.d.ts +4 -4
- package/dist/src/core/token-scaffold.js +4 -4
- package/dist/src/core/token-variant.d.ts +14 -14
- package/dist/src/core/token-variant.js +32 -32
- package/dist/src/core/toolchain-preflight.d.ts +15 -15
- package/dist/src/core/toolchain-preflight.js +22 -22
- package/dist/src/core/tree-cow.d.ts +3 -3
- package/dist/src/core/tree-cow.js +6 -6
- package/dist/src/core/tree-guard.d.ts +3 -3
- package/dist/src/core/tree-guard.js +23 -23
- package/dist/src/core/tree-store.d.ts +15 -15
- package/dist/src/core/tree-store.js +35 -33
- package/dist/src/core/typecheck-shim.d.ts +16 -15
- package/dist/src/core/typecheck-shim.js +26 -25
- package/dist/src/core/typecheck.d.ts +12 -12
- package/dist/src/core/typecheck.js +31 -31
- package/dist/src/core/wire-destroy.d.ts +2 -2
- package/dist/src/core/wire-destroy.js +5 -5
- package/dist/src/core/wire-dom-fragment.d.ts +3 -3
- package/dist/src/core/wire-dom-fragment.js +6 -6
- package/dist/src/core/wire-init.d.ts +2 -2
- package/dist/src/core/wire-init.js +7 -7
- package/dist/src/core/wire-subscript.d.ts +1 -1
- package/dist/src/core/wire-subscript.js +3 -3
- package/dist/src/core/wire-utils.d.ts +9 -9
- package/dist/src/core/wire-utils.js +11 -11
- package/dist/src/core/xpcshell-appdir.d.ts +20 -20
- package/dist/src/core/xpcshell-appdir.js +26 -26
- package/dist/src/core/xpcshell-profile-dir.d.ts +3 -3
- package/dist/src/core/xpcshell-profile-dir.js +7 -7
- package/dist/src/errors/base.d.ts +22 -21
- package/dist/src/errors/base.js +22 -21
- package/dist/src/errors/build.d.ts +6 -6
- package/dist/src/errors/build.js +6 -6
- package/dist/src/errors/codes.d.ts +10 -10
- package/dist/src/errors/codes.js +10 -10
- package/dist/src/errors/furnace.d.ts +2 -2
- package/dist/src/errors/git.d.ts +1 -1
- package/dist/src/errors/git.js +1 -1
- package/dist/src/errors/patch.d.ts +3 -3
- package/dist/src/errors/patch.js +3 -3
- package/dist/src/errors/rebase.d.ts +1 -1
- package/dist/src/errors/rebase.js +1 -1
- package/dist/src/errors/run.d.ts +1 -1
- package/dist/src/errors/run.js +1 -1
- package/dist/src/index.d.ts +4 -4
- package/dist/src/index.js +4 -4
- package/dist/src/types/commands/options.d.ts +86 -85
- package/dist/src/types/commands/patches.d.ts +19 -19
- package/dist/src/types/commands/project.d.ts +3 -3
- package/dist/src/types/config.d.ts +24 -23
- package/dist/src/types/furnace.d.ts +17 -17
- package/dist/src/types/json.d.ts +3 -3
- package/dist/src/types/json.js +2 -2
- package/dist/src/types/typecheck.d.ts +3 -3
- package/dist/src/utils/assert.d.ts +1 -1
- package/dist/src/utils/assert.js +6 -6
- package/dist/src/utils/build-info.d.ts +5 -5
- package/dist/src/utils/build-info.js +6 -6
- package/dist/src/utils/child-env.d.ts +5 -5
- package/dist/src/utils/child-env.js +5 -5
- package/dist/src/utils/concurrency.d.ts +2 -2
- package/dist/src/utils/concurrency.js +2 -2
- package/dist/src/utils/elapsed.js +1 -1
- package/dist/src/utils/errors.d.ts +8 -8
- package/dist/src/utils/errors.js +8 -8
- package/dist/src/utils/fs.d.ts +1 -1
- package/dist/src/utils/fs.js +8 -8
- package/dist/src/utils/line-dispatch.d.ts +3 -3
- package/dist/src/utils/line-dispatch.js +5 -5
- package/dist/src/utils/logger.d.ts +4 -4
- package/dist/src/utils/logger.js +11 -11
- package/dist/src/utils/machine-output.js +2 -2
- package/dist/src/utils/options.d.ts +13 -13
- package/dist/src/utils/options.js +20 -20
- package/dist/src/utils/package-root.js +2 -2
- package/dist/src/utils/paths.d.ts +4 -4
- package/dist/src/utils/paths.js +4 -4
- package/dist/src/utils/process-group.d.ts +8 -8
- package/dist/src/utils/process-group.js +19 -19
- package/dist/src/utils/process.d.ts +34 -33
- package/dist/src/utils/process.js +20 -19
- package/dist/src/utils/ps-duration.d.ts +4 -4
- package/dist/src/utils/ps-duration.js +6 -6
- package/dist/src/utils/regex.d.ts +4 -4
- package/dist/src/utils/regex.js +7 -7
- package/dist/src/utils/sleep.d.ts +7 -7
- package/dist/src/utils/sleep.js +7 -7
- package/dist/src/utils/stdio-drain.d.ts +7 -7
- package/dist/src/utils/stdio-drain.js +8 -8
- package/dist/src/utils/validation.d.ts +11 -12
- package/dist/src/utils/validation.js +20 -21
- package/docs/README.md +2 -2
- package/docs/configuration.md +120 -114
- package/docs/exit-codes.md +63 -58
- package/docs/furnace.md +20 -19
- package/docs/lifecycle-invariants.md +412 -251
- package/docs/machine-output.md +33 -32
- package/docs/patch-workflow.md +48 -45
- package/docs/run-logs.md +62 -58
- package/docs/testing.md +101 -101
- package/docs/verification-trees.md +23 -22
- package/package.json +2 -2
package/dist/src/core/mach.js
CHANGED
|
@@ -16,7 +16,7 @@ import { detectHarnessCrashSignature } from './test-harness-crash.js';
|
|
|
16
16
|
// This block is a frozen compatibility list, not a barrel to grow: every name
|
|
17
17
|
// here already had a `from './mach.js'` import when the module was split.
|
|
18
18
|
// New helpers belong in their own sub-module and are imported from it
|
|
19
|
-
// directly
|
|
19
|
+
// directly. Adding to this list pulls the whole sub-module into every suite
|
|
20
20
|
// that mocks `mach.js`.
|
|
21
21
|
export { attemptMozinfoRewrite, buildArtifactMismatchMessage, hasBuildArtifacts, hasRunnableBundle, } from './mach-build-artifacts.js';
|
|
22
22
|
export { generateMozconfig } from './mach-mozconfig.js';
|
|
@@ -51,8 +51,8 @@ export async function runMach(args, engineDir, options = {}) {
|
|
|
51
51
|
if (options.inherit) {
|
|
52
52
|
// Group-reap every long-lived inherited mach dispatch (bootstrap, run,
|
|
53
53
|
// watch): a mach dying at startup must not strand multiprocessing
|
|
54
|
-
// workers. Short-lived metadata queries below stay on plain exec()
|
|
55
|
-
//
|
|
54
|
+
// workers. Short-lived metadata queries below stay on plain exec().
|
|
55
|
+
// Adding groups there would touch every non-mach exec consumer's path
|
|
56
56
|
// for no reaping benefit.
|
|
57
57
|
return execInherit(python, [machPath, ...args], { ...execOptions, processGroup: true });
|
|
58
58
|
}
|
|
@@ -79,7 +79,7 @@ export async function runMachCapture(args, engineDir, options = {}) {
|
|
|
79
79
|
const machPath = join(engineDir, 'mach');
|
|
80
80
|
let stdout = '';
|
|
81
81
|
let stderr = '';
|
|
82
|
-
// Echo-path filters only: the captured strings above accumulate
|
|
82
|
+
// Echo-path filters only: the captured strings above accumulate raw so the
|
|
83
83
|
// classifier still sees the full teardown traceback. When the option is
|
|
84
84
|
// off, the filters are absent and echo is a straight write (unchanged).
|
|
85
85
|
// One shutdown context per run, shared by both stream filters: the
|
|
@@ -94,18 +94,18 @@ export async function runMachCapture(args, engineDir, options = {}) {
|
|
|
94
94
|
...(options.envUnset ? { envUnset: options.envUnset } : {}),
|
|
95
95
|
// Every capture dispatch (test suites, protected builds, package,
|
|
96
96
|
// storybook) runs as a process-group leader and is group-reaped on
|
|
97
|
-
// exit/abort
|
|
97
|
+
// exit/abort. See ExecOptions.processGroup.
|
|
98
98
|
processGroup: true,
|
|
99
99
|
onStdout: (data) => {
|
|
100
100
|
stdout += data;
|
|
101
101
|
if (stdout.length > CAPTURE_TAIL_LIMIT) {
|
|
102
102
|
stdout = stdout.slice(-CAPTURE_TAIL_LIMIT);
|
|
103
103
|
}
|
|
104
|
-
//
|
|
104
|
+
// Raw into the log, filtered into the echo. The log exists to be
|
|
105
105
|
// re-read after the fact by whoever is diagnosing the run, and the
|
|
106
|
-
// echo filter
|
|
107
|
-
//
|
|
108
|
-
//
|
|
106
|
+
// echo filter only exists to shorten what a human scrolls past.
|
|
107
|
+
// Collapsing a traceback in the artifact would reintroduce the loss
|
|
108
|
+
// this log exists to prevent.
|
|
109
109
|
writeToActiveRunLog(data);
|
|
110
110
|
process.stdout.write(stdoutFilter ? stdoutFilter.transform(data) : data);
|
|
111
111
|
},
|
|
@@ -163,9 +163,9 @@ export async function bootstrapWithOutput(engineDir) {
|
|
|
163
163
|
* propagates so the hint sits immediately below the raw mach error in the
|
|
164
164
|
* operator's terminal.
|
|
165
165
|
*
|
|
166
|
-
* The scanner is passed the concatenation of stderr
|
|
166
|
+
* The scanner is passed the concatenation of stderr and stdout because mach
|
|
167
167
|
* streams its subcommand output through a timestamp-prefixing wrapper that
|
|
168
|
-
* writes both streams to whatever FD the subprocess chose
|
|
168
|
+
* writes both streams to whatever FD the subprocess chose, so `rustc` errors
|
|
169
169
|
* from `mach build` can land on stdout, so feeding only `result.stderr`
|
|
170
170
|
* silently loses the match.
|
|
171
171
|
*/
|
|
@@ -186,10 +186,10 @@ function surfaceMachErrorHints(result) {
|
|
|
186
186
|
*/
|
|
187
187
|
const DEFAULT_BUILD_CRASH_RETRIES = 2;
|
|
188
188
|
/**
|
|
189
|
-
* Names the known mozsystemmonitor teardown traceback when a
|
|
190
|
-
* it. The test path collapses this signature in the echo
|
|
189
|
+
* Names the known mozsystemmonitor teardown traceback when a build carried
|
|
190
|
+
* it. The test path collapses this signature in the echo. A build cannot
|
|
191
191
|
* (see `mach-known-noise-filter.ts`), so it reached operators as an
|
|
192
|
-
* unexplained traceback in a build log
|
|
192
|
+
* unexplained traceback in a build log: a recognized, documented upstream
|
|
193
193
|
* defect wearing the appearance of a new one. The output is left verbatim
|
|
194
194
|
* and this one line is added beside it, so the same signature reads the same
|
|
195
195
|
* in both phases.
|
|
@@ -201,20 +201,20 @@ function noteKnownTeardownNoiseInBuild(result) {
|
|
|
201
201
|
}
|
|
202
202
|
/**
|
|
203
203
|
* The single protected path every FireForge mach build dispatch routes
|
|
204
|
-
* through
|
|
204
|
+
* through. `build`, `build --ui`, and the pre-test `--build` step all use
|
|
205
205
|
* it, so no entry point is left unprotected with a different retry budget:
|
|
206
206
|
*
|
|
207
|
-
* 1. installs the resource-monitor degrade guard
|
|
208
|
-
* (plus the PYTHONPATH fallback)
|
|
207
|
+
* 1. installs the resource-monitor degrade guard in the mach virtualenvs
|
|
208
|
+
* (plus the PYTHONPATH fallback), re-installed before every attempt, so
|
|
209
209
|
* a venv materialized by a crashed first attempt is guarded on the next
|
|
210
|
-
* one instead of every retry dying on the same wedged state
|
|
211
|
-
* 2. spawns a fresh mach process per attempt
|
|
212
|
-
* 3. retries
|
|
213
|
-
* psutil startup tracebacks) up to the uniform budget
|
|
210
|
+
* one instead of every retry dying on the same wedged state.
|
|
211
|
+
* 2. spawns a fresh mach process per attempt.
|
|
212
|
+
* 3. retries only the recognized harness-crash family (resource monitor /
|
|
213
|
+
* psutil startup tracebacks) up to the uniform budget. An ordinary
|
|
214
214
|
* compile error is never retried.
|
|
215
215
|
*
|
|
216
216
|
* The protected path never runs `mach configure`, never clobbers, and never
|
|
217
|
-
* widens the requested build kind
|
|
217
|
+
* widens the requested build kind: a `faster` dispatch retries as
|
|
218
218
|
* `mach build faster`, so it cannot invalidate more of the objdir than the
|
|
219
219
|
* command the operator asked for.
|
|
220
220
|
*/
|
|
@@ -250,8 +250,8 @@ export async function runProtectedMachBuild(kind, engineDir, options = {}) {
|
|
|
250
250
|
* hints are surfaced on top of the raw mach output so operators get an
|
|
251
251
|
* actionable nudge alongside the cryptic mozbuild traceback. Returns the
|
|
252
252
|
* captured result so the caller (e.g. `fireforge build`) can inspect the
|
|
253
|
-
* tail for post-build diagnostics that mach prints
|
|
254
|
-
* successful!"
|
|
253
|
+
* tail for post-build diagnostics that mach prints after "Your build was
|
|
254
|
+
* successful!", notably the stale `config.status is out of date`
|
|
255
255
|
* notice that mach emits when a tool-managed edit landed on
|
|
256
256
|
* `moz.configure` before the build.
|
|
257
257
|
* @param engineDir - Path to the engine directory
|
|
@@ -279,13 +279,13 @@ export async function buildUI(engineDir) {
|
|
|
279
279
|
*
|
|
280
280
|
* Without it, a `build --ui` started while a full `build` is still in flight
|
|
281
281
|
* hands off to `mach build faster` and fails almost immediately with `No
|
|
282
|
-
* rule to make target 'XUL'
|
|
282
|
+
* rule to make target 'XUL'`, the real problem being that the first build
|
|
283
283
|
* has not yet materialised the full backend, with nothing in the low-level
|
|
284
284
|
* make error pointing at the concurrent run. The lock intercepts the second
|
|
285
285
|
* invocation before it touches mach, and the refusal names the PID holding
|
|
286
286
|
* the lock so the operator can decide whether to wait or investigate.
|
|
287
287
|
*
|
|
288
|
-
* Stale-lock recovery: the lock stores the owner PID
|
|
288
|
+
* Stale-lock recovery: the lock stores the owner PID. A crashed build
|
|
289
289
|
* (SIGINT, SIGTERM, or a kernel kill) leaves the lock dir behind but not the
|
|
290
290
|
* owning process, and `withFileLock` removes the lock on the next attempt
|
|
291
291
|
* when `process.kill(pid, 0)` shows the owner is gone.
|
|
@@ -299,9 +299,9 @@ export async function buildUI(engineDir) {
|
|
|
299
299
|
export async function withBuildLock(projectRoot, operation) {
|
|
300
300
|
const lockPath = createSiblingLockPath(join(projectRoot, '.fireforge-build'), '.lock');
|
|
301
301
|
return withFileLock(lockPath, operation, {
|
|
302
|
-
// Default lock timeout is 30s
|
|
303
|
-
// not trip the timeout while the second invocation waits. A real
|
|
304
|
-
// operator will ^C long before 24h elapses
|
|
302
|
+
// Default lock timeout is 30s. Bump it to 24h so a slow full build
|
|
303
|
+
// does not trip the timeout while the second invocation waits. A real
|
|
304
|
+
// operator will ^C long before 24h elapses. The ceiling is there
|
|
305
305
|
// purely so a forgotten lock cannot wedge the command forever.
|
|
306
306
|
timeoutMs: 24 * 60 * 60 * 1000,
|
|
307
307
|
onTimeoutMessage: `Timed out waiting for the FireForge build lock at ${lockPath}. ` +
|
|
@@ -323,7 +323,7 @@ export async function run(engineDir, args = []) {
|
|
|
323
323
|
* enforces a deadline by SIGTERMing the whole process group, and returns
|
|
324
324
|
* the captured output alongside a `timedOut` flag.
|
|
325
325
|
*
|
|
326
|
-
* Unlike {@link run}, this variant does
|
|
326
|
+
* Unlike {@link run}, this variant does not inherit stdio. The child
|
|
327
327
|
* stdout/stderr are piped back through the line callbacks so the caller
|
|
328
328
|
* can scan for `JavaScript error:` / `console.error:` without coupling
|
|
329
329
|
* the runner to chrome-specific pattern logic.
|
|
@@ -360,7 +360,7 @@ export async function machPackageCapture(engineDir) {
|
|
|
360
360
|
* `env` is threaded through so the caller can prepend the resolved watchman
|
|
361
361
|
* directory to PATH in a way mach inherits: `fireforge watch` can locate
|
|
362
362
|
* `watchman` via `which`, but the mach subprocess spawns with the parent's
|
|
363
|
-
* PATH only
|
|
363
|
+
* PATH only, and on macOS that typically omits `/opt/homebrew/bin`, so
|
|
364
364
|
* `mach watch` fails at the `watch-project` subscription step.
|
|
365
365
|
*
|
|
366
366
|
* @param engineDir - Path to the engine directory
|
|
@@ -376,13 +376,13 @@ export async function watchWithOutput(engineDir, options = {}) {
|
|
|
376
376
|
* agent (`mozbuild.util.is_running_under_coding_agent`), which quiets
|
|
377
377
|
* terminal output to warnings and errors.
|
|
378
378
|
*
|
|
379
|
-
* The quieting is genuinely useful for
|
|
380
|
-
* agent session prints
|
|
379
|
+
* The quieting is genuinely useful for builds, which are most of what an
|
|
380
|
+
* agent session prints, but it applies to test runs too, where it removes
|
|
381
381
|
* `TEST_START` and console INFO: exactly the lines a hang or stall
|
|
382
382
|
* diagnosis needs, and the ones FireForge's own classifier reads
|
|
383
383
|
* (`Ran N checks`, `Unexpected results:`, `TEST-UNEXPECTED-*`). Unsetting
|
|
384
384
|
* the variable globally would give up the build half as well, so the
|
|
385
|
-
* dispatchers below unset it per
|
|
385
|
+
* dispatchers below unset it per test dispatch and leave the build path
|
|
386
386
|
* alone.
|
|
387
387
|
*/
|
|
388
388
|
const CODING_AGENT_ENV_MARKERS = ['CLAUDECODE'];
|
|
@@ -399,8 +399,8 @@ function testVerbosityEnvUnset(fullOutput) {
|
|
|
399
399
|
/**
|
|
400
400
|
* Runs one mach test command (`mach test` / `mach xpcshell-test` / `mach
|
|
401
401
|
* mochitest`) while capturing streamed output for better diagnostics. The
|
|
402
|
-
* three commands share every other detail of the dispatch
|
|
403
|
-
* verbosity env, teardown-noise annotation
|
|
402
|
+
* three commands share every other detail of the dispatch (resource guard,
|
|
403
|
+
* verbosity env, teardown-noise annotation), so they share one entry point
|
|
404
404
|
* keyed by `kind` rather than three copies that drift.
|
|
405
405
|
*
|
|
406
406
|
* @param kind - Which mach command to run
|
|
@@ -11,7 +11,7 @@ export interface MarionettePortHolder {
|
|
|
11
11
|
/**
|
|
12
12
|
* Full command line the holder was launched with, when the probe
|
|
13
13
|
* can recover it. `lsof` by itself only returns the basename, so
|
|
14
|
-
* POSIX callers see `command === commandLine
|
|
14
|
+
* POSIX callers see `command === commandLine`. Windows callers
|
|
15
15
|
* recover the full command line via `Get-Process`. Used to detect
|
|
16
16
|
* the `-marionette` flag, which positively identifies a stale
|
|
17
17
|
* browser rather than an unrelated listener.
|
|
@@ -33,7 +33,7 @@ export interface RunningBundleProcess {
|
|
|
33
33
|
commandLine: string;
|
|
34
34
|
/**
|
|
35
35
|
* Elapsed wall-clock seconds since the process started, from `ps
|
|
36
|
-
* etime=`. `NaN` when the field was absent or unparseable
|
|
36
|
+
* etime=`. `NaN` when the field was absent or unparseable, and callers must
|
|
37
37
|
* omit the clause rather than print a zero, because "started 0s ago" is
|
|
38
38
|
* exactly the wrong attribution for a peer session's long-lived browser.
|
|
39
39
|
*/
|
|
@@ -44,7 +44,7 @@ export interface RunningBundleProcess {
|
|
|
44
44
|
* regression-testable.
|
|
45
45
|
*
|
|
46
46
|
* Reads `pid etime args` where the middle field is a `ps` duration. The
|
|
47
|
-
* elapsed field is parsed
|
|
47
|
+
* elapsed field is parsed optimistically: a listing produced without
|
|
48
48
|
* `etime=` still parses, with the duration reported as `NaN` and the whole
|
|
49
49
|
* second field folded back into the command line, so a caller that lost the
|
|
50
50
|
* column degrades to the old behaviour instead of dropping the process.
|
|
@@ -62,17 +62,17 @@ export declare function ensureLaunchableBrowserNotRunning(launchableBinary: stri
|
|
|
62
62
|
/**
|
|
63
63
|
* Builds the refusal for a running objdir browser.
|
|
64
64
|
*
|
|
65
|
-
* Reports the
|
|
65
|
+
* Reports the evidence rather than a bare PID: the elapsed time and the
|
|
66
66
|
* command line are what let an operator on a shared checkout decide whose
|
|
67
67
|
* process it is, without reconstructing PID ancestry by hand. A downstream
|
|
68
|
-
* fork hit exactly this
|
|
68
|
+
* fork hit exactly this: the message named a PID belonging to a peer
|
|
69
69
|
* session's live browser and offered a flag that would have killed a
|
|
70
70
|
* multi-hour evaluation run.
|
|
71
71
|
*
|
|
72
|
-
* So `--kill-stale-marionette` is offered
|
|
72
|
+
* So `--kill-stale-marionette` is offered only for a marionette-driven
|
|
73
73
|
* browser. For a bare launch the message says what it found and stops:
|
|
74
74
|
* FireForge cannot tell a dead run's orphan from someone's live window, and
|
|
75
|
-
* the flag is the right
|
|
75
|
+
* the flag is the right manual clear once ownership is verified, never an
|
|
76
76
|
* automatic one.
|
|
77
77
|
*
|
|
78
78
|
* Exported for direct unit testing.
|
|
@@ -88,7 +88,7 @@ export declare function describeRunningBundleRefusal(holder: RunningBundleProces
|
|
|
88
88
|
export declare function probeMarionettePort(port?: number): Promise<MarionettePortProbeResult>;
|
|
89
89
|
/**
|
|
90
90
|
* Raises a targeted {@link GeneralError} when the Marionette port
|
|
91
|
-
* is held by a browser process
|
|
91
|
+
* is held by a browser process. Raises a softer warning-shaped
|
|
92
92
|
* error when the holder is unrelated (so the operator still sees
|
|
93
93
|
* a useful signal but can decide whether to wait it out).
|
|
94
94
|
*
|
|
@@ -118,18 +118,20 @@ export declare function ensureMarionettePortAvailable(port?: number, options?: {
|
|
|
118
118
|
* the test command auto-forwards to mach.
|
|
119
119
|
*
|
|
120
120
|
* @param machArgs - Forwarded mach args as they would appear on the command
|
|
121
|
-
* line (one element per token
|
|
122
|
-
*
|
|
123
|
-
*
|
|
121
|
+
* line (one element per token, with `--foo=bar` and `--foo bar` both
|
|
122
|
+
* supported).
|
|
123
|
+
* @returns The integer port if a recognised arg is present and parses,
|
|
124
|
+
* otherwise `undefined`.
|
|
124
125
|
*/
|
|
125
126
|
export declare function extractForwardedMarionettePort(machArgs: string[]): number | undefined;
|
|
126
127
|
/**
|
|
127
128
|
* True when forwarded mach args already set a Marionette **client** address
|
|
128
129
|
* for mach/mochitest (`--marionette=host:port` or `--marionette host:port`).
|
|
129
130
|
* Used only to avoid duplicating FireForge's auto-injected
|
|
130
|
-
* `--marionette=127.0.0.1:<n
|
|
131
|
+
* `--marionette=127.0.0.1:<n>`. This is not a full URL validator (IPv6,
|
|
132
|
+
* etc.).
|
|
131
133
|
*
|
|
132
|
-
*
|
|
134
|
+
* Does not treat `--marionette-port` as a client endpoint.
|
|
133
135
|
*/
|
|
134
136
|
export declare function forwardedMachArgsIncludeMarionetteClient(machArgs: string[]): boolean;
|
|
135
137
|
/**
|
|
@@ -7,11 +7,11 @@
|
|
|
7
7
|
* browser with that flag, so any test run needs the port free at start.
|
|
8
8
|
*
|
|
9
9
|
* An interrupted `fireforge test` can leave an orphan browser process
|
|
10
|
-
* listening on 2828 with parent PID 1, and the next test run
|
|
11
|
-
* *different* FireForge project
|
|
12
|
-
* error. This probe runs before every test launch
|
|
13
|
-
* held
|
|
14
|
-
* `-marionette` flag or by basename matching a known browser binary)
|
|
10
|
+
* listening on 2828 with parent PID 1, and the next test run (possibly in a
|
|
11
|
+
* *different* FireForge project) then fails with a bare Marionette bind
|
|
12
|
+
* error. This probe runs before every test launch and detects when the port
|
|
13
|
+
* is held. When the holder is a browser process (by command-line
|
|
14
|
+
* `-marionette` flag or by basename matching a known browser binary), it
|
|
15
15
|
* throws a targeted `GeneralError` naming the PID and the exact `kill`
|
|
16
16
|
* command to run.
|
|
17
17
|
*
|
|
@@ -22,7 +22,8 @@
|
|
|
22
22
|
*
|
|
23
23
|
* Both paths tolerate missing tooling: if `lsof` / PowerShell is not
|
|
24
24
|
* installed the probe returns `{ inUse: false }` rather than failing the
|
|
25
|
-
* test run
|
|
25
|
+
* test run. It is a best-effort friendliness check rather than a
|
|
26
|
+
* prerequisite.
|
|
26
27
|
*/
|
|
27
28
|
import { PreflightRefusalError } from '../errors/base.js';
|
|
28
29
|
import { toError } from '../utils/errors.js';
|
|
@@ -63,7 +64,7 @@ async function findRunningBundleProcesses(launchableBinary) {
|
|
|
63
64
|
return parseProcessList(result.stdout, launchableBinary);
|
|
64
65
|
}
|
|
65
66
|
// `etime=` is what makes the refusal attributable on a shared checkout:
|
|
66
|
-
// a browser that started as
|
|
67
|
+
// a browser that started as your run was finishing is not yours.
|
|
67
68
|
const result = await exec('ps', ['-axo', 'pid=,etime=,args=']);
|
|
68
69
|
return parseProcessList(result.stdout, launchableBinary);
|
|
69
70
|
}
|
|
@@ -76,7 +77,7 @@ async function findRunningBundleProcesses(launchableBinary) {
|
|
|
76
77
|
* regression-testable.
|
|
77
78
|
*
|
|
78
79
|
* Reads `pid etime args` where the middle field is a `ps` duration. The
|
|
79
|
-
* elapsed field is parsed
|
|
80
|
+
* elapsed field is parsed optimistically: a listing produced without
|
|
80
81
|
* `etime=` still parses, with the duration reported as `NaN` and the whole
|
|
81
82
|
* second field folded back into the command line, so a caller that lost the
|
|
82
83
|
* column degrades to the old behaviour instead of dropping the process.
|
|
@@ -139,13 +140,13 @@ export async function ensureLaunchableBrowserNotRunning(launchableBinary, option
|
|
|
139
140
|
throw new PreflightRefusalError(describeRunningBundleRefusal(holder), 'stale-browser');
|
|
140
141
|
}
|
|
141
142
|
/**
|
|
142
|
-
* True when the process was launched
|
|
143
|
-
* carries `-marionette` (the control channel every `fireforge test`
|
|
144
|
-
* is started with) or a harness `-profile`.
|
|
143
|
+
* True when the process was launched by a test harness, i.e. its command
|
|
144
|
+
* line carries `-marionette` (the control channel every `fireforge test`
|
|
145
|
+
* browser is started with) or a harness `-profile`.
|
|
145
146
|
*
|
|
146
147
|
* This is the distinction the refusal turns on. The objdir-bundle probe
|
|
147
148
|
* matches any process running this project's binary, which on a shared
|
|
148
|
-
* checkout includes a peer session's
|
|
149
|
+
* checkout includes a peer session's live browser and a developer's own
|
|
149
150
|
* interactive one. Only a marionette-driven browser is safely
|
|
150
151
|
* attributable to an interrupted run.
|
|
151
152
|
*/
|
|
@@ -155,17 +156,17 @@ function isHarnessDrivenBrowser(commandLine) {
|
|
|
155
156
|
/**
|
|
156
157
|
* Builds the refusal for a running objdir browser.
|
|
157
158
|
*
|
|
158
|
-
* Reports the
|
|
159
|
+
* Reports the evidence rather than a bare PID: the elapsed time and the
|
|
159
160
|
* command line are what let an operator on a shared checkout decide whose
|
|
160
161
|
* process it is, without reconstructing PID ancestry by hand. A downstream
|
|
161
|
-
* fork hit exactly this
|
|
162
|
+
* fork hit exactly this: the message named a PID belonging to a peer
|
|
162
163
|
* session's live browser and offered a flag that would have killed a
|
|
163
164
|
* multi-hour evaluation run.
|
|
164
165
|
*
|
|
165
|
-
* So `--kill-stale-marionette` is offered
|
|
166
|
+
* So `--kill-stale-marionette` is offered only for a marionette-driven
|
|
166
167
|
* browser. For a bare launch the message says what it found and stops:
|
|
167
168
|
* FireForge cannot tell a dead run's orphan from someone's live window, and
|
|
168
|
-
* the flag is the right
|
|
169
|
+
* the flag is the right manual clear once ownership is verified, never an
|
|
169
170
|
* automatic one.
|
|
170
171
|
*
|
|
171
172
|
* Exported for direct unit testing.
|
|
@@ -216,19 +217,19 @@ function isBrowserMarionettePortHolder(holder, binaryName) {
|
|
|
216
217
|
}
|
|
217
218
|
/**
|
|
218
219
|
* Probes the given port with `lsof` (macOS / Linux). Returns
|
|
219
|
-
* `{ inUse: false }` when the port is free
|
|
220
|
-
* available
|
|
220
|
+
* `{ inUse: false }` when the port is free or when `lsof` is not
|
|
221
|
+
* available. The probe is a best-effort courtesy check, so a
|
|
221
222
|
* missing tool must not block the test run.
|
|
222
223
|
*/
|
|
223
224
|
async function probeWithLsof(port) {
|
|
224
225
|
try {
|
|
225
|
-
// `-sTCP:LISTEN` filters to listeners only
|
|
226
|
+
// `-sTCP:LISTEN` filters to listeners only, and `-P -n` avoids
|
|
226
227
|
// service/host lookups (faster + no DNS-dependent flakiness).
|
|
227
228
|
// `-Fpcn` emits a machine-readable format: one field per line,
|
|
228
229
|
// with `p<pid>`, `c<command>`, `n<name>` records.
|
|
229
230
|
const result = await exec('lsof', ['-i', `tcp:${port}`, '-P', '-n', '-sTCP:LISTEN', '-Fpcn']);
|
|
230
|
-
// `lsof` exits 1 when no matches
|
|
231
|
-
// error. We key off stdout shape instead of exit code.
|
|
231
|
+
// `lsof` exits 1 when no matches, which means "port is free" rather
|
|
232
|
+
// than an error. We key off stdout shape instead of exit code.
|
|
232
233
|
const stdout = result.stdout;
|
|
233
234
|
const lines = stdout.split(/\r?\n/).filter((l) => l.length > 0);
|
|
234
235
|
let pid = -1;
|
|
@@ -242,7 +243,7 @@ async function probeWithLsof(port) {
|
|
|
242
243
|
if (!Number.isFinite(pid) || pid < 0 || command === '') {
|
|
243
244
|
return { inUse: false };
|
|
244
245
|
}
|
|
245
|
-
// `lsof` does not return the full command line
|
|
246
|
+
// `lsof` does not return the full command line, but `ps` does. A
|
|
246
247
|
// missing `ps` (exotic Linux container) falls back to `command`
|
|
247
248
|
// alone, which is still enough to match `BROWSER_BASENAMES`.
|
|
248
249
|
let commandLine = command;
|
|
@@ -253,7 +254,7 @@ async function probeWithLsof(port) {
|
|
|
253
254
|
commandLine = psLine.trim();
|
|
254
255
|
}
|
|
255
256
|
catch {
|
|
256
|
-
// ps not available
|
|
257
|
+
// ps not available, so keep the basename.
|
|
257
258
|
}
|
|
258
259
|
return { inUse: true, holder: { pid, command, commandLine } };
|
|
259
260
|
}
|
|
@@ -320,7 +321,7 @@ export async function probeMarionettePort(port = DEFAULT_MARIONETTE_PORT) {
|
|
|
320
321
|
platform = getPlatform();
|
|
321
322
|
}
|
|
322
323
|
catch {
|
|
323
|
-
// Unrecognised host platform
|
|
324
|
+
// Unrecognised host platform, so no probe strategy applies and the port is
|
|
324
325
|
// reported free rather than blocking the run.
|
|
325
326
|
return { inUse: false };
|
|
326
327
|
}
|
|
@@ -332,7 +333,7 @@ export async function probeMarionettePort(port = DEFAULT_MARIONETTE_PORT) {
|
|
|
332
333
|
}
|
|
333
334
|
/**
|
|
334
335
|
* Raises a targeted {@link GeneralError} when the Marionette port
|
|
335
|
-
* is held by a browser process
|
|
336
|
+
* is held by a browser process. Raises a softer warning-shaped
|
|
336
337
|
* error when the holder is unrelated (so the operator still sees
|
|
337
338
|
* a useful signal but can decide whether to wait it out).
|
|
338
339
|
*
|
|
@@ -405,9 +406,10 @@ export async function ensureMarionettePortAvailable(port = DEFAULT_MARIONETTE_PO
|
|
|
405
406
|
* the test command auto-forwards to mach.
|
|
406
407
|
*
|
|
407
408
|
* @param machArgs - Forwarded mach args as they would appear on the command
|
|
408
|
-
* line (one element per token
|
|
409
|
-
*
|
|
410
|
-
*
|
|
409
|
+
* line (one element per token, with `--foo=bar` and `--foo bar` both
|
|
410
|
+
* supported).
|
|
411
|
+
* @returns The integer port if a recognised arg is present and parses,
|
|
412
|
+
* otherwise `undefined`.
|
|
411
413
|
*/
|
|
412
414
|
export function extractForwardedMarionettePort(machArgs) {
|
|
413
415
|
for (const [i, arg] of machArgs.entries()) {
|
|
@@ -427,7 +429,7 @@ export function extractForwardedMarionettePort(machArgs) {
|
|
|
427
429
|
return n;
|
|
428
430
|
}
|
|
429
431
|
}
|
|
430
|
-
// `--setpref=marionette.port=NNNN
|
|
432
|
+
// `--setpref=marionette.port=NNNN`, the auto-forward shape. Recognised
|
|
431
433
|
// here so a duplicate check at the call site can spot operator-supplied
|
|
432
434
|
// setprefs without re-implementing the parse.
|
|
433
435
|
match = /^--setpref=marionette\.port=(\d+)$/.exec(arg);
|
|
@@ -443,9 +445,10 @@ export function extractForwardedMarionettePort(machArgs) {
|
|
|
443
445
|
* True when forwarded mach args already set a Marionette **client** address
|
|
444
446
|
* for mach/mochitest (`--marionette=host:port` or `--marionette host:port`).
|
|
445
447
|
* Used only to avoid duplicating FireForge's auto-injected
|
|
446
|
-
* `--marionette=127.0.0.1:<n
|
|
448
|
+
* `--marionette=127.0.0.1:<n>`. This is not a full URL validator (IPv6,
|
|
449
|
+
* etc.).
|
|
447
450
|
*
|
|
448
|
-
*
|
|
451
|
+
* Does not treat `--marionette-port` as a client endpoint.
|
|
449
452
|
*/
|
|
450
453
|
export function forwardedMachArgsIncludeMarionetteClient(machArgs) {
|
|
451
454
|
const valueLooksLikeHostPort = (token) => /:[0-9]+$/.test(token) || /^\[[^]]+\]:[0-9]+$/.test(token);
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Answers a single question before tests run: "does marionette come up?" A
|
|
5
5
|
* silent 360-second mach-test hang is indistinguishable from "tests failed
|
|
6
|
-
* to discover"
|
|
6
|
+
* to discover". This helper surfaces the failure in under a minute with a
|
|
7
7
|
* clear PASS/FAIL line and the tail of the browser's stderr.
|
|
8
8
|
*
|
|
9
9
|
* The probe is a cascade of layered checks (engine → mach → python →
|
|
@@ -22,7 +22,7 @@ export interface MarionettePreflightResult {
|
|
|
22
22
|
export interface MarionettePreflightOptions {
|
|
23
23
|
/** Total budget in ms. Defaults to 30 seconds. */
|
|
24
24
|
timeoutMs?: number;
|
|
25
|
-
/** Overrides marionette TCP port
|
|
25
|
+
/** Overrides marionette TCP port. Primarily used in tests. */
|
|
26
26
|
port?: number;
|
|
27
27
|
/**
|
|
28
28
|
* Grace window after spawn() before the browser is considered "running
|
|
@@ -37,16 +37,16 @@ export interface MarionettePreflightOptions {
|
|
|
37
37
|
}
|
|
38
38
|
/**
|
|
39
39
|
* Runs the marionette preflight. Returns PASS on first byte read from the
|
|
40
|
-
* marionette socket within the budget
|
|
41
|
-
* identifying which layer of the cascade broke. Always tears
|
|
42
|
-
* spawned browser before returning.
|
|
40
|
+
* marionette socket within the budget, and FAIL otherwise, with a
|
|
41
|
+
* diagnostic identifying which layer of the cascade broke. Always tears
|
|
42
|
+
* down the spawned browser before returning.
|
|
43
43
|
*/
|
|
44
44
|
export declare function runMarionettePreflight(engineDir: string, options?: MarionettePreflightOptions): Promise<MarionettePreflightResult>;
|
|
45
45
|
/** Renders a PASS/FAIL banner to the CLI using the shared logger helpers. */
|
|
46
46
|
export declare function reportMarionettePreflight(result: MarionettePreflightResult): void;
|
|
47
47
|
/**
|
|
48
48
|
* Formats the PASS/FAIL banner as a plain string for direct
|
|
49
|
-
* `process.stdout.write` use
|
|
49
|
+
* `process.stdout.write` use, bypassing the clack logger entirely so
|
|
50
50
|
* operators running `fireforge test --doctor` under a non-TTY (pipe, CI,
|
|
51
51
|
* `tee`-wrapped capture) always see the final line. Clack's renderer can
|
|
52
52
|
* swallow trailing log output just before process exit, and a
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Answers a single question before tests run: "does marionette come up?" A
|
|
6
6
|
* silent 360-second mach-test hang is indistinguishable from "tests failed
|
|
7
|
-
* to discover"
|
|
7
|
+
* to discover". This helper surfaces the failure in under a minute with a
|
|
8
8
|
* clear PASS/FAIL line and the tail of the browser's stderr.
|
|
9
9
|
*
|
|
10
10
|
* The probe is a cascade of layered checks (engine → mach → python →
|
|
@@ -34,7 +34,7 @@ const SOCKET_ATTEMPT_TIMEOUT_MS = 2_000;
|
|
|
34
34
|
/**
|
|
35
35
|
* Grace window after spawn() returns before we accept the child as
|
|
36
36
|
* "spawned OK". A browser binary that exits immediately (missing dylib,
|
|
37
|
-
* wrong CPU arch, corrupt profile) must be caught here
|
|
37
|
+
* wrong CPU arch, corrupt profile) must be caught here, not 30 seconds
|
|
38
38
|
* later at the socket layer.
|
|
39
39
|
*/
|
|
40
40
|
const SPAWN_SETTLE_MS = 750;
|
|
@@ -58,9 +58,9 @@ function layerTag(name) {
|
|
|
58
58
|
}
|
|
59
59
|
/**
|
|
60
60
|
* Runs the marionette preflight. Returns PASS on first byte read from the
|
|
61
|
-
* marionette socket within the budget
|
|
62
|
-
* identifying which layer of the cascade broke. Always tears
|
|
63
|
-
* spawned browser before returning.
|
|
61
|
+
* marionette socket within the budget, and FAIL otherwise, with a
|
|
62
|
+
* diagnostic identifying which layer of the cascade broke. Always tears
|
|
63
|
+
* down the spawned browser before returning.
|
|
64
64
|
*/
|
|
65
65
|
export async function runMarionettePreflight(engineDir, options = {}) {
|
|
66
66
|
const timeoutMs = options.timeoutMs ?? DEFAULT_PREFLIGHT_TIMEOUT_MS;
|
|
@@ -101,15 +101,15 @@ export async function runMarionettePreflight(engineDir, options = {}) {
|
|
|
101
101
|
let stderrTail = '';
|
|
102
102
|
// Shutdown contract for a child spawned outside the exec layer.
|
|
103
103
|
//
|
|
104
|
-
// This is the
|
|
105
|
-
//
|
|
104
|
+
// This is the one raw `spawn` in the repo. The preflight needs the live
|
|
105
|
+
// `ChildProcess` mid-run (`hasChildExited` gates the socket poll),
|
|
106
106
|
// returns while the browser is still running, and aborts on a TCP byte
|
|
107
|
-
// rather than on a deadline
|
|
108
|
-
//
|
|
109
|
-
//
|
|
110
|
-
//
|
|
111
|
-
//
|
|
112
|
-
//
|
|
107
|
+
// rather than on a deadline. No wrapper in utils/process can express
|
|
108
|
+
// that. It still has to honour the contract every wrapper applies to a
|
|
109
|
+
// detached child: register the closure so the bin signal handler waits
|
|
110
|
+
// for it, and forward the parent's SIGINT/SIGTERM to the group. Without
|
|
111
|
+
// both, Ctrl+C during `fireforge test --doctor` left the whole
|
|
112
|
+
// mach → Firefox tree running.
|
|
113
113
|
let closure;
|
|
114
114
|
let forwarder;
|
|
115
115
|
try {
|
|
@@ -130,7 +130,7 @@ export async function runMarionettePreflight(engineDir, options = {}) {
|
|
|
130
130
|
// `detached: true` puts the child in a new process group so we can
|
|
131
131
|
// signal it and every descendant (Firefox, its helpers) via
|
|
132
132
|
// `process.kill(-pid, …)` in the finally block. Without it, the
|
|
133
|
-
// child is Python running mach
|
|
133
|
+
// child is Python running mach. A SIGTERM kills Python but the
|
|
134
134
|
// Firefox grandchild inherits the stderr pipe FD and keeps Node's
|
|
135
135
|
// event loop alive even after the preflight PASS log, so
|
|
136
136
|
// `fireforge test --doctor` prints `Marionette preflight: PASS`
|
|
@@ -150,7 +150,7 @@ export async function runMarionettePreflight(engineDir, options = {}) {
|
|
|
150
150
|
const chunk = data.toString();
|
|
151
151
|
stderrTail = (stderrTail + chunk).slice(-STDERR_TAIL_LIMIT);
|
|
152
152
|
});
|
|
153
|
-
// Short settle window
|
|
153
|
+
// Short settle window. Catches "binary exits immediately" failures
|
|
154
154
|
// (missing dylib, wrong CPU arch, corrupt profile) before the socket
|
|
155
155
|
// poll swallows the full overall budget waiting for bytes that will
|
|
156
156
|
// never come.
|
|
@@ -173,7 +173,7 @@ export async function runMarionettePreflight(engineDir, options = {}) {
|
|
|
173
173
|
detail: `Marionette handshake received on 127.0.0.1:${port} in ${Date.now() - startedAt}ms.`,
|
|
174
174
|
};
|
|
175
175
|
}
|
|
176
|
-
// Child may have exited before the socket was ever ready
|
|
176
|
+
// Child may have exited before the socket was ever ready. Surface that
|
|
177
177
|
// distinctly from "socket never answered" so the operator has a lead.
|
|
178
178
|
if (hasChildExited(spawnedChild)) {
|
|
179
179
|
return fail('marionette-handshake', `Browser process exited before marionette handshake (exit code ${spawnedChild.exitCode}, signal ${spawnedChild.signalCode ?? 'none'}). ` +
|
|
@@ -213,8 +213,8 @@ async function teardownPreflightChild(child, forwarder, closure, profileDir) {
|
|
|
213
213
|
}
|
|
214
214
|
}
|
|
215
215
|
// Reap anything that outlived the group signal. The file's own comments
|
|
216
|
-
// worry about exactly this
|
|
217
|
-
// mach wrapper
|
|
216
|
+
// worry about exactly this case (Firefox grandchildren surviving the
|
|
217
|
+
// Python mach wrapper), and every exec-layer wrapper sweeps for it.
|
|
218
218
|
if (groupPid !== undefined && process.platform !== 'win32') {
|
|
219
219
|
try {
|
|
220
220
|
await sweepProcessGroup(groupPid);
|
|
@@ -226,8 +226,8 @@ async function teardownPreflightChild(child, forwarder, closure, profileDir) {
|
|
|
226
226
|
closure?.settle();
|
|
227
227
|
// Destroy the stderr pipe explicitly. Firefox (a grandchild of the Python
|
|
228
228
|
// mach wrapper we spawned) can inherit and hold the stderr FD even after
|
|
229
|
-
// its direct parent exits
|
|
230
|
-
//
|
|
229
|
+
// its direct parent exits. Until the pipe closes, Node's readable stream
|
|
230
|
+
// stays attached and `uv__io_poll` keeps the event loop alive.
|
|
231
231
|
// `destroy()` closes the local end regardless, so `fireforge test
|
|
232
232
|
// --doctor` exits cleanly after a passing preflight.
|
|
233
233
|
child?.stderr?.destroy();
|
|
@@ -271,7 +271,7 @@ function attemptMarionetteConnect(port, connectFn) {
|
|
|
271
271
|
socket.destroy();
|
|
272
272
|
}
|
|
273
273
|
catch {
|
|
274
|
-
// Ignore
|
|
274
|
+
// Ignore: already closed.
|
|
275
275
|
}
|
|
276
276
|
resolve({ ok });
|
|
277
277
|
};
|
|
@@ -280,7 +280,7 @@ function attemptMarionetteConnect(port, connectFn) {
|
|
|
280
280
|
}, SOCKET_ATTEMPT_TIMEOUT_MS);
|
|
281
281
|
attemptTimer.unref();
|
|
282
282
|
socket.once('connect', () => {
|
|
283
|
-
// Connect alone is insufficient
|
|
283
|
+
// Connect alone is insufficient. The marionette server performs a
|
|
284
284
|
// handshake send as soon as the socket opens, so wait for at least one
|
|
285
285
|
// byte to confirm the server is actually speaking marionette.
|
|
286
286
|
const readTimer = setTimeout(() => {
|
|
@@ -311,7 +311,7 @@ export function reportMarionettePreflight(result) {
|
|
|
311
311
|
}
|
|
312
312
|
/**
|
|
313
313
|
* Formats the PASS/FAIL banner as a plain string for direct
|
|
314
|
-
* `process.stdout.write` use
|
|
314
|
+
* `process.stdout.write` use, bypassing the clack logger entirely so
|
|
315
315
|
* operators running `fireforge test --doctor` under a non-TTY (pipe, CI,
|
|
316
316
|
* `tee`-wrapped capture) always see the final line. Clack's renderer can
|
|
317
317
|
* swallow trailing log output just before process exit, and a
|