@hominis/fireforge 0.45.0 → 0.46.1
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 +409 -446
- package/dist/bin/fireforge.d.ts +1 -1
- package/dist/bin/fireforge.js +21 -15
- package/dist/build-info.json +4 -4
- package/dist/src/cli-usage-error.d.ts +46 -0
- package/dist/src/cli-usage-error.js +81 -0
- package/dist/src/cli.d.ts +7 -2
- package/dist/src/cli.js +47 -47
- package/dist/src/commands/bootstrap-checks.js +2 -1
- package/dist/src/commands/bootstrap.js +3 -4
- package/dist/src/commands/build.js +27 -17
- package/dist/src/commands/config.js +9 -9
- package/dist/src/commands/destructive-decision.d.ts +19 -0
- package/dist/src/commands/destructive-decision.js +31 -0
- package/dist/src/commands/discard.js +5 -5
- package/dist/src/commands/doctor-check-core.d.ts +4 -10
- package/dist/src/commands/doctor-check-core.js +0 -8
- 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 -17
- package/dist/src/commands/doctor-orphaned-harness.js +14 -23
- 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 +3 -3
- 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 +3 -1
- package/dist/src/commands/doctor.js +15 -16
- package/dist/src/commands/download.js +50 -37
- package/dist/src/commands/export-all.js +29 -12
- package/dist/src/commands/export-flow.d.ts +5 -5
- package/dist/src/commands/export-flow.js +29 -59
- package/dist/src/commands/export-placement-conflicts.d.ts +3 -3
- package/dist/src/commands/export-placement-conflicts.js +12 -12
- package/dist/src/commands/export-placement-gate.d.ts +2 -2
- package/dist/src/commands/export-placement-gate.js +7 -13
- package/dist/src/commands/export-placement-policy.d.ts +1 -1
- package/dist/src/commands/export-placement-policy.js +4 -6
- package/dist/src/commands/export-shared.d.ts +51 -32
- package/dist/src/commands/export-shared.js +17 -32
- package/dist/src/commands/export.js +14 -5
- package/dist/src/commands/furnace/apply.js +16 -16
- package/dist/src/commands/furnace/authoring-config.d.ts +13 -0
- package/dist/src/commands/furnace/authoring-config.js +19 -0
- package/dist/src/commands/furnace/chrome-doc-remove.d.ts +1 -1
- package/dist/src/commands/furnace/chrome-doc-remove.js +2 -2
- 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 +7 -12
- package/dist/src/commands/furnace/create-dry-run.d.ts +4 -4
- package/dist/src/commands/furnace/create-dry-run.js +6 -9
- 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 +31 -15
- package/dist/src/commands/furnace/create-templates.js +20 -19
- 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 +35 -29
- package/dist/src/commands/furnace/deploy.js +15 -6
- 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 +17 -16
- 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 +43 -34
- package/dist/src/commands/furnace/preview.js +17 -17
- package/dist/src/commands/furnace/refresh.js +15 -7
- package/dist/src/commands/furnace/remove-mutations.d.ts +9 -10
- package/dist/src/commands/furnace/remove-mutations.js +19 -19
- 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 +4 -8
- package/dist/src/commands/furnace/rename-browser-test.js +10 -15
- 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 +36 -36
- package/dist/src/commands/furnace/scan.js +3 -3
- package/dist/src/commands/furnace/status.js +19 -16
- package/dist/src/commands/furnace/sync.js +6 -6
- package/dist/src/commands/furnace/test-file-name.d.ts +28 -0
- package/dist/src/commands/furnace/test-file-name.js +39 -0
- package/dist/src/commands/furnace/validate.js +11 -12
- package/dist/src/commands/furnace/validation-output.d.ts +21 -9
- package/dist/src/commands/furnace/validation-output.js +3 -8
- package/dist/src/commands/import.js +22 -29
- package/dist/src/commands/lint-per-patch.d.ts +2 -2
- package/dist/src/commands/lint-per-patch.js +27 -12
- package/dist/src/commands/lint-per-run-checkjs.d.ts +14 -15
- 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 +5 -4
- package/dist/src/commands/lint.js +36 -36
- package/dist/src/commands/manifest.d.ts +4 -4
- package/dist/src/commands/manifest.js +1 -1
- package/dist/src/commands/package.js +4 -6
- package/dist/src/commands/patch/compact.d.ts +2 -2
- package/dist/src/commands/patch/compact.js +19 -20
- package/dist/src/commands/patch/delete.d.ts +1 -1
- package/dist/src/commands/patch/delete.js +23 -33
- package/dist/src/commands/patch/entry-projection.d.ts +13 -0
- package/dist/src/commands/patch/entry-projection.js +24 -0
- package/dist/src/commands/patch/lint-ignore.d.ts +3 -12
- package/dist/src/commands/patch/lint-ignore.js +33 -44
- package/dist/src/commands/patch/move-files-create.d.ts +2 -2
- package/dist/src/commands/patch/move-files-create.js +29 -15
- package/dist/src/commands/patch/move-files-into.d.ts +2 -2
- package/dist/src/commands/patch/move-files-into.js +41 -37
- package/dist/src/commands/patch/move-files.js +5 -14
- 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 +35 -49
- package/dist/src/commands/patch/reorder.js +35 -48
- package/dist/src/commands/patch/split-plan.d.ts +7 -8
- package/dist/src/commands/patch/split-plan.js +10 -13
- package/dist/src/commands/patch/split.d.ts +2 -2
- package/dist/src/commands/patch/split.js +50 -48
- 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 +22 -28
- package/dist/src/commands/patch/tier.d.ts +2 -2
- package/dist/src/commands/patch/tier.js +20 -30
- package/dist/src/commands/patch-rename-map.d.ts +19 -0
- package/dist/src/commands/patch-rename-map.js +36 -0
- package/dist/src/commands/pending-resolution.d.ts +15 -0
- package/dist/src/commands/pending-resolution.js +25 -0
- package/dist/src/commands/re-export-adjacent.d.ts +25 -3
- package/dist/src/commands/re-export-adjacent.js +40 -24
- package/dist/src/commands/re-export-bulk-scan.d.ts +3 -3
- package/dist/src/commands/re-export-bulk-scan.js +23 -27
- package/dist/src/commands/re-export-drift.d.ts +10 -10
- package/dist/src/commands/re-export-drift.js +33 -33
- package/dist/src/commands/re-export-files.d.ts +2 -3
- package/dist/src/commands/re-export-files.js +52 -44
- package/dist/src/commands/re-export-lint.d.ts +29 -30
- package/dist/src/commands/re-export-lint.js +36 -29
- 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 +12 -9
- package/dist/src/commands/re-export-single.d.ts +23 -4
- package/dist/src/commands/re-export-single.js +39 -31
- package/dist/src/commands/re-export.js +35 -17
- package/dist/src/commands/rebase/abort.js +9 -14
- package/dist/src/commands/rebase/continue.js +20 -19
- package/dist/src/commands/rebase/index.d.ts +1 -1
- package/dist/src/commands/rebase/index.js +5 -5
- package/dist/src/commands/rebase/patch-loop.d.ts +2 -2
- package/dist/src/commands/rebase/patch-loop.js +20 -24
- 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 +21 -13
- package/dist/src/commands/run.d.ts +0 -13
- package/dist/src/commands/run.js +38 -51
- package/dist/src/commands/setup-support.d.ts +16 -4
- package/dist/src/commands/setup-support.js +20 -20
- package/dist/src/commands/setup.js +4 -10
- package/dist/src/commands/source.js +9 -2
- package/dist/src/commands/status-check.d.ts +3 -3
- package/dist/src/commands/status-check.js +6 -6
- 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 +5 -5
- 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 +25 -26
- package/dist/src/commands/test-build-phase.d.ts +3 -3
- package/dist/src/commands/test-build-phase.js +48 -24
- 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 +4 -4
- package/dist/src/commands/test-modes.js +4 -5
- package/dist/src/commands/test-register.js +5 -3
- package/dist/src/commands/test-run.d.ts +11 -11
- package/dist/src/commands/test-run.js +40 -33
- package/dist/src/commands/test-stale-gate.d.ts +12 -12
- package/dist/src/commands/test-stale-gate.js +17 -17
- package/dist/src/commands/test-verdict.d.ts +19 -5
- package/dist/src/commands/test-verdict.js +26 -11
- package/dist/src/commands/test.d.ts +3 -3
- package/dist/src/commands/test.js +73 -36
- package/dist/src/commands/token-coverage.js +3 -3
- package/dist/src/commands/token-list.d.ts +26 -0
- package/dist/src/commands/token-list.js +153 -0
- package/dist/src/commands/token.js +26 -10
- package/dist/src/commands/tree.js +26 -21
- package/dist/src/commands/typecheck.d.ts +6 -6
- package/dist/src/commands/typecheck.js +16 -16
- 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 +17 -16
- 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 -12
- package/dist/src/core/branding.js +6 -5
- package/dist/src/core/browser-wire.d.ts +1 -1
- package/dist/src/core/browser-wire.js +10 -7
- package/dist/src/core/build-audit-platform.d.ts +32 -3
- package/dist/src/core/build-audit-platform.js +153 -13
- package/dist/src/core/build-audit-registration.d.ts +5 -5
- package/dist/src/core/build-audit-registration.js +10 -9
- 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 +57 -0
- package/dist/src/core/build-audit-skip.js +112 -0
- 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 +21 -8
- package/dist/src/core/build-audit.js +142 -40
- 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 +48 -31
- package/dist/src/core/build-baseline.js +20 -43
- package/dist/src/core/build-jar-escalation.d.ts +8 -8
- package/dist/src/core/build-jar-escalation.js +18 -17
- package/dist/src/core/build-overwrite-guard.d.ts +4 -4
- package/dist/src/core/build-overwrite-guard.js +14 -14
- package/dist/src/core/build-prepare.d.ts +4 -12
- package/dist/src/core/build-prepare.js +22 -26
- package/dist/src/core/config-mutate.js +4 -4
- package/dist/src/core/config-paths.d.ts +2 -6
- package/dist/src/core/config-paths.js +4 -2
- package/dist/src/core/config-state.d.ts +0 -6
- package/dist/src/core/config-state.js +3 -21
- package/dist/src/core/config-validate-build-audit.d.ts +8 -0
- package/dist/src/core/config-validate-build-audit.js +80 -0
- package/dist/src/core/config-validate-file-size.d.ts +1 -1
- package/dist/src/core/config-validate-file-size.js +3 -3
- package/dist/src/core/config-validate-patch-policy.d.ts +2 -2
- package/dist/src/core/config-validate-patch-policy.js +3 -3
- package/dist/src/core/config-validate-test-toolchains.d.ts +2 -2
- package/dist/src/core/config-validate-test-toolchains.js +4 -5
- package/dist/src/core/config-validate.js +22 -12
- package/dist/src/core/config.d.ts +12 -12
- package/dist/src/core/config.js +21 -25
- package/dist/src/core/coverage-extend.d.ts +16 -16
- package/dist/src/core/coverage-extend.js +20 -20
- 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 +22 -23
- 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 +5 -13
- package/dist/src/core/engine-precondition.js +5 -10
- package/dist/src/core/engine-session-lock.d.ts +18 -18
- package/dist/src/core/engine-session-lock.js +50 -54
- package/dist/src/core/export-moved-code-shape.d.ts +7 -7
- package/dist/src/core/export-moved-code-shape.js +10 -10
- package/dist/src/core/file-lock-owner.d.ts +103 -0
- package/dist/src/core/file-lock-owner.js +259 -0
- package/dist/src/core/file-lock.d.ts +14 -19
- package/dist/src/core/file-lock.js +90 -128
- package/dist/src/core/firefox-cache.d.ts +13 -1
- package/dist/src/core/firefox-cache.js +61 -36
- package/dist/src/core/firefox-download.d.ts +15 -0
- package/dist/src/core/firefox-download.js +38 -22
- package/dist/src/core/firefox-extract.d.ts +8 -7
- package/dist/src/core/firefox-extract.js +45 -27
- package/dist/src/core/firefox.d.ts +34 -36
- package/dist/src/core/firefox.js +13 -44
- package/dist/src/core/furnace-apply-dry-run.d.ts +1 -6
- package/dist/src/core/furnace-apply-dry-run.js +2 -8
- 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 -20
- package/dist/src/core/furnace-apply-helpers.js +28 -39
- 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 +13 -11
- 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 +4 -4
- package/dist/src/core/furnace-apply.js +50 -29
- 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 +5 -5
- package/dist/src/core/furnace-config.js +40 -53
- package/dist/src/core/furnace-constants.d.ts +6 -6
- package/dist/src/core/furnace-constants.js +9 -8
- 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 +20 -0
- package/dist/src/core/furnace-dir-entry.js +21 -0
- 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 +22 -19
- package/dist/src/core/furnace-operation.js +38 -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.d.ts +18 -6
- package/dist/src/core/furnace-refresh.js +5 -8
- package/dist/src/core/furnace-registration-ast.d.ts +2 -3
- package/dist/src/core/furnace-registration-ast.js +9 -12
- 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 +7 -6
- package/dist/src/core/furnace-registration.js +29 -36
- package/dist/src/core/furnace-rollback.d.ts +1 -1
- package/dist/src/core/furnace-rollback.js +5 -5
- package/dist/src/core/furnace-scanner.js +3 -6
- 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 +12 -12
- 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 +18 -20
- 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 +6 -4
- package/dist/src/core/git-base.js +29 -7
- package/dist/src/core/git-diff-new-file.d.ts +40 -0
- package/dist/src/core/git-diff-new-file.js +119 -0
- package/dist/src/core/git-diff.d.ts +13 -13
- package/dist/src/core/git-diff.js +121 -189
- package/dist/src/core/git-file-ops.d.ts +6 -13
- package/dist/src/core/git-file-ops.js +11 -35
- package/dist/src/core/git-readonly-index.d.ts +12 -14
- package/dist/src/core/git-readonly-index.js +12 -16
- package/dist/src/core/git-status.d.ts +9 -2
- package/dist/src/core/git-status.js +23 -11
- package/dist/src/core/git.d.ts +3 -9
- package/dist/src/core/git.js +28 -57
- package/dist/src/core/harness-orphans.d.ts +17 -17
- package/dist/src/core/harness-orphans.js +28 -27
- package/dist/src/core/history-log.d.ts +19 -0
- package/dist/src/core/history-log.js +29 -0
- 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 -10
- package/dist/src/core/mach-error-hints.js +14 -14
- package/dist/src/core/mach-known-noise-filter.d.ts +42 -38
- package/dist/src/core/mach-known-noise-filter.js +57 -56
- package/dist/src/core/mach-mozconfig.d.ts +6 -6
- package/dist/src/core/mach-mozconfig.js +17 -16
- package/dist/src/core/mach-python.d.ts +3 -0
- package/dist/src/core/mach-python.js +13 -7
- package/dist/src/core/mach-resource-shim.d.ts +24 -12
- package/dist/src/core/mach-resource-shim.js +124 -21
- package/dist/src/core/mach.d.ts +59 -73
- package/dist/src/core/mach.js +47 -115
- package/dist/src/core/marionette-port.d.ts +15 -30
- package/dist/src/core/marionette-port.js +46 -89
- package/dist/src/core/marionette-preflight.d.ts +6 -6
- package/dist/src/core/marionette-preflight.js +32 -50
- 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 +17 -17
- 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 +46 -42
- 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 +13 -13
- package/dist/src/core/patch-apply.d.ts +13 -14
- package/dist/src/core/patch-apply.js +36 -42
- package/dist/src/core/patch-export-coverage.d.ts +0 -9
- package/dist/src/core/patch-export-coverage.js +1 -30
- package/dist/src/core/patch-export-update.d.ts +21 -4
- package/dist/src/core/patch-export-update.js +7 -6
- package/dist/src/core/patch-export.d.ts +20 -30
- package/dist/src/core/patch-export.js +55 -77
- package/dist/src/core/patch-files.d.ts +0 -4
- package/dist/src/core/patch-files.js +0 -11
- 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 +12 -18
- package/dist/src/core/patch-lint-cache.d.ts +18 -2
- package/dist/src/core/patch-lint-cache.js +16 -19
- package/dist/src/core/patch-lint-checkjs.d.ts +55 -38
- package/dist/src/core/patch-lint-checkjs.js +78 -64
- 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 +5 -9
- package/dist/src/core/patch-lint-creators.js +3 -3
- package/dist/src/core/patch-lint-cross.d.ts +27 -19
- package/dist/src/core/patch-lint-cross.js +67 -110
- package/dist/src/core/patch-lint-css.d.ts +1 -1
- package/dist/src/core/patch-lint-css.js +15 -11
- 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 +6 -6
- package/dist/src/core/patch-lint-forward-registration.d.ts +58 -0
- package/dist/src/core/patch-lint-forward-registration.js +210 -0
- package/dist/src/core/patch-lint-jsdoc.d.ts +2 -2
- package/dist/src/core/patch-lint-jsdoc.js +46 -46
- package/dist/src/core/patch-lint-module-registration.d.ts +3 -9
- 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 +7 -7
- package/dist/src/core/patch-lint-queue-types.d.ts +60 -0
- package/dist/src/core/patch-lint-queue-types.js +12 -0
- package/dist/src/core/patch-lint-staged-registration.d.ts +61 -0
- package/dist/src/core/patch-lint-staged-registration.js +90 -0
- 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 +41 -35
- package/dist/src/core/patch-lint.js +52 -49
- package/dist/src/core/patch-lock.d.ts +1 -1
- package/dist/src/core/patch-lock.js +11 -11
- 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 +35 -34
- 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 +32 -21
- package/dist/src/core/patch-parse.js +40 -15
- package/dist/src/core/patch-policy.js +15 -27
- 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-source-metadata.d.ts +1 -3
- package/dist/src/core/patch-source-metadata.js +0 -4
- package/dist/src/core/patch-transform.d.ts +8 -16
- package/dist/src/core/patch-transform.js +13 -23
- package/dist/src/core/process-cpu-time.d.ts +1 -1
- package/dist/src/core/process-cpu-time.js +6 -6
- package/dist/src/core/rebase-session.d.ts +9 -15
- package/dist/src/core/rebase-session.js +13 -25
- package/dist/src/core/register-browser-content.js +3 -2
- package/dist/src/core/register-browser-test.js +2 -1
- package/dist/src/core/register-module.js +2 -1
- 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 +8 -7
- package/dist/src/core/register-shared-css.d.ts +3 -3
- package/dist/src/core/register-shared-css.js +6 -5
- 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 +38 -0
- package/dist/src/core/run-log-redact.js +69 -0
- package/dist/src/core/run-log.d.ts +21 -10
- package/dist/src/core/run-log.js +76 -27
- 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 +4 -6
- package/dist/src/core/smoke-patterns.d.ts +5 -6
- package/dist/src/core/smoke-patterns.js +15 -20
- package/dist/src/core/state-file.d.ts +15 -4
- package/dist/src/core/state-file.js +14 -1
- 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 +13 -12
- package/dist/src/core/test-changed-prefs.d.ts +12 -12
- package/dist/src/core/test-changed-prefs.js +40 -25
- package/dist/src/core/test-harness-crash.d.ts +39 -39
- package/dist/src/core/test-harness-crash.js +69 -69
- 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 -23
- package/dist/src/core/test-stale-check.js +31 -30
- 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/test-xpcshell-retry.d.ts +26 -7
- package/dist/src/core/test-xpcshell-retry.js +14 -11
- package/dist/src/core/token-category.d.ts +35 -2
- package/dist/src/core/token-category.js +67 -58
- package/dist/src/core/token-coverage.js +4 -5
- package/dist/src/core/token-dark-mode.d.ts +9 -9
- package/dist/src/core/token-dark-mode.js +13 -25
- package/dist/src/core/token-docs.d.ts +1 -1
- package/dist/src/core/token-inventory.d.ts +56 -0
- package/dist/src/core/token-inventory.js +109 -0
- package/dist/src/core/token-manager.d.ts +4 -4
- package/dist/src/core/token-manager.js +22 -22
- 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 +52 -53
- package/dist/src/core/toolchain-preflight.d.ts +15 -15
- package/dist/src/core/toolchain-preflight.js +23 -23
- package/dist/src/core/tree-cow.d.ts +3 -5
- package/dist/src/core/tree-cow.js +8 -8
- 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 +39 -38
- 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 +33 -33
- 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 +12 -23
- 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 +16 -28
- package/dist/src/core/xpcshell-appdir.d.ts +20 -20
- package/dist/src/core/xpcshell-appdir.js +28 -30
- 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 +69 -16
- package/dist/src/errors/base.js +95 -26
- package/dist/src/errors/build.d.ts +6 -6
- package/dist/src/errors/build.js +26 -34
- package/dist/src/errors/codes.d.ts +10 -10
- package/dist/src/errors/codes.js +10 -10
- package/dist/src/errors/config.d.ts +0 -14
- package/dist/src/errors/config.js +13 -34
- package/dist/src/errors/download.d.ts +13 -0
- package/dist/src/errors/download.js +53 -24
- package/dist/src/errors/furnace.d.ts +2 -2
- package/dist/src/errors/furnace.js +8 -9
- package/dist/src/errors/git.d.ts +9 -9
- package/dist/src/errors/git.js +21 -31
- package/dist/src/errors/patch.d.ts +3 -3
- package/dist/src/errors/patch.js +11 -13
- package/dist/src/errors/rebase.d.ts +1 -1
- package/dist/src/errors/rebase.js +8 -8
- 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 +155 -200
- 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 +52 -19
- package/dist/src/types/furnace.d.ts +17 -17
- package/dist/src/types/index.d.ts +0 -1
- 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 +4 -16
- package/dist/src/utils/assert.js +7 -24
- package/dist/src/utils/build-info.d.ts +6 -6
- package/dist/src/utils/build-info.js +6 -6
- package/dist/src/utils/child-env.d.ts +7 -6
- 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 +10 -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 +15 -20
- package/dist/src/utils/hash.d.ts +12 -0
- package/dist/src/utils/hash.js +16 -0
- package/dist/src/utils/line-dispatch.d.ts +15 -0
- package/dist/src/utils/line-dispatch.js +48 -0
- 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 +14 -20
- package/dist/src/utils/options.js +26 -27
- package/dist/src/utils/package-root.js +5 -14
- package/dist/src/utils/paths.d.ts +4 -4
- package/dist/src/utils/paths.js +4 -4
- package/dist/src/utils/platform.d.ts +0 -4
- package/dist/src/utils/process-group.d.ts +10 -9
- package/dist/src/utils/process-group.js +37 -36
- package/dist/src/utils/process.d.ts +70 -55
- package/dist/src/utils/process.js +129 -179
- package/dist/src/utils/ps-duration.d.ts +4 -4
- package/dist/src/utils/ps-duration.js +9 -9
- package/dist/src/utils/regex.d.ts +4 -4
- package/dist/src/utils/regex.js +7 -7
- package/dist/src/utils/sleep.d.ts +26 -0
- package/dist/src/utils/sleep.js +31 -0
- 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 +12 -49
- package/dist/src/utils/validation.js +26 -36
- package/docs/README.md +2 -2
- package/docs/configuration.md +163 -69
- package/docs/exit-codes.md +66 -49
- package/docs/furnace.md +20 -19
- package/docs/lifecycle-invariants.md +414 -247
- package/docs/machine-output.md +58 -34
- package/docs/patch-workflow.md +48 -44
- package/docs/run-logs.md +72 -28
- package/docs/testing.md +105 -98
- package/docs/verification-trees.md +23 -22
- package/package.json +7 -6
- package/dist/src/commands/rebase.d.ts +0 -4
- package/dist/src/commands/rebase.js +0 -5
- package/dist/src/core/patch-artifact-normalize.d.ts +0 -21
- package/dist/src/core/patch-artifact-normalize.js +0 -24
- package/dist/src/core/patch-lint-reexports.d.ts +0 -7
- package/dist/src/core/patch-lint-reexports.js +0 -8
- package/dist/src/core/wire-targets.d.ts +0 -7
- package/dist/src/core/wire-targets.js +0 -8
|
@@ -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,9 +22,10 @@
|
|
|
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
|
-
import {
|
|
28
|
+
import { PreflightRefusalError } from '../errors/base.js';
|
|
28
29
|
import { toError } from '../utils/errors.js';
|
|
29
30
|
import { getPlatform } from '../utils/platform.js';
|
|
30
31
|
import { exec } from '../utils/process.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.
|
|
@@ -133,19 +134,19 @@ export async function ensureLaunchableBrowserNotRunning(launchableBinary, option
|
|
|
133
134
|
return;
|
|
134
135
|
}
|
|
135
136
|
catch (error) {
|
|
136
|
-
throw new
|
|
137
|
+
throw new PreflightRefusalError(`A browser from this objdir is still running (PID ${holder.pid}), but FireForge could not terminate it: ${toError(error).message}`, 'stale-browser-kill-failed');
|
|
137
138
|
}
|
|
138
139
|
}
|
|
139
|
-
throw new
|
|
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
|
*
|
|
@@ -349,18 +350,18 @@ export async function assertMarionettePortAvailable(port = DEFAULT_MARIONETTE_PO
|
|
|
349
350
|
const killHint = process.platform === 'win32'
|
|
350
351
|
? `Stop-Process -Id ${holder.pid} -Force`
|
|
351
352
|
: `kill ${holder.pid} # or "kill -9 ${holder.pid}" if it doesn't exit`;
|
|
352
|
-
throw new
|
|
353
|
+
throw new PreflightRefusalError(`Marionette port ${port} is already in use by ${holder.command} (PID ${holder.pid}). ` +
|
|
353
354
|
`This is usually a browser left running by a previously interrupted "fireforge test" run. ` +
|
|
354
355
|
`Kill it with "${killHint}", then retry. ` +
|
|
355
356
|
`(If you expected ${holder.command} to be running on ${port}, stop it manually or pass ` +
|
|
356
|
-
`"--marionette-port <port>" to launch mach test on a different port.)
|
|
357
|
+
`"--marionette-port <port>" to launch mach test on a different port.)`, 'marionette-port-busy');
|
|
357
358
|
}
|
|
358
359
|
// Non-browser holder: mach test will still fail to bind, but the
|
|
359
360
|
// cause is not a stale FireForge-launched browser. Flag it
|
|
360
361
|
// explicitly so the operator can decide what to do instead of
|
|
361
362
|
// getting mach's bind error with no FireForge context.
|
|
362
|
-
throw new
|
|
363
|
-
`This is not a FireForge-launched browser; stop the holder process or free the port before rerunning
|
|
363
|
+
throw new PreflightRefusalError(`Marionette port ${port} is already in use by ${holder.command} (PID ${holder.pid}). ` +
|
|
364
|
+
`This is not a FireForge-launched browser; stop the holder process or free the port before rerunning.`, 'marionette-port-busy');
|
|
364
365
|
}
|
|
365
366
|
/**
|
|
366
367
|
* Ensures the Marionette port is usable, optionally terminating a stale
|
|
@@ -390,8 +391,8 @@ export async function ensureMarionettePortAvailable(port = DEFAULT_MARIONETTE_PO
|
|
|
390
391
|
}
|
|
391
392
|
}
|
|
392
393
|
catch (error) {
|
|
393
|
-
throw new
|
|
394
|
-
`but FireForge could not terminate it: ${toError(error).message}
|
|
394
|
+
throw new PreflightRefusalError(`Marionette port ${port} is held by stale browser ${holder.command} (PID ${holder.pid}), ` +
|
|
395
|
+
`but FireForge could not terminate it: ${toError(error).message}`, 'stale-browser-kill-failed');
|
|
395
396
|
}
|
|
396
397
|
}
|
|
397
398
|
/**
|
|
@@ -405,15 +406,13 @@ 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
|
-
for (
|
|
414
|
-
const arg = machArgs[i];
|
|
415
|
-
if (arg === undefined)
|
|
416
|
-
continue;
|
|
415
|
+
for (const [i, arg] of machArgs.entries()) {
|
|
417
416
|
// `--marionette-port=NNNN`
|
|
418
417
|
let match = /^--marionette-port=(\d+)$/.exec(arg);
|
|
419
418
|
if (match?.[1]) {
|
|
@@ -430,7 +429,7 @@ export function extractForwardedMarionettePort(machArgs) {
|
|
|
430
429
|
return n;
|
|
431
430
|
}
|
|
432
431
|
}
|
|
433
|
-
// `--setpref=marionette.port=NNNN
|
|
432
|
+
// `--setpref=marionette.port=NNNN`, the auto-forward shape. Recognised
|
|
434
433
|
// here so a duplicate check at the call site can spot operator-supplied
|
|
435
434
|
// setprefs without re-implementing the parse.
|
|
436
435
|
match = /^--setpref=marionette\.port=(\d+)$/.exec(arg);
|
|
@@ -446,16 +445,14 @@ export function extractForwardedMarionettePort(machArgs) {
|
|
|
446
445
|
* True when forwarded mach args already set a Marionette **client** address
|
|
447
446
|
* for mach/mochitest (`--marionette=host:port` or `--marionette host:port`).
|
|
448
447
|
* Used only to avoid duplicating FireForge's auto-injected
|
|
449
|
-
* `--marionette=127.0.0.1:<n
|
|
448
|
+
* `--marionette=127.0.0.1:<n>`. This is not a full URL validator (IPv6,
|
|
449
|
+
* etc.).
|
|
450
450
|
*
|
|
451
|
-
*
|
|
451
|
+
* Does not treat `--marionette-port` as a client endpoint.
|
|
452
452
|
*/
|
|
453
453
|
export function forwardedMachArgsIncludeMarionetteClient(machArgs) {
|
|
454
454
|
const valueLooksLikeHostPort = (token) => /:[0-9]+$/.test(token) || /^\[[^]]+\]:[0-9]+$/.test(token);
|
|
455
|
-
for (
|
|
456
|
-
const arg = machArgs[i];
|
|
457
|
-
if (arg === undefined)
|
|
458
|
-
continue;
|
|
455
|
+
for (const [i, arg] of machArgs.entries()) {
|
|
459
456
|
if (arg.startsWith('--marionette=') && !arg.startsWith('--marionette-port=')) {
|
|
460
457
|
return true;
|
|
461
458
|
}
|
|
@@ -473,8 +470,7 @@ export function forwardedMachArgsIncludeMarionetteClient(machArgs) {
|
|
|
473
470
|
* for runs where the pref is ignored anyway.
|
|
474
471
|
*/
|
|
475
472
|
export function hasExplicitXpcshellFlavor(machArgs) {
|
|
476
|
-
for (
|
|
477
|
-
const arg = machArgs[i] ?? '';
|
|
473
|
+
for (const [i, arg] of machArgs.entries()) {
|
|
478
474
|
if (/^--flavor=xpcshell\b/.test(arg) || arg === '--flavor=xpcshell-tests')
|
|
479
475
|
return true;
|
|
480
476
|
if (arg === '--flavor' && /^xpcshell(?:-tests)?$/.test(machArgs[i + 1] ?? ''))
|
|
@@ -493,42 +489,3 @@ export function hasExplicitXpcshellFlavor(machArgs) {
|
|
|
493
489
|
export function shouldAutoForwardMarionettePortToMach(machArgs) {
|
|
494
490
|
return !hasExplicitXpcshellFlavor(machArgs);
|
|
495
491
|
}
|
|
496
|
-
/**
|
|
497
|
-
* Heuristic: do the test paths or forwarded mach args indicate a flavour
|
|
498
|
-
* that actually launches a Marionette-driven browser? Browser-chrome and
|
|
499
|
-
* mochitest do; xpcshell does not. A no-paths invocation (the default "run
|
|
500
|
-
* all tests" shape) is treated as marionette-relevant since it includes
|
|
501
|
-
* browser-chrome.
|
|
502
|
-
*
|
|
503
|
-
* Note: `fireforge test` auto-forward of `--marionette-port` to mach uses
|
|
504
|
-
* {@link shouldAutoForwardMarionettePortToMach} (mach-arg flavor gate) rather
|
|
505
|
-
* than this function alone, so toolkit paths without `/mochitest/` still get
|
|
506
|
-
* the listener pref and harness `--marionette=127.0.0.1:<n>` when appropriate.
|
|
507
|
-
*
|
|
508
|
-
* @param testPaths - Engine-relative paths after `stripEnginePrefix`.
|
|
509
|
-
* @param machArgs - Forwarded mach args (post-`--mach-arg`).
|
|
510
|
-
* @returns `true` when the run is likely to bind a Marionette listener.
|
|
511
|
-
*/
|
|
512
|
-
export function isMarionetteFlavor(testPaths, machArgs) {
|
|
513
|
-
if (hasExplicitXpcshellFlavor(machArgs))
|
|
514
|
-
return false;
|
|
515
|
-
for (const arg of machArgs) {
|
|
516
|
-
if (/^--flavor=(browser-chrome|mochitest|chrome|a11y)\b/.test(arg))
|
|
517
|
-
return true;
|
|
518
|
-
}
|
|
519
|
-
if (testPaths.length === 0)
|
|
520
|
-
return true;
|
|
521
|
-
for (const path of testPaths) {
|
|
522
|
-
const base = path.split('/').pop() ?? path;
|
|
523
|
-
if (/^browser_.+\.(js|ini|toml)$/.test(base))
|
|
524
|
-
return true;
|
|
525
|
-
if (path.includes('/mochitest/') || path.startsWith('mochitest/'))
|
|
526
|
-
return true;
|
|
527
|
-
if (path.includes('/browser-chrome/') || path.startsWith('browser-chrome/'))
|
|
528
|
-
return true;
|
|
529
|
-
if (path.includes('toolkit/content/tests/') && !path.includes('/tests/xpcshell/')) {
|
|
530
|
-
return true;
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
return false;
|
|
534
|
-
}
|
|
@@ -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 →
|
|
@@ -22,6 +22,7 @@ import { pathExists } from '../utils/fs.js';
|
|
|
22
22
|
import { info, verbose, warn } from '../utils/logger.js';
|
|
23
23
|
import { installGracefulShutdownForwarder, trackChildClosure } from '../utils/process.js';
|
|
24
24
|
import { killProcessTree, sweepProcessGroup } from '../utils/process-group.js';
|
|
25
|
+
import { sleep } from '../utils/sleep.js';
|
|
25
26
|
import { ensureMach } from './mach.js';
|
|
26
27
|
import { getPython } from './mach-python.js';
|
|
27
28
|
/** Marionette's default TCP port when the browser is launched with `--marionette`. */
|
|
@@ -33,7 +34,7 @@ const SOCKET_ATTEMPT_TIMEOUT_MS = 2_000;
|
|
|
33
34
|
/**
|
|
34
35
|
* Grace window after spawn() returns before we accept the child as
|
|
35
36
|
* "spawned OK". A browser binary that exits immediately (missing dylib,
|
|
36
|
-
* wrong CPU arch, corrupt profile) must be caught here
|
|
37
|
+
* wrong CPU arch, corrupt profile) must be caught here, not 30 seconds
|
|
37
38
|
* later at the socket layer.
|
|
38
39
|
*/
|
|
39
40
|
const SPAWN_SETTLE_MS = 750;
|
|
@@ -57,9 +58,9 @@ function layerTag(name) {
|
|
|
57
58
|
}
|
|
58
59
|
/**
|
|
59
60
|
* Runs the marionette preflight. Returns PASS on first byte read from the
|
|
60
|
-
* marionette socket within the budget
|
|
61
|
-
* identifying which layer of the cascade broke. Always tears
|
|
62
|
-
* 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.
|
|
63
64
|
*/
|
|
64
65
|
export async function runMarionettePreflight(engineDir, options = {}) {
|
|
65
66
|
const timeoutMs = options.timeoutMs ?? DEFAULT_PREFLIGHT_TIMEOUT_MS;
|
|
@@ -100,15 +101,15 @@ export async function runMarionettePreflight(engineDir, options = {}) {
|
|
|
100
101
|
let stderrTail = '';
|
|
101
102
|
// Shutdown contract for a child spawned outside the exec layer.
|
|
102
103
|
//
|
|
103
|
-
// This is the
|
|
104
|
-
//
|
|
104
|
+
// This is the one raw `spawn` in the repo. The preflight needs the live
|
|
105
|
+
// `ChildProcess` mid-run (`hasChildExited` gates the socket poll),
|
|
105
106
|
// returns while the browser is still running, and aborts on a TCP byte
|
|
106
|
-
// rather than on a deadline
|
|
107
|
-
//
|
|
108
|
-
//
|
|
109
|
-
//
|
|
110
|
-
//
|
|
111
|
-
//
|
|
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.
|
|
112
113
|
let closure;
|
|
113
114
|
let forwarder;
|
|
114
115
|
try {
|
|
@@ -129,7 +130,7 @@ export async function runMarionettePreflight(engineDir, options = {}) {
|
|
|
129
130
|
// `detached: true` puts the child in a new process group so we can
|
|
130
131
|
// signal it and every descendant (Firefox, its helpers) via
|
|
131
132
|
// `process.kill(-pid, …)` in the finally block. Without it, the
|
|
132
|
-
// child is Python running mach
|
|
133
|
+
// child is Python running mach. A SIGTERM kills Python but the
|
|
133
134
|
// Firefox grandchild inherits the stderr pipe FD and keeps Node's
|
|
134
135
|
// event loop alive even after the preflight PASS log, so
|
|
135
136
|
// `fireforge test --doctor` prints `Marionette preflight: PASS`
|
|
@@ -143,22 +144,22 @@ export async function runMarionettePreflight(engineDir, options = {}) {
|
|
|
143
144
|
const spawnedChild = child;
|
|
144
145
|
closure = trackChildClosure();
|
|
145
146
|
forwarder = installGracefulShutdownForwarder(spawnedChild, 500, (signal) => {
|
|
146
|
-
|
|
147
|
+
killProcessTree(spawnedChild, signal, process.platform !== 'win32');
|
|
147
148
|
});
|
|
148
149
|
child.stderr?.on('data', (data) => {
|
|
149
150
|
const chunk = data.toString();
|
|
150
151
|
stderrTail = (stderrTail + chunk).slice(-STDERR_TAIL_LIMIT);
|
|
151
152
|
});
|
|
152
|
-
// Short settle window
|
|
153
|
+
// Short settle window. Catches "binary exits immediately" failures
|
|
153
154
|
// (missing dylib, wrong CPU arch, corrupt profile) before the socket
|
|
154
155
|
// poll swallows the full overall budget waiting for bytes that will
|
|
155
156
|
// never come.
|
|
156
157
|
const settleDeadline = Math.min(spawnSettleMs, Math.max(0, timeoutMs - elapsed()));
|
|
157
158
|
if (settleDeadline > 0) {
|
|
158
|
-
await
|
|
159
|
+
await sleep(settleDeadline, { unref: true });
|
|
159
160
|
}
|
|
160
161
|
if (hasChildExited(spawnedChild)) {
|
|
161
|
-
return fail('browser-spawns', `Browser process exited during spawn (exit code ${
|
|
162
|
+
return fail('browser-spawns', `Browser process exited during spawn (exit code ${spawnedChild.exitCode}, signal ${spawnedChild.signalCode ?? 'none'}). ` +
|
|
162
163
|
`stderr tail: ${stderrTail.trim().slice(-2_000) || '(empty)'}`, elapsed());
|
|
163
164
|
}
|
|
164
165
|
// Layer 6: marionette handshake within the remaining budget.
|
|
@@ -172,10 +173,10 @@ export async function runMarionettePreflight(engineDir, options = {}) {
|
|
|
172
173
|
detail: `Marionette handshake received on 127.0.0.1:${port} in ${Date.now() - startedAt}ms.`,
|
|
173
174
|
};
|
|
174
175
|
}
|
|
175
|
-
// Child may have exited before the socket was ever ready
|
|
176
|
+
// Child may have exited before the socket was ever ready. Surface that
|
|
176
177
|
// distinctly from "socket never answered" so the operator has a lead.
|
|
177
178
|
if (hasChildExited(spawnedChild)) {
|
|
178
|
-
return fail('marionette-handshake', `Browser process exited before marionette handshake (exit code ${
|
|
179
|
+
return fail('marionette-handshake', `Browser process exited before marionette handshake (exit code ${spawnedChild.exitCode}, signal ${spawnedChild.signalCode ?? 'none'}). ` +
|
|
179
180
|
`stderr tail: ${stderrTail.trim().slice(-2_000) || '(empty)'}`, elapsed());
|
|
180
181
|
}
|
|
181
182
|
return fail('marionette-handshake', `Marionette socket on 127.0.0.1:${port} did not respond within ${timeoutMs}ms. ` +
|
|
@@ -203,17 +204,17 @@ async function teardownPreflightChild(child, forwarder, closure, profileDir) {
|
|
|
203
204
|
forwarder?.dispose();
|
|
204
205
|
const groupPid = child?.pid;
|
|
205
206
|
if (child && !hasChildExited(child)) {
|
|
206
|
-
|
|
207
|
+
killProcessTree(child, 'SIGTERM', process.platform !== 'win32');
|
|
207
208
|
// Small escalation: if the child doesn't honour SIGTERM quickly, SIGKILL
|
|
208
209
|
// so we don't leave a ghost mach process around after a failed probe.
|
|
209
|
-
await
|
|
210
|
+
await sleep(500, { unref: true });
|
|
210
211
|
if (!hasChildExited(child)) {
|
|
211
|
-
|
|
212
|
+
killProcessTree(child, 'SIGKILL', process.platform !== 'win32');
|
|
212
213
|
}
|
|
213
214
|
}
|
|
214
215
|
// Reap anything that outlived the group signal. The file's own comments
|
|
215
|
-
// worry about exactly this
|
|
216
|
-
// mach wrapper
|
|
216
|
+
// worry about exactly this case (Firefox grandchildren surviving the
|
|
217
|
+
// Python mach wrapper), and every exec-layer wrapper sweeps for it.
|
|
217
218
|
if (groupPid !== undefined && process.platform !== 'win32') {
|
|
218
219
|
try {
|
|
219
220
|
await sweepProcessGroup(groupPid);
|
|
@@ -225,8 +226,8 @@ async function teardownPreflightChild(child, forwarder, closure, profileDir) {
|
|
|
225
226
|
closure?.settle();
|
|
226
227
|
// Destroy the stderr pipe explicitly. Firefox (a grandchild of the Python
|
|
227
228
|
// mach wrapper we spawned) can inherit and hold the stderr FD even after
|
|
228
|
-
// its direct parent exits
|
|
229
|
-
//
|
|
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.
|
|
230
231
|
// `destroy()` closes the local end regardless, so `fireforge test
|
|
231
232
|
// --doctor` exits cleanly after a passing preflight.
|
|
232
233
|
child?.stderr?.destroy();
|
|
@@ -237,19 +238,6 @@ async function teardownPreflightChild(child, forwarder, closure, profileDir) {
|
|
|
237
238
|
warn(`Could not clean up marionette preflight profile: ${toError(error).message}`);
|
|
238
239
|
}
|
|
239
240
|
}
|
|
240
|
-
/**
|
|
241
|
-
* Sends `signal` to the child's whole process group when possible, falling
|
|
242
|
-
* back to a direct `child.kill` for environments that don't support
|
|
243
|
-
* `detached: true` (Windows in particular: Node still returns a pid, but
|
|
244
|
-
* `kill(-pid, …)` is not a supported kernel primitive).
|
|
245
|
-
*/
|
|
246
|
-
function killProcessGroup(child, signal) {
|
|
247
|
-
// Delegates to the shared implementation, which is a strict superset of
|
|
248
|
-
// the hand-rolled one this replaced: same POSIX `kill(-pid)` with the same
|
|
249
|
-
// fall-through to a direct `child.kill`, plus a Windows `taskkill /T /F`
|
|
250
|
-
// branch and an already-exited early return.
|
|
251
|
-
killProcessTree(child, signal, process.platform !== 'win32');
|
|
252
|
-
}
|
|
253
241
|
function fail(layer, message, durationMs) {
|
|
254
242
|
return {
|
|
255
243
|
ok: false,
|
|
@@ -267,7 +255,7 @@ async function waitForMarionetteSocket(port, connectFn, keepTrying) {
|
|
|
267
255
|
if (result.ok) {
|
|
268
256
|
return { ok: true };
|
|
269
257
|
}
|
|
270
|
-
await
|
|
258
|
+
await sleep(400, { unref: true });
|
|
271
259
|
}
|
|
272
260
|
return { ok: false };
|
|
273
261
|
}
|
|
@@ -283,7 +271,7 @@ function attemptMarionetteConnect(port, connectFn) {
|
|
|
283
271
|
socket.destroy();
|
|
284
272
|
}
|
|
285
273
|
catch {
|
|
286
|
-
// Ignore
|
|
274
|
+
// Ignore: already closed.
|
|
287
275
|
}
|
|
288
276
|
resolve({ ok });
|
|
289
277
|
};
|
|
@@ -292,7 +280,7 @@ function attemptMarionetteConnect(port, connectFn) {
|
|
|
292
280
|
}, SOCKET_ATTEMPT_TIMEOUT_MS);
|
|
293
281
|
attemptTimer.unref();
|
|
294
282
|
socket.once('connect', () => {
|
|
295
|
-
// Connect alone is insufficient
|
|
283
|
+
// Connect alone is insufficient. The marionette server performs a
|
|
296
284
|
// handshake send as soon as the socket opens, so wait for at least one
|
|
297
285
|
// byte to confirm the server is actually speaking marionette.
|
|
298
286
|
const readTimer = setTimeout(() => {
|
|
@@ -312,12 +300,6 @@ function attemptMarionetteConnect(port, connectFn) {
|
|
|
312
300
|
});
|
|
313
301
|
});
|
|
314
302
|
}
|
|
315
|
-
function delay(ms) {
|
|
316
|
-
return new Promise((resolve) => {
|
|
317
|
-
const timer = setTimeout(resolve, ms);
|
|
318
|
-
timer.unref();
|
|
319
|
-
});
|
|
320
|
-
}
|
|
321
303
|
/** Renders a PASS/FAIL banner to the CLI using the shared logger helpers. */
|
|
322
304
|
export function reportMarionettePreflight(result) {
|
|
323
305
|
if (result.ok) {
|
|
@@ -329,7 +311,7 @@ export function reportMarionettePreflight(result) {
|
|
|
329
311
|
}
|
|
330
312
|
/**
|
|
331
313
|
* Formats the PASS/FAIL banner as a plain string for direct
|
|
332
|
-
* `process.stdout.write` use
|
|
314
|
+
* `process.stdout.write` use, bypassing the clack logger entirely so
|
|
333
315
|
* operators running `fireforge test --doctor` under a non-TTY (pipe, CI,
|
|
334
316
|
* `tee`-wrapped capture) always see the final line. Clack's renderer can
|
|
335
317
|
* swallow trailing log output just before process exit, and a
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Minimal Markdown pipe-table parser/writer used by token-manager.
|
|
3
3
|
*
|
|
4
|
-
* This is
|
|
4
|
+
* This is not a general Markdown parser. It understands exactly the
|
|
5
5
|
* slice of GitHub-flavoured Markdown that FireForge emits into token docs:
|
|
6
6
|
*
|
|
7
7
|
* - Leading `|` per row, trailing `|` optional.
|
|
@@ -12,10 +12,10 @@
|
|
|
12
12
|
* - Literal `|` and `\` inside a cell are expressed as `\|` and `\\`
|
|
13
13
|
* respectively. The parser treats any other backslash as a literal
|
|
14
14
|
* so prose-style backslashes in cell values (e.g. a Windows path)
|
|
15
|
-
* still round-trip. Unescaping happens at split time
|
|
15
|
+
* still round-trip. Unescaping happens at split time. Serialization
|
|
16
16
|
* re-applies escapes so round-trips are exact for well-formed input.
|
|
17
17
|
*
|
|
18
|
-
* The parser returns
|
|
18
|
+
* The parser returns positional metadata (`startLine`, `endLine`) so
|
|
19
19
|
* callers can splice the table back into the surrounding document by
|
|
20
20
|
* range instead of hand-rolled line counters. Mutation operations return
|
|
21
21
|
* a fresh line array rather than mutating in place, matching the rest of
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
* Fallback tolerance: rows with more cells than the header get their
|
|
25
25
|
* overflow merged into the last column (using a literal `|` separator
|
|
26
26
|
* between the merged values). This is for the rare case where a FireForge
|
|
27
|
-
* writer emits an unescaped pipe
|
|
27
|
+
* writer emits an unescaped pipe. The parser still produces a consistent
|
|
28
28
|
* cell count rather than desynchronising the table. On re-serialize the
|
|
29
29
|
* merged cell's literal pipes are escaped, so a malformed input becomes
|
|
30
30
|
* a well-formed output after one round trip.
|
|
@@ -37,8 +37,8 @@ export interface MarkdownTable {
|
|
|
37
37
|
headers: string[];
|
|
38
38
|
/**
|
|
39
39
|
* Data rows. Each row is an array with exactly `headers.length` entries,
|
|
40
|
-
* trimmed. Rows shorter than the header are right-padded with `''
|
|
41
|
-
*
|
|
40
|
+
* trimmed. Rows shorter than the header are right-padded with `''`.
|
|
41
|
+
* Longer rows have trailing cells merged into the last column so the
|
|
42
42
|
* round-trip is faithful.
|
|
43
43
|
*/
|
|
44
44
|
rows: string[][];
|
|
@@ -60,14 +60,14 @@ export interface MarkdownTable {
|
|
|
60
60
|
*/
|
|
61
61
|
export declare function findNextTable(lines: string[], fromLine: number): MarkdownTable | null;
|
|
62
62
|
/**
|
|
63
|
-
* Returns the first table whose header contains
|
|
63
|
+
* Returns the first table whose header contains all of the provided
|
|
64
64
|
* column names (case-sensitive, order-insensitive). Useful when several
|
|
65
65
|
* pipe tables share a document and you want to select "the one with a
|
|
66
66
|
* Mode column".
|
|
67
67
|
*/
|
|
68
68
|
export declare function findTableByColumns(lines: string[], requiredColumns: string[]): MarkdownTable | null;
|
|
69
69
|
/**
|
|
70
|
-
* Returns the first table that appears
|
|
70
|
+
* Returns the first table that appears after a heading matching the
|
|
71
71
|
* given regex. The heading regex is applied to raw lines (no trimming)
|
|
72
72
|
* so callers that want leading whitespace flexibility should include
|
|
73
73
|
* `^\s*` or `^#+\s*` as appropriate.
|
|
@@ -83,7 +83,7 @@ export declare function findTableAfterHeading(lines: string[], headingPattern: R
|
|
|
83
83
|
export declare function serializeRow(cells: string[]): string;
|
|
84
84
|
/**
|
|
85
85
|
* Inserts a new row into `table.rows` at the given zero-based index. A
|
|
86
|
-
* negative index counts from the end
|
|
86
|
+
* negative index counts from the end. `Infinity` appends. Mutates the
|
|
87
87
|
* table object so callers using {@link rewriteTableRows} see the update.
|
|
88
88
|
*/
|
|
89
89
|
export declare function insertRow(table: MarkdownTable, cells: string[], index: number): void;
|