@hominis/fireforge 0.49.2 → 0.51.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +87 -1
- package/README.md +1 -1
- package/dist/bin/fireforge.js +6 -0
- package/dist/build-info.json +4 -4
- package/dist/src/commands/build-prelock.d.ts +20 -0
- package/dist/src/commands/build-prelock.js +50 -0
- package/dist/src/commands/build.d.ts +3 -1
- package/dist/src/commands/build.js +13 -6
- package/dist/src/commands/check-report.d.ts +41 -0
- package/dist/src/commands/check-report.js +91 -0
- package/dist/src/commands/check-run.d.ts +33 -0
- package/dist/src/commands/check-run.js +112 -0
- package/dist/src/commands/check-steps.d.ts +75 -0
- package/dist/src/commands/check-steps.js +200 -0
- package/dist/src/commands/check.d.ts +32 -0
- package/dist/src/commands/check.js +160 -0
- package/dist/src/commands/config.js +5 -6
- package/dist/src/commands/declarations-report.d.ts +43 -0
- package/dist/src/commands/declarations-report.js +76 -0
- package/dist/src/commands/doctor-engine-eslint.js +6 -1
- package/dist/src/commands/doctor-source-pin.js +4 -1
- package/dist/src/commands/export-adopt-check.d.ts +38 -0
- package/dist/src/commands/export-adopt-check.js +98 -0
- package/dist/src/commands/export-flow.js +29 -14
- package/dist/src/commands/export-placement-gate.d.ts +6 -2
- package/dist/src/commands/export-placement-gate.js +8 -0
- package/dist/src/commands/export-shared.d.ts +2 -1
- package/dist/src/commands/export-staged-registration.d.ts +46 -0
- package/dist/src/commands/export-staged-registration.js +91 -0
- package/dist/src/commands/forward-import-remedy.d.ts +32 -0
- package/dist/src/commands/forward-import-remedy.js +63 -0
- package/dist/src/commands/furnace/apply.js +3 -3
- package/dist/src/commands/furnace/chrome-doc-remove.d.ts +2 -1
- package/dist/src/commands/furnace/chrome-doc-remove.js +2 -2
- package/dist/src/commands/furnace/chrome-doc.d.ts +2 -1
- package/dist/src/commands/furnace/chrome-doc.js +2 -2
- package/dist/src/commands/furnace/create.js +2 -2
- package/dist/src/commands/furnace/deploy-named.d.ts +48 -0
- package/dist/src/commands/furnace/deploy-named.js +107 -0
- package/dist/src/commands/furnace/deploy.d.ts +3 -2
- package/dist/src/commands/furnace/deploy.js +50 -86
- package/dist/src/commands/furnace/diff.js +26 -3
- package/dist/src/commands/furnace/index.js +66 -41
- package/dist/src/commands/furnace/init.js +13 -6
- package/dist/src/commands/furnace/override.js +4 -2
- package/dist/src/commands/furnace/preview.js +4 -3
- package/dist/src/commands/furnace/refresh.js +2 -2
- package/dist/src/commands/furnace/remove.js +4 -3
- package/dist/src/commands/furnace/rename-dry-run.d.ts +29 -0
- package/dist/src/commands/furnace/rename-dry-run.js +127 -0
- package/dist/src/commands/furnace/rename-helpers.d.ts +7 -0
- package/dist/src/commands/furnace/rename-helpers.js +15 -1
- package/dist/src/commands/furnace/rename-registrations.d.ts +41 -0
- package/dist/src/commands/furnace/rename-registrations.js +98 -0
- package/dist/src/commands/furnace/rename.d.ts +2 -1
- package/dist/src/commands/furnace/rename.js +28 -66
- package/dist/src/commands/furnace/scan.d.ts +9 -4
- package/dist/src/commands/furnace/scan.js +11 -9
- package/dist/src/commands/furnace/sync.js +3 -2
- package/dist/src/commands/furnace/validate-report.d.ts +45 -0
- package/dist/src/commands/furnace/validate-report.js +91 -0
- package/dist/src/commands/furnace/validate.d.ts +1 -1
- package/dist/src/commands/furnace/validate.js +151 -113
- package/dist/src/commands/furnace/validation-output.js +14 -3
- package/dist/src/commands/lint-per-patch.js +36 -61
- package/dist/src/commands/lint-per-run-checkjs.js +2 -2
- package/dist/src/commands/lint-report.d.ts +8 -4
- package/dist/src/commands/lint-report.js +20 -5
- package/dist/src/commands/lint.js +15 -34
- package/dist/src/commands/manifest.js +4 -0
- package/dist/src/commands/park.d.ts +22 -0
- package/dist/src/commands/park.js +232 -0
- package/dist/src/commands/patch/delete-gap-notice.js +3 -1
- package/dist/src/commands/patch/delete.d.ts +1 -1
- package/dist/src/commands/patch/delete.js +24 -104
- package/dist/src/commands/patch/index.d.ts +3 -3
- package/dist/src/commands/patch/index.js +10 -4
- package/dist/src/commands/patch/lint-ignore-from.d.ts +44 -0
- package/dist/src/commands/patch/lint-ignore-from.js +142 -0
- package/dist/src/commands/patch/lint-ignore.d.ts +5 -1
- package/dist/src/commands/patch/lint-ignore.js +78 -31
- package/dist/src/commands/patch/move-files-create.js +34 -18
- package/dist/src/commands/patch/move-files-into.js +15 -7
- package/dist/src/commands/patch/move-files.js +6 -2
- package/dist/src/commands/patch/removal-created-files.d.ts +48 -0
- package/dist/src/commands/patch/removal-created-files.js +83 -0
- package/dist/src/commands/patch/removal-dependents.d.ts +63 -0
- package/dist/src/commands/patch/removal-dependents.js +133 -0
- package/dist/src/commands/patch/rename.js +20 -1
- package/dist/src/commands/patch/reserve.d.ts +33 -0
- package/dist/src/commands/patch/reserve.js +152 -0
- package/dist/src/commands/patch/retire.d.ts +34 -0
- package/dist/src/commands/patch/retire.js +133 -0
- package/dist/src/commands/patch/split-plan.d.ts +17 -8
- package/dist/src/commands/patch/split-plan.js +60 -28
- package/dist/src/commands/patch/split-staged.d.ts +108 -0
- package/dist/src/commands/patch/split-staged.js +202 -0
- package/dist/src/commands/patch/split.d.ts +5 -0
- package/dist/src/commands/patch/split.js +62 -17
- package/dist/src/commands/patch/stage.d.ts +34 -0
- package/dist/src/commands/patch/stage.js +153 -0
- package/dist/src/commands/patch/staged-dependency-batch.d.ts +48 -0
- package/dist/src/commands/patch/staged-dependency-batch.js +176 -0
- package/dist/src/commands/patch/staged-dependency-entries.d.ts +36 -0
- package/dist/src/commands/patch/staged-dependency-entries.js +52 -0
- package/dist/src/commands/patch/staged-dependency-from.d.ts +14 -0
- package/dist/src/commands/patch/staged-dependency-from.js +108 -0
- package/dist/src/commands/patch/staged-dependency-remove.d.ts +31 -0
- package/dist/src/commands/patch/staged-dependency-remove.js +80 -0
- package/dist/src/commands/patch/staged-dependency.js +54 -139
- package/dist/src/commands/re-export-adjacent-registrations.d.ts +20 -0
- package/dist/src/commands/re-export-adjacent-registrations.js +75 -0
- package/dist/src/commands/re-export-adjacent.d.ts +50 -2
- package/dist/src/commands/re-export-adjacent.js +160 -40
- package/dist/src/commands/re-export-bulk-scan.d.ts +2 -1
- package/dist/src/commands/re-export-bulk-scan.js +22 -7
- package/dist/src/commands/re-export-drift.d.ts +36 -8
- package/dist/src/commands/re-export-drift.js +73 -49
- package/dist/src/commands/re-export-files.js +11 -8
- package/dist/src/commands/re-export-hunks.d.ts +35 -0
- package/dist/src/commands/re-export-hunks.js +220 -0
- package/dist/src/commands/re-export-lint.d.ts +2 -1
- package/dist/src/commands/re-export-lint.js +23 -10
- package/dist/src/commands/re-export-options.js +74 -6
- package/dist/src/commands/re-export-preflight.d.ts +23 -0
- package/dist/src/commands/re-export-preflight.js +160 -0
- package/dist/src/commands/re-export-purity-scope.d.ts +18 -0
- package/dist/src/commands/re-export-purity-scope.js +131 -0
- package/dist/src/commands/re-export-register.js +56 -17
- package/dist/src/commands/re-export-removed.d.ts +13 -2
- package/dist/src/commands/re-export-removed.js +57 -12
- package/dist/src/commands/re-export-scan-owner.d.ts +44 -0
- package/dist/src/commands/re-export-scan-owner.js +116 -0
- package/dist/src/commands/re-export-scan.d.ts +19 -9
- package/dist/src/commands/re-export-scan.js +60 -24
- package/dist/src/commands/re-export-single.js +122 -46
- package/dist/src/commands/re-export-stale-registrations.d.ts +18 -0
- package/dist/src/commands/re-export-stale-registrations.js +62 -0
- package/dist/src/commands/re-export-summary.d.ts +28 -0
- package/dist/src/commands/re-export-summary.js +36 -0
- package/dist/src/commands/re-export.js +71 -57
- package/dist/src/commands/rebase/index.js +17 -17
- package/dist/src/commands/run.js +16 -2
- package/dist/src/commands/status-check.d.ts +55 -16
- package/dist/src/commands/status-check.js +92 -37
- package/dist/src/commands/status-json.d.ts +22 -9
- package/dist/src/commands/status-json.js +47 -32
- package/dist/src/commands/status-output.js +3 -1
- package/dist/src/commands/status-scope.d.ts +37 -0
- package/dist/src/commands/status-scope.js +54 -0
- package/dist/src/commands/status.js +66 -23
- package/dist/src/commands/test-browser-preflight.js +19 -3
- package/dist/src/commands/test-build-furnace.d.ts +22 -0
- package/dist/src/commands/test-build-furnace.js +54 -0
- package/dist/src/commands/test-build-phase.js +64 -41
- package/dist/src/commands/test-checkjs.js +10 -2
- package/dist/src/commands/test-diagnose.js +7 -0
- package/dist/src/commands/test-dispatch.d.ts +39 -0
- package/dist/src/commands/test-dispatch.js +211 -0
- package/dist/src/commands/test-furnace-reach.d.ts +37 -0
- package/dist/src/commands/test-furnace-reach.js +132 -0
- package/dist/src/commands/test-modes.d.ts +16 -1
- package/dist/src/commands/test-modes.js +24 -1
- package/dist/src/commands/test-multi-verdict.d.ts +61 -0
- package/dist/src/commands/test-multi-verdict.js +111 -0
- package/dist/src/commands/test-orchestrate.d.ts +52 -0
- package/dist/src/commands/test-orchestrate.js +240 -0
- package/dist/src/commands/test-perf-scope.d.ts +50 -0
- package/dist/src/commands/test-perf-scope.js +138 -0
- package/dist/src/commands/test-prelock.d.ts +51 -0
- package/dist/src/commands/test-prelock.js +273 -0
- package/dist/src/commands/test-register.js +69 -10
- package/dist/src/commands/test-results.d.ts +62 -0
- package/dist/src/commands/test-results.js +62 -0
- package/dist/src/commands/test-run.d.ts +13 -55
- package/dist/src/commands/test-run.js +74 -99
- package/dist/src/commands/test-shards.d.ts +110 -0
- package/dist/src/commands/test-shards.js +255 -0
- package/dist/src/commands/test-stale-gate.d.ts +5 -1
- package/dist/src/commands/test-stale-gate.js +60 -28
- package/dist/src/commands/test-verdict.d.ts +11 -1
- package/dist/src/commands/test-verdict.js +28 -1
- package/dist/src/commands/test.d.ts +6 -1
- package/dist/src/commands/test.js +120 -124
- package/dist/src/commands/token-lint.d.ts +14 -0
- package/dist/src/commands/token-lint.js +151 -0
- package/dist/src/commands/token.js +10 -0
- package/dist/src/commands/verify-scope.d.ts +28 -0
- package/dist/src/commands/verify-scope.js +67 -0
- package/dist/src/commands/verify.d.ts +10 -2
- package/dist/src/commands/verify.js +67 -36
- package/dist/src/core/build-baseline-types.d.ts +46 -0
- package/dist/src/core/build-baseline-validate.js +19 -0
- package/dist/src/core/build-baseline.d.ts +5 -1
- package/dist/src/core/build-baseline.js +3 -1
- package/dist/src/core/build-overwrite-guard.d.ts +50 -0
- package/dist/src/core/build-overwrite-guard.js +84 -4
- package/dist/src/core/build-prepare.d.ts +13 -0
- package/dist/src/core/build-prepare.js +42 -10
- package/dist/src/core/build-run-record.d.ts +74 -0
- package/dist/src/core/build-run-record.js +136 -0
- package/dist/src/core/checkjs-support-heads.d.ts +41 -0
- package/dist/src/core/checkjs-support-heads.js +104 -0
- package/dist/src/core/config-paths.d.ts +2 -2
- package/dist/src/core/config-paths.js +10 -0
- package/dist/src/core/config-validate-check.d.ts +8 -0
- package/dist/src/core/config-validate-check.js +219 -0
- package/dist/src/core/config-validate-file-size.d.ts +9 -6
- package/dist/src/core/config-validate-file-size.js +91 -2
- package/dist/src/core/config-validate-history.d.ts +11 -0
- package/dist/src/core/config-validate-history.js +38 -0
- package/dist/src/core/config-validate-patch-policy.js +100 -0
- package/dist/src/core/config-validate-test-toolchains.js +21 -0
- package/dist/src/core/config-validate-token-scales.d.ts +9 -0
- package/dist/src/core/config-validate-token-scales.js +92 -0
- package/dist/src/core/config-validate.js +20 -5
- package/dist/src/core/config.d.ts +5 -0
- package/dist/src/core/config.js +16 -0
- package/dist/src/core/coverage-dispatch.d.ts +24 -0
- package/dist/src/core/coverage-dispatch.js +44 -0
- package/dist/src/core/coverage-extend.d.ts +70 -45
- package/dist/src/core/coverage-extend.js +199 -144
- package/dist/src/core/coverage-records.d.ts +108 -0
- package/dist/src/core/coverage-records.js +384 -0
- package/dist/src/core/destructive.d.ts +7 -4
- package/dist/src/core/destructive.js +10 -10
- package/dist/src/core/engine-session-lock.d.ts +16 -1
- package/dist/src/core/engine-session-lock.js +38 -10
- package/dist/src/core/export-moved-code-shape.d.ts +49 -11
- package/dist/src/core/export-moved-code-shape.js +135 -44
- package/dist/src/core/file-lock-queue.d.ts +67 -0
- package/dist/src/core/file-lock-queue.js +221 -0
- package/dist/src/core/file-lock-shared.d.ts +57 -0
- package/dist/src/core/file-lock-shared.js +117 -0
- package/dist/src/core/file-lock.d.ts +13 -25
- package/dist/src/core/file-lock.js +163 -140
- package/dist/src/core/furnace-apply-output.d.ts +10 -0
- package/dist/src/core/furnace-apply-output.js +31 -1
- package/dist/src/core/furnace-apply.js +22 -12
- package/dist/src/core/furnace-composed-source.d.ts +76 -0
- package/dist/src/core/furnace-composed-source.js +167 -0
- package/dist/src/core/furnace-config-validate-exceptions.d.ts +16 -0
- package/dist/src/core/furnace-config-validate-exceptions.js +102 -0
- package/dist/src/core/furnace-config-validate.js +14 -0
- package/dist/src/core/furnace-css-fragments.d.ts +10 -0
- package/dist/src/core/furnace-css-fragments.js +26 -0
- package/dist/src/core/furnace-operation.d.ts +3 -3
- package/dist/src/core/furnace-registration-jar-inplace.d.ts +12 -0
- package/dist/src/core/furnace-registration-jar-inplace.js +80 -0
- package/dist/src/core/furnace-registration-remove.d.ts +22 -1
- package/dist/src/core/furnace-registration-remove.js +53 -17
- package/dist/src/core/furnace-registration-rename.d.ts +26 -0
- package/dist/src/core/furnace-registration-rename.js +77 -0
- package/dist/src/core/furnace-registration.d.ts +14 -4
- package/dist/src/core/furnace-registration.js +44 -10
- package/dist/src/core/furnace-staleness.d.ts +7 -0
- package/dist/src/core/furnace-staleness.js +34 -24
- package/dist/src/core/furnace-validate-accessibility.d.ts +8 -4
- package/dist/src/core/furnace-validate-accessibility.js +71 -28
- package/dist/src/core/furnace-validate-exceptions.d.ts +48 -0
- package/dist/src/core/furnace-validate-exceptions.js +80 -0
- package/dist/src/core/furnace-validate-icon-button.d.ts +7 -0
- package/dist/src/core/furnace-validate-icon-button.js +78 -0
- package/dist/src/core/furnace-validate.js +1 -1
- package/dist/src/core/harness-port-fallback.d.ts +60 -0
- package/dist/src/core/harness-port-fallback.js +96 -0
- package/dist/src/core/history-log-file.d.ts +61 -0
- package/dist/src/core/history-log-file.js +164 -0
- package/dist/src/core/history-log.d.ts +2 -1
- package/dist/src/core/history-log.js +2 -1
- package/dist/src/core/json-preserving-edit.d.ts +22 -0
- package/dist/src/core/json-preserving-edit.js +199 -0
- package/dist/src/core/line-prefixer.d.ts +18 -0
- package/dist/src/core/line-prefixer.js +34 -0
- package/dist/src/core/mach.d.ts +7 -0
- package/dist/src/core/mach.js +32 -10
- package/dist/src/core/module-resolution-preflight.d.ts +19 -3
- package/dist/src/core/module-resolution-preflight.js +24 -6
- package/dist/src/core/negative-control-compiled.d.ts +27 -0
- package/dist/src/core/negative-control-compiled.js +73 -0
- package/dist/src/core/negative-control-diff.d.ts +51 -0
- package/dist/src/core/negative-control-diff.js +179 -0
- package/dist/src/core/negative-control.d.ts +150 -0
- package/dist/src/core/negative-control.js +399 -0
- package/dist/src/core/objdir-install-manifests.d.ts +73 -0
- package/dist/src/core/objdir-install-manifests.js +226 -0
- package/dist/src/core/park-store.d.ts +63 -0
- package/dist/src/core/park-store.js +216 -0
- package/dist/src/core/patch-export-update.d.ts +6 -0
- package/dist/src/core/patch-export-update.js +13 -3
- package/dist/src/core/patch-export.d.ts +3 -2
- package/dist/src/core/patch-export.js +22 -16
- package/dist/src/core/patch-files.js +26 -8
- package/dist/src/core/patch-lint-checkjs-any-import.d.ts +39 -0
- package/dist/src/core/patch-lint-checkjs-any-import.js +63 -0
- package/dist/src/core/patch-lint-checkjs-diagnostics.d.ts +17 -0
- package/dist/src/core/patch-lint-checkjs-diagnostics.js +32 -0
- package/dist/src/core/patch-lint-checkjs.d.ts +10 -1
- package/dist/src/core/patch-lint-checkjs.js +20 -13
- package/dist/src/core/patch-lint-code-lines.d.ts +59 -0
- package/dist/src/core/patch-lint-code-lines.js +105 -0
- package/dist/src/core/patch-lint-cross.d.ts +3 -1
- package/dist/src/core/patch-lint-cross.js +17 -4
- package/dist/src/core/patch-lint-css.d.ts +8 -2
- package/dist/src/core/patch-lint-css.js +24 -14
- package/dist/src/core/patch-lint-file-size.d.ts +12 -5
- package/dist/src/core/patch-lint-file-size.js +22 -11
- package/dist/src/core/patch-lint-forward-registration-extended.d.ts +23 -0
- package/dist/src/core/patch-lint-forward-registration-extended.js +36 -11
- package/dist/src/core/patch-lint-forward-registration.js +10 -0
- package/dist/src/core/patch-lint-ignore.d.ts +196 -0
- package/dist/src/core/patch-lint-ignore.js +429 -0
- package/dist/src/core/patch-lint-ownership.d.ts +10 -0
- package/dist/src/core/patch-lint-ownership.js +26 -0
- package/dist/src/core/patch-lint-size-thresholds.d.ts +52 -0
- package/dist/src/core/patch-lint-size-thresholds.js +110 -0
- package/dist/src/core/patch-lint-size.d.ts +117 -0
- package/dist/src/core/patch-lint-size.js +331 -0
- package/dist/src/core/patch-lint-staged-registration.d.ts +18 -1
- package/dist/src/core/patch-lint-staged-registration.js +20 -0
- package/dist/src/core/patch-lint-token-scale.d.ts +57 -0
- package/dist/src/core/patch-lint-token-scale.js +286 -0
- package/dist/src/core/patch-lint.d.ts +11 -83
- package/dist/src/core/patch-lint.js +66 -288
- package/dist/src/core/patch-lock.js +7 -6
- package/dist/src/core/patch-manifest-consistency.js +7 -6
- package/dist/src/core/patch-manifest-io.d.ts +6 -3
- package/dist/src/core/patch-manifest-io.js +27 -9
- package/dist/src/core/patch-manifest-key-order.d.ts +24 -0
- package/dist/src/core/patch-manifest-key-order.js +61 -0
- package/dist/src/core/patch-manifest-stage.d.ts +46 -0
- package/dist/src/core/patch-manifest-stage.js +96 -0
- package/dist/src/core/patch-manifest-validate.js +61 -3
- package/dist/src/core/patch-order-legal.d.ts +26 -0
- package/dist/src/core/patch-order-legal.js +88 -0
- package/dist/src/core/patch-policy-content.d.ts +40 -0
- package/dist/src/core/patch-policy-content.js +216 -0
- package/dist/src/core/patch-policy.d.ts +22 -5
- package/dist/src/core/patch-policy.js +26 -12
- package/dist/src/core/patch-retired.d.ts +57 -0
- package/dist/src/core/patch-retired.js +92 -0
- package/dist/src/core/patch-subset.d.ts +16 -0
- package/dist/src/core/patch-subset.js +66 -0
- package/dist/src/core/preflight-wait.d.ts +20 -0
- package/dist/src/core/preflight-wait.js +38 -0
- package/dist/src/core/rebase-from-version.d.ts +46 -0
- package/dist/src/core/rebase-from-version.js +71 -0
- package/dist/src/core/run-log.d.ts +26 -0
- package/dist/src/core/run-log.js +106 -4
- package/dist/src/core/run-profile.d.ts +7 -0
- package/dist/src/core/run-profile.js +7 -1
- package/dist/src/core/smoke-patterns.d.ts +5 -0
- package/dist/src/core/smoke-patterns.js +13 -0
- package/dist/src/core/test-harness-crash.d.ts +19 -1
- package/dist/src/core/test-harness-crash.js +8 -9
- package/dist/src/core/test-harness-signature.d.ts +33 -0
- package/dist/src/core/test-harness-signature.js +23 -1
- package/dist/src/core/test-raw-log.d.ts +66 -0
- package/dist/src/core/test-raw-log.js +122 -0
- package/dist/src/core/test-run-completeness.d.ts +90 -0
- package/dist/src/core/test-run-completeness.js +184 -0
- package/dist/src/core/test-stale-check.d.ts +27 -1
- package/dist/src/core/test-stale-check.js +39 -49
- package/dist/src/core/test-stale-exempt.d.ts +40 -0
- package/dist/src/core/test-stale-exempt.js +70 -0
- package/dist/src/core/test-xpcshell-retry.d.ts +2 -0
- package/dist/src/core/test-xpcshell-retry.js +2 -1
- package/dist/src/core/token-lint.d.ts +53 -0
- package/dist/src/core/token-lint.js +131 -0
- package/dist/src/core/token-sibling-sheets.d.ts +46 -0
- package/dist/src/core/token-sibling-sheets.js +119 -0
- package/dist/src/core/tree-guard.js +5 -0
- package/dist/src/core/typecheck-shim.d.ts +6 -2
- package/dist/src/core/typecheck-shim.js +205 -4
- package/dist/src/core/typecheck.js +3 -1
- package/dist/src/index.d.ts +14 -3
- package/dist/src/index.js +6 -1
- package/dist/src/types/commands/index.d.ts +2 -2
- package/dist/src/types/commands/options.d.ts +212 -24
- package/dist/src/types/commands/patches.d.ts +118 -1
- package/dist/src/types/config.d.ts +264 -0
- package/dist/src/types/config.js +9 -0
- package/dist/src/types/furnace.d.ts +63 -1
- package/dist/src/types/furnace.js +7 -0
- package/dist/src/types/index.d.ts +1 -1
- package/dist/src/utils/options.d.ts +36 -7
- package/dist/src/utils/options.js +94 -8
- package/dist/src/utils/path-glob.d.ts +15 -0
- package/dist/src/utils/path-glob.js +47 -0
- package/dist/src/utils/regex.d.ts +15 -3
- package/dist/src/utils/regex.js +37 -16
- package/docs/configuration.md +369 -11
- package/docs/exit-codes.md +18 -1
- package/docs/furnace.md +139 -3
- package/docs/lifecycle-invariants.md +65 -30
- package/docs/machine-output.md +120 -12
- package/docs/patch-workflow.md +458 -22
- package/docs/run-logs.md +20 -1
- package/docs/testing.md +346 -21
- package/package.json +3 -3
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { toError } from '../utils/errors.js';
|
|
4
4
|
import { pathExists, readText, removeFile, writeText } from '../utils/fs.js';
|
|
5
|
-
import { warn } from '../utils/logger.js';
|
|
5
|
+
import { info, warn } from '../utils/logger.js';
|
|
6
6
|
import { discoverPatches, withPatchDirectoryLock } from './patch-apply.js';
|
|
7
7
|
import { findAllPatchesForFilesWithDetails, } from './patch-export-coverage.js';
|
|
8
8
|
import { addPatchToManifest, loadPatchesManifestForWrite, PATCHES_MANIFEST, savePatchesManifest, } from './patch-manifest.js';
|
|
9
9
|
import { formatPatchOrder, requirePatchOrder } from './patch-parse.js';
|
|
10
10
|
import { allocatePolicyOrder, enforcePatchPolicy } from './patch-policy.js';
|
|
11
|
+
import { manifestWithRetiredSlots, reservationAt, reservedOrderSet } from './patch-retired.js';
|
|
11
12
|
export { findAllPatchesForFiles, findAllPatchesForFilesWithDetails, } from './patch-export-coverage.js';
|
|
12
13
|
import { escapeRegex } from '../utils/regex.js';
|
|
13
14
|
export { mutatePatchMetadata, updatePatchMetadata } from './patch-export-metadata.js';
|
|
@@ -39,18 +40,16 @@ export function buildPlanExportInput(input) {
|
|
|
39
40
|
/**
|
|
40
41
|
* Gets the next patch number for a new patch.
|
|
41
42
|
* @param patchesDir - Path to the patches directory
|
|
43
|
+
* @param reserved - Orders held by `patch reserve`, skipped
|
|
42
44
|
* @returns Next patch number (e.g., "005" for 4 existing patches)
|
|
43
45
|
*/
|
|
44
|
-
export async function getNextPatchNumber(patchesDir) {
|
|
46
|
+
export async function getNextPatchNumber(patchesDir, reserved = new Set()) {
|
|
45
47
|
const patches = await discoverPatches(patchesDir);
|
|
46
|
-
if (patches.length === 0) {
|
|
47
|
-
return '001';
|
|
48
|
-
}
|
|
49
48
|
const finitePatches = patches.filter((p) => Number.isFinite(p.order));
|
|
50
|
-
if (finitePatches.length === 0)
|
|
51
|
-
return '001';
|
|
52
49
|
const maxOrder = finitePatches.reduce((max, p) => Math.max(max, p.order), 0);
|
|
53
|
-
|
|
50
|
+
let nextNumber = maxOrder + 1;
|
|
51
|
+
while (reserved.has(nextNumber))
|
|
52
|
+
nextNumber++;
|
|
54
53
|
return String(nextNumber).padStart(Math.max(3, String(nextNumber).length), '0');
|
|
55
54
|
}
|
|
56
55
|
/**
|
|
@@ -117,8 +116,8 @@ export function patchNameSlug(name, category) {
|
|
|
117
116
|
* @param name - Human-readable name
|
|
118
117
|
* @returns Filename like "001-ui-sidebar.patch"
|
|
119
118
|
*/
|
|
120
|
-
export async function getNextPatchFilename(patchesDir, category, name) {
|
|
121
|
-
const patchNumber = await getNextPatchNumber(patchesDir);
|
|
119
|
+
export async function getNextPatchFilename(patchesDir, category, name, reserved = new Set()) {
|
|
120
|
+
const patchNumber = await getNextPatchNumber(patchesDir, reserved);
|
|
122
121
|
const sanitizedName = patchNameSlug(name, category);
|
|
123
122
|
return `${patchNumber}-${category}-${sanitizedName}.patch`;
|
|
124
123
|
}
|
|
@@ -233,12 +232,15 @@ async function computeExportPlanUnderLock(input) {
|
|
|
233
232
|
// wipes the queue metadata, and the rollback path would then delete
|
|
234
233
|
// patches.json entirely because manifestBefore looked absent.
|
|
235
234
|
const manifestBefore = await loadPatchesManifestForWrite(input.patchesDir);
|
|
235
|
+
// A default allocation never lands on a reservation; only an explicit
|
|
236
|
+
// `--order` placement fills one.
|
|
237
|
+
const reserved = reservedOrderSet(manifestBefore ?? {});
|
|
236
238
|
const policyOrder = input.config !== undefined
|
|
237
|
-
? allocatePolicyOrder(input.config, manifestBefore?.patches ?? [], input.category)
|
|
239
|
+
? allocatePolicyOrder(input.config, manifestBefore?.patches ?? [], input.category, reserved)
|
|
238
240
|
: null;
|
|
239
241
|
const patchFilename = policyOrder !== null
|
|
240
242
|
? `${formatPatchOrder(policyOrder)}-${input.category}-${patchNameSlug(input.name, input.category)}.patch`
|
|
241
|
-
: await getNextPatchFilename(input.patchesDir, input.category, input.name);
|
|
243
|
+
: await getNextPatchFilename(input.patchesDir, input.category, input.name, reserved);
|
|
242
244
|
const patchPath = join(input.patchesDir, patchFilename);
|
|
243
245
|
const metadata = {
|
|
244
246
|
filename: patchFilename,
|
|
@@ -266,6 +268,12 @@ async function computeExportPlanUnderLock(input) {
|
|
|
266
268
|
const afterPatches = (manifestBefore?.patches ?? []).filter((p) => !supersededSet.has(p.filename) && p.filename !== patchFilename);
|
|
267
269
|
afterPatches.push(metadata);
|
|
268
270
|
afterPatches.sort((a, b) => a.order - b.order || a.filename.localeCompare(b.filename));
|
|
271
|
+
const reservation = reservationAt(manifestBefore, metadata.order);
|
|
272
|
+
if (reservation !== undefined) {
|
|
273
|
+
info(`Order ${formatPatchOrder(metadata.order)} was reserved by ${reservation.owner}` +
|
|
274
|
+
`${reservation.reason !== undefined ? ` (${reservation.reason})` : ''}; ` +
|
|
275
|
+
'this export fills the reservation.');
|
|
276
|
+
}
|
|
269
277
|
return {
|
|
270
278
|
patchFilename,
|
|
271
279
|
patchPath,
|
|
@@ -273,10 +281,8 @@ async function computeExportPlanUnderLock(input) {
|
|
|
273
281
|
supersededDetails,
|
|
274
282
|
supersededPatches,
|
|
275
283
|
manifestBefore: manifestBefore ?? null,
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
patches: afterPatches,
|
|
279
|
-
},
|
|
284
|
+
// A patch landing on a retired or reserved order fills that slot.
|
|
285
|
+
manifestAfter: manifestWithRetiredSlots(manifestBefore, afterPatches),
|
|
280
286
|
};
|
|
281
287
|
}
|
|
282
288
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
-
import { readdir } from 'node:fs/promises';
|
|
2
|
+
import { readdir, stat } from 'node:fs/promises';
|
|
3
3
|
import { extname, join } from 'node:path';
|
|
4
4
|
import { pathExists, readText } from '../utils/fs.js';
|
|
5
5
|
import { extractAffectedFiles, extractOrder } from './patch-parse.js';
|
|
@@ -9,16 +9,34 @@ export async function discoverPatches(patchesDir) {
|
|
|
9
9
|
return [];
|
|
10
10
|
}
|
|
11
11
|
const entries = await readdir(patchesDir, { withFileTypes: true });
|
|
12
|
-
const patches =
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
12
|
+
const patches = [];
|
|
13
|
+
for (const entry of entries) {
|
|
14
|
+
if (extname(entry.name) !== '.patch')
|
|
15
|
+
continue;
|
|
16
|
+
// A symlinked patch (a scratch queue built from links to the real
|
|
17
|
+
// patches) counts when it resolves to a regular file; a dangling link or
|
|
18
|
+
// a link to a directory does not.
|
|
19
|
+
if (!entry.isFile() &&
|
|
20
|
+
!(entry.isSymbolicLink() && (await isLinkToFile(patchesDir, entry.name)))) {
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
patches.push({
|
|
24
|
+
path: join(patchesDir, entry.name),
|
|
25
|
+
filename: entry.name,
|
|
26
|
+
order: extractOrder(entry.name),
|
|
27
|
+
});
|
|
28
|
+
}
|
|
19
29
|
patches.sort((a, b) => a.order - b.order || a.filename.localeCompare(b.filename));
|
|
20
30
|
return patches;
|
|
21
31
|
}
|
|
32
|
+
async function isLinkToFile(dir, name) {
|
|
33
|
+
try {
|
|
34
|
+
return (await stat(join(dir, name))).isFile();
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
22
40
|
/** Counts the patch files currently present in a patch directory. */
|
|
23
41
|
export async function countPatches(patchesDir) {
|
|
24
42
|
const patches = await discoverPatches(patchesDir);
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Explains an implicit-`any` checkJs finding that comes from a URL import
|
|
3
|
+
* the per-patch program cannot resolve.
|
|
4
|
+
*
|
|
5
|
+
* The program resolves URL imports only to modules the queue creates (for
|
|
6
|
+
* a test, those created up to its own patch, plus its directory's
|
|
7
|
+
* head.js), so a `resource:///` or `chrome://` import of a module a later
|
|
8
|
+
* patch creates, an upstream module, or a basename two patches create
|
|
9
|
+
* falls back to the shim's `declare module 'resource:*'` wildcard and
|
|
10
|
+
* types as `any`. A callback
|
|
11
|
+
* over its values then has implicitly-`any` parameters under
|
|
12
|
+
* `checkJsStrict`, while the whole-tree `fireforge typecheck`, which sees
|
|
13
|
+
* the module, is clean. Without the note the two disagree with no
|
|
14
|
+
* explanation. Split out of patch-lint-checkjs.ts for the line budget.
|
|
15
|
+
*/
|
|
16
|
+
/** Unresolved URL import specifiers, keyed by the importing file's TS path. */
|
|
17
|
+
export type AnyTypedImports = Map<string, Set<string>>;
|
|
18
|
+
/**
|
|
19
|
+
* The note an implicit-`any` finding carries when its file imports a
|
|
20
|
+
* `resource://`/`chrome://` module this checkJs program could not resolve.
|
|
21
|
+
* Such an import types as `any` (the shim's wildcard module), so a
|
|
22
|
+
* callback over its values has implicitly-`any` parameters here while the
|
|
23
|
+
* whole-tree `fireforge typecheck`, which sees the module, is clean.
|
|
24
|
+
*/
|
|
25
|
+
export declare function anyTypedImportHint(code: number, specifiers: ReadonlySet<string> | undefined): string;
|
|
26
|
+
/**
|
|
27
|
+
* The host's `resolveModuleNameLiterals`: owned specifiers first, then a
|
|
28
|
+
* reviewed `paths` mapping, recording every URL import that resolves to
|
|
29
|
+
* neither.
|
|
30
|
+
*
|
|
31
|
+
* @param resolveOwned - Patch-owned specifier resolver
|
|
32
|
+
* @param resolveViaPaths - Optional `paths` resolver
|
|
33
|
+
* @param into - Map that collects the unresolved URL imports
|
|
34
|
+
*/
|
|
35
|
+
export declare function createModuleLiteralResolver<Resolved>(resolveOwned: (specifier: string) => Resolved | undefined, resolveViaPaths: ((specifier: string) => Resolved | undefined) | undefined, into: AnyTypedImports): (moduleLiterals: readonly {
|
|
36
|
+
text: string;
|
|
37
|
+
}[], containingFile: string) => Array<{
|
|
38
|
+
resolvedModule: Resolved | undefined;
|
|
39
|
+
}>;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
/**
|
|
3
|
+
* Explains an implicit-`any` checkJs finding that comes from a URL import
|
|
4
|
+
* the per-patch program cannot resolve.
|
|
5
|
+
*
|
|
6
|
+
* The program resolves URL imports only to modules the queue creates (for
|
|
7
|
+
* a test, those created up to its own patch, plus its directory's
|
|
8
|
+
* head.js), so a `resource:///` or `chrome://` import of a module a later
|
|
9
|
+
* patch creates, an upstream module, or a basename two patches create
|
|
10
|
+
* falls back to the shim's `declare module 'resource:*'` wildcard and
|
|
11
|
+
* types as `any`. A callback
|
|
12
|
+
* over its values then has implicitly-`any` parameters under
|
|
13
|
+
* `checkJsStrict`, while the whole-tree `fireforge typecheck`, which sees
|
|
14
|
+
* the module, is clean. Without the note the two disagree with no
|
|
15
|
+
* explanation. Split out of patch-lint-checkjs.ts for the line budget.
|
|
16
|
+
*/
|
|
17
|
+
/** TypeScript's implicit-`any` diagnostic codes (noImplicitAny). */
|
|
18
|
+
const IMPLICIT_ANY_CODES = new Set([
|
|
19
|
+
7005, 7006, 7008, 7010, 7011, 7019, 7031, 7034,
|
|
20
|
+
]);
|
|
21
|
+
function recordAnyTypedImport(into, containingFile, specifier) {
|
|
22
|
+
if (!/^(?:resource|chrome):/.test(specifier))
|
|
23
|
+
return;
|
|
24
|
+
const list = into.get(containingFile) ?? new Set();
|
|
25
|
+
list.add(specifier);
|
|
26
|
+
into.set(containingFile, list);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* The note an implicit-`any` finding carries when its file imports a
|
|
30
|
+
* `resource://`/`chrome://` module this checkJs program could not resolve.
|
|
31
|
+
* Such an import types as `any` (the shim's wildcard module), so a
|
|
32
|
+
* callback over its values has implicitly-`any` parameters here while the
|
|
33
|
+
* whole-tree `fireforge typecheck`, which sees the module, is clean.
|
|
34
|
+
*/
|
|
35
|
+
export function anyTypedImportHint(code, specifiers) {
|
|
36
|
+
if (!IMPLICIT_ANY_CODES.has(code) || specifiers === undefined || specifiers.size === 0)
|
|
37
|
+
return '';
|
|
38
|
+
const list = [...specifiers].sort().join(', ');
|
|
39
|
+
return (` (This file imports ${list}, which this per-patch checkJs program cannot resolve — ` +
|
|
40
|
+
'no patch up to this one creates the module under that name: a later patch creates it, ' +
|
|
41
|
+
'it is upstream, or two patches create the same basename — so the import is typed `any`. ' +
|
|
42
|
+
'Annotate the parameter explicitly; the whole-tree "fireforge typecheck" resolves the real type.)');
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The host's `resolveModuleNameLiterals`: owned specifiers first, then a
|
|
46
|
+
* reviewed `paths` mapping, recording every URL import that resolves to
|
|
47
|
+
* neither.
|
|
48
|
+
*
|
|
49
|
+
* @param resolveOwned - Patch-owned specifier resolver
|
|
50
|
+
* @param resolveViaPaths - Optional `paths` resolver
|
|
51
|
+
* @param into - Map that collects the unresolved URL imports
|
|
52
|
+
*/
|
|
53
|
+
export function createModuleLiteralResolver(resolveOwned, resolveViaPaths, into) {
|
|
54
|
+
return (moduleLiterals, containingFile) => moduleLiterals.map((literal) => {
|
|
55
|
+
const owned = resolveOwned(literal.text);
|
|
56
|
+
if (owned)
|
|
57
|
+
return { resolvedModule: owned };
|
|
58
|
+
const viaPaths = resolveViaPaths?.(literal.text);
|
|
59
|
+
if (viaPaths === undefined)
|
|
60
|
+
recordAnyTypedImport(into, containingFile, literal.text);
|
|
61
|
+
return { resolvedModule: viaPaths };
|
|
62
|
+
});
|
|
63
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collects a checkJs program's diagnostics, for every file or for a report
|
|
3
|
+
* scope only. A per-test program resolves the modules its imports reach
|
|
4
|
+
* (see `runCheckJsTestFilesGrouped`), and asking for the whole program's
|
|
5
|
+
* diagnostics would type-check each of those modules once per test, so a
|
|
6
|
+
* scoped run asks only for the files it reports. Split out of
|
|
7
|
+
* patch-lint-checkjs.ts for the line budget.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* The program's semantic and syntactic diagnostics, limited to the files
|
|
11
|
+
* `reportOnly` names when it is set.
|
|
12
|
+
*
|
|
13
|
+
* @param program - The built program
|
|
14
|
+
* @param relByAbsolute - Owned files: TS path → repo-relative path
|
|
15
|
+
* @param reportOnly - Repo-relative files to collect for, or all when unset
|
|
16
|
+
*/
|
|
17
|
+
export declare function collectCheckJsDiagnostics(program: import('typescript').Program, relByAbsolute: ReadonlyMap<string, string>, reportOnly: ReadonlySet<string> | undefined): import('typescript').Diagnostic[];
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
/**
|
|
3
|
+
* Collects a checkJs program's diagnostics, for every file or for a report
|
|
4
|
+
* scope only. A per-test program resolves the modules its imports reach
|
|
5
|
+
* (see `runCheckJsTestFilesGrouped`), and asking for the whole program's
|
|
6
|
+
* diagnostics would type-check each of those modules once per test, so a
|
|
7
|
+
* scoped run asks only for the files it reports. Split out of
|
|
8
|
+
* patch-lint-checkjs.ts for the line budget.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* The program's semantic and syntactic diagnostics, limited to the files
|
|
12
|
+
* `reportOnly` names when it is set.
|
|
13
|
+
*
|
|
14
|
+
* @param program - The built program
|
|
15
|
+
* @param relByAbsolute - Owned files: TS path → repo-relative path
|
|
16
|
+
* @param reportOnly - Repo-relative files to collect for, or all when unset
|
|
17
|
+
*/
|
|
18
|
+
export function collectCheckJsDiagnostics(program, relByAbsolute, reportOnly) {
|
|
19
|
+
if (reportOnly === undefined) {
|
|
20
|
+
return [...program.getSemanticDiagnostics(), ...program.getSyntacticDiagnostics()];
|
|
21
|
+
}
|
|
22
|
+
return program
|
|
23
|
+
.getSourceFiles()
|
|
24
|
+
.filter((sourceFile) => {
|
|
25
|
+
const rel = relByAbsolute.get(sourceFile.fileName);
|
|
26
|
+
return rel !== undefined && reportOnly.has(rel);
|
|
27
|
+
})
|
|
28
|
+
.flatMap((sourceFile) => [
|
|
29
|
+
...program.getSemanticDiagnostics(sourceFile),
|
|
30
|
+
...program.getSyntacticDiagnostics(sourceFile),
|
|
31
|
+
]);
|
|
32
|
+
}
|
|
@@ -82,6 +82,8 @@ export interface RunCheckJsGroupedInput {
|
|
|
82
82
|
* compiler options and shim in one run. See {@link runCheckJsTestFilesGrouped}.
|
|
83
83
|
*/
|
|
84
84
|
sourceFileCache?: CheckJsSourceFileCache;
|
|
85
|
+
/** When set, diagnostics are collected only for these repo-relative files. */
|
|
86
|
+
reportOnly?: ReadonlySet<string>;
|
|
85
87
|
}
|
|
86
88
|
/**
|
|
87
89
|
* Builds the checkJs program once over `resolutionOwned` and returns its
|
|
@@ -136,12 +138,19 @@ export declare function invokePatchLintCheckJs(repoDir: string, patchOwnedFiles:
|
|
|
136
138
|
* reported per program (head helpers report from their own program), and
|
|
137
139
|
* run-level errors are de-duplicated across programs.
|
|
138
140
|
*
|
|
141
|
+
* With `resolvableModules`, a test's `resource:///` and `chrome://`
|
|
142
|
+
* imports also resolve to the modules it returns for that test (the
|
|
143
|
+
* modules the queue creates up to the test's own patch), so a test that
|
|
144
|
+
* imports an earlier patch's module is typed against its real source
|
|
145
|
+
* instead of the shim's `any` wildcard. Those modules are resolution
|
|
146
|
+
* targets only: never roots, and never reported on.
|
|
147
|
+
*
|
|
139
148
|
* @param repoDir - Absolute engine (repository) directory
|
|
140
149
|
* @param testFiles - Patch-owned test-script paths (repo-relative)
|
|
141
150
|
* @param patchLint - The resolved `patchLint` config block
|
|
142
151
|
* @param projectRoot - FireForge project root for shim resolution
|
|
143
152
|
*/
|
|
144
|
-
export declare function runCheckJsTestFilesGrouped(repoDir: string, testFiles: Set<string>, patchLint: PatchLintConfig, projectRoot: string, rootScope?: ReadonlySet<string>): Promise<GroupedCheckJsResult>;
|
|
153
|
+
export declare function runCheckJsTestFilesGrouped(repoDir: string, testFiles: Set<string>, patchLint: PatchLintConfig, projectRoot: string, rootScope?: ReadonlySet<string>, resolvableModules?: (testFile: string) => ReadonlySet<string>): Promise<GroupedCheckJsResult>;
|
|
145
154
|
/**
|
|
146
155
|
* Grouped variant of {@link invokePatchLintCheckJs}: builds one queue-wide
|
|
147
156
|
* checkJs program over `patchOwnedFiles` and returns its findings grouped by
|
|
@@ -31,7 +31,9 @@ import { pathExists } from '../utils/fs.js';
|
|
|
31
31
|
import { verbose } from '../utils/logger.js';
|
|
32
32
|
import { normalizePathSlashes } from '../utils/paths.js';
|
|
33
33
|
import { withGeckoDomTypes } from './gecko-dom-types.js';
|
|
34
|
+
import { anyTypedImportHint, createModuleLiteralResolver, } from './patch-lint-checkjs-any-import.js';
|
|
34
35
|
import { withSharedSourceFiles } from './patch-lint-checkjs-cache.js';
|
|
36
|
+
import { collectCheckJsDiagnostics } from './patch-lint-checkjs-diagnostics.js';
|
|
35
37
|
import { collectUnmanagedCompanions, retargetUnmanagedCompanionHints, } from './patch-lint-unmanaged-companion.js';
|
|
36
38
|
import { composeShimSource, SHIM_FILENAME, SUPPRESSED_DIAGNOSTIC_CODES, TEST_HARNESS_SHIM, UNDEFINED_IDENTIFIER_CODES, UNDEFINED_IDENTIFIER_HINT, } from './typecheck-shim.js';
|
|
37
39
|
// ---------------------------------------------------------------------------
|
|
@@ -293,6 +295,9 @@ export async function runCheckJsGrouped(input) {
|
|
|
293
295
|
...overrides,
|
|
294
296
|
};
|
|
295
297
|
const resolveOwnedSpecifier = createOwnedSpecifierResolver(ts, ownedAbsolute);
|
|
298
|
+
// URL imports this program cannot resolve, per importing file (see
|
|
299
|
+
// patch-lint-checkjs-any-import.ts).
|
|
300
|
+
const anyTypedImports = new Map();
|
|
296
301
|
// Custom compiler host: reads patch-owned files from disk, returns
|
|
297
302
|
// the shim for the shim path, and returns empty content for
|
|
298
303
|
// anything else to avoid reading the full Firefox tree.
|
|
@@ -333,17 +338,10 @@ export async function runCheckJsGrouped(input) {
|
|
|
333
338
|
return shimSource;
|
|
334
339
|
return defaultHost.readFile(fileName);
|
|
335
340
|
},
|
|
336
|
-
resolveModuleNameLiterals(
|
|
337
|
-
return moduleLiterals.map((literal) => {
|
|
338
|
-
const owned = resolveOwnedSpecifier(literal.text);
|
|
339
|
-
if (owned)
|
|
340
|
-
return { resolvedModule: owned };
|
|
341
|
-
return { resolvedModule: resolveViaPaths?.(literal.text) };
|
|
342
|
-
});
|
|
343
|
-
},
|
|
341
|
+
resolveModuleNameLiterals: createModuleLiteralResolver(resolveOwnedSpecifier, resolveViaPaths, anyTypedImports),
|
|
344
342
|
};
|
|
345
343
|
const program = ts.createProgram(rootFiles, options, withSharedSourceFiles(host, input.sourceFileCache, shimPath, shimSource));
|
|
346
|
-
const byFile = groupOwnedDiagnostics(ts,
|
|
344
|
+
const byFile = groupOwnedDiagnostics(ts, collectCheckJsDiagnostics(program, relByAbsolute, input.reportOnly), relByAbsolute, input.mode?.undefinedIdentifiers ?? 'warning', anyTypedImports);
|
|
347
345
|
verbose(`checkJs: analyzed ${rootFiles.length - 1} file(s) across ${byFile.size} owning file(s)`);
|
|
348
346
|
return { byFile, global: [] };
|
|
349
347
|
}
|
|
@@ -354,7 +352,7 @@ export async function runCheckJsGrouped(input) {
|
|
|
354
352
|
* or shim files are dropped. Only owned files (in `relByAbsolute`) carry
|
|
355
353
|
* findings.
|
|
356
354
|
*/
|
|
357
|
-
function groupOwnedDiagnostics(ts, diagnostics, relByAbsolute, undefinedIdentifiers = 'warning') {
|
|
355
|
+
function groupOwnedDiagnostics(ts, diagnostics, relByAbsolute, undefinedIdentifiers = 'warning', anyTypedImports = new Map()) {
|
|
358
356
|
const byFile = new Map();
|
|
359
357
|
for (const diag of diagnostics) {
|
|
360
358
|
if (SUPPRESSED_DIAGNOSTIC_CODES.has(diag.code))
|
|
@@ -386,7 +384,7 @@ function groupOwnedDiagnostics(ts, diagnostics, relByAbsolute, undefinedIdentifi
|
|
|
386
384
|
check: 'checkjs-type-error',
|
|
387
385
|
message: isUndefinedIdentifier
|
|
388
386
|
? `Line ${line}: ${messageText} ${UNDEFINED_IDENTIFIER_HINT}`
|
|
389
|
-
: `Line ${line}: ${messageText}`,
|
|
387
|
+
: `Line ${line}: ${messageText}${anyTypedImportHint(diag.code, anyTypedImports.get(sourceFile.fileName))}`,
|
|
390
388
|
severity,
|
|
391
389
|
});
|
|
392
390
|
byFile.set(relPath, bucket);
|
|
@@ -451,12 +449,19 @@ export async function invokePatchLintCheckJs(repoDir, patchOwnedFiles, patchLint
|
|
|
451
449
|
* reported per program (head helpers report from their own program), and
|
|
452
450
|
* run-level errors are de-duplicated across programs.
|
|
453
451
|
*
|
|
452
|
+
* With `resolvableModules`, a test's `resource:///` and `chrome://`
|
|
453
|
+
* imports also resolve to the modules it returns for that test (the
|
|
454
|
+
* modules the queue creates up to the test's own patch), so a test that
|
|
455
|
+
* imports an earlier patch's module is typed against its real source
|
|
456
|
+
* instead of the shim's `any` wildcard. Those modules are resolution
|
|
457
|
+
* targets only: never roots, and never reported on.
|
|
458
|
+
*
|
|
454
459
|
* @param repoDir - Absolute engine (repository) directory
|
|
455
460
|
* @param testFiles - Patch-owned test-script paths (repo-relative)
|
|
456
461
|
* @param patchLint - The resolved `patchLint` config block
|
|
457
462
|
* @param projectRoot - FireForge project root for shim resolution
|
|
458
463
|
*/
|
|
459
|
-
export async function runCheckJsTestFilesGrouped(repoDir, testFiles, patchLint, projectRoot, rootScope) {
|
|
464
|
+
export async function runCheckJsTestFilesGrouped(repoDir, testFiles, patchLint, projectRoot, rootScope, resolvableModules) {
|
|
460
465
|
const merged = { byFile: new Map(), global: [] };
|
|
461
466
|
if (testFiles.size === 0)
|
|
462
467
|
return merged;
|
|
@@ -487,7 +492,9 @@ export async function runCheckJsTestFilesGrouped(repoDir, testFiles, patchLint,
|
|
|
487
492
|
}
|
|
488
493
|
const result = await runCheckJsGrouped({
|
|
489
494
|
repoDir,
|
|
490
|
-
resolutionOwned: roots,
|
|
495
|
+
resolutionOwned: new Set([...roots, ...(resolvableModules?.(file) ?? [])]),
|
|
496
|
+
rootScope: roots,
|
|
497
|
+
reportOnly: new Set([file]),
|
|
491
498
|
...(patchLint.checkJsTestShim !== undefined
|
|
492
499
|
? { extraShimPath: patchLint.checkJsTestShim }
|
|
493
500
|
: {}),
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Line counting for the size rules: raw lines, code lines, and the per-line
|
|
3
|
+
* code mask the `addedCode` patch-size metric reads off a file's
|
|
4
|
+
* post-image.
|
|
5
|
+
*
|
|
6
|
+
* "Code" means a line left non-blank once comments are blanked. JS goes
|
|
7
|
+
* through acorn's tokenizer (`stripJsCommentsParsed`), so a regex literal
|
|
8
|
+
* containing `/*`, a string containing `//`, nested template literals,
|
|
9
|
+
* JSDoc and a shebang are all judged correctly, and a blank line inside a
|
|
10
|
+
* template literal counts as blank.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Counts the lines of `content` the way `wc -l` reports them. A naive
|
|
14
|
+
* `split('\n').length` over-counts by one for any content ending in `\n`
|
|
15
|
+
* (the common case), making the size rules fire one line early against
|
|
16
|
+
* the operator's own `wc -l` measurement.
|
|
17
|
+
*/
|
|
18
|
+
export declare function countRawLines(content: string): number;
|
|
19
|
+
/** The result of {@link countCodeLines}. */
|
|
20
|
+
export interface CodeLineCount {
|
|
21
|
+
/**
|
|
22
|
+
* Lines that carry code: non-blank once comments are blanked. When the
|
|
23
|
+
* source could not be tokenized this is the raw line count instead, the
|
|
24
|
+
* upper bound, so an unparsable file never measures smaller than it is.
|
|
25
|
+
*/
|
|
26
|
+
lines: number;
|
|
27
|
+
/** False when acorn could tokenize the source neither as a module nor as a script. */
|
|
28
|
+
parsed: boolean;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Counts the code lines of a JS source: comments are blanked by acorn's
|
|
32
|
+
* tokenizer (module goal first, then script, since chrome subscripts are
|
|
33
|
+
* scripts) and the non-blank lines are counted. When neither goal
|
|
34
|
+
* tokenizes, the raw line count is returned with `parsed: false`. A regex
|
|
35
|
+
* fallback would under-count, which fails open.
|
|
36
|
+
*
|
|
37
|
+
* @param content - JS source text
|
|
38
|
+
*/
|
|
39
|
+
export declare function countCodeLines(content: string): CodeLineCount;
|
|
40
|
+
/** The per-line code mask of one post-image. */
|
|
41
|
+
export interface CodeLineMask {
|
|
42
|
+
/** `code[i]` is true when line `i + 1` carries code. */
|
|
43
|
+
code: boolean[];
|
|
44
|
+
/** False for a JS file acorn could not tokenize; every non-blank line then counts. */
|
|
45
|
+
parsed: boolean;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Classifies every line of a file's post-image as code or not, by file
|
|
49
|
+
* kind: JS through acorn, CSS block comments, `<!-- -->` in markup, and
|
|
50
|
+
* whole-line `#` comments (`;` for `.ini`/`.in`, `!` for `.properties`) in
|
|
51
|
+
* Fluent, manifests, `moz.build` and similar. Any other file counts every
|
|
52
|
+
* non-blank line. In CSS, lines inside a Furnace fragment expansion
|
|
53
|
+
* (`@fireforge-include` … `@fireforge-end-include`) are not code of this
|
|
54
|
+
* file: they are a copy of a shared fragment.
|
|
55
|
+
*
|
|
56
|
+
* @param file - Engine-relative path, used only to pick the file kind
|
|
57
|
+
* @param content - The post-image text
|
|
58
|
+
*/
|
|
59
|
+
export declare function codeLineMask(file: string, content: string): CodeLineMask;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
/**
|
|
3
|
+
* Line counting for the size rules: raw lines, code lines, and the per-line
|
|
4
|
+
* code mask the `addedCode` patch-size metric reads off a file's
|
|
5
|
+
* post-image.
|
|
6
|
+
*
|
|
7
|
+
* "Code" means a line left non-blank once comments are blanked. JS goes
|
|
8
|
+
* through acorn's tokenizer (`stripJsCommentsParsed`), so a regex literal
|
|
9
|
+
* containing `/*`, a string containing `//`, nested template literals,
|
|
10
|
+
* JSDoc and a shebang are all judged correctly, and a blank line inside a
|
|
11
|
+
* template literal counts as blank.
|
|
12
|
+
*/
|
|
13
|
+
import { stripJsCommentsParsed } from '../utils/regex.js';
|
|
14
|
+
import { expandedFragmentLineMask } from './furnace-css-fragments.js';
|
|
15
|
+
import { maskCssComments } from './patch-lint-css.js';
|
|
16
|
+
/**
|
|
17
|
+
* Splits content into lines the way `wc -l` reports them: a trailing
|
|
18
|
+
* newline terminates the last line rather than starting an empty extra one.
|
|
19
|
+
*/
|
|
20
|
+
function splitContentLines(content) {
|
|
21
|
+
const lines = content.split('\n');
|
|
22
|
+
if (lines[lines.length - 1] === '')
|
|
23
|
+
lines.pop();
|
|
24
|
+
return lines;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Counts the lines of `content` the way `wc -l` reports them. A naive
|
|
28
|
+
* `split('\n').length` over-counts by one for any content ending in `\n`
|
|
29
|
+
* (the common case), making the size rules fire one line early against
|
|
30
|
+
* the operator's own `wc -l` measurement.
|
|
31
|
+
*/
|
|
32
|
+
export function countRawLines(content) {
|
|
33
|
+
return splitContentLines(content).length;
|
|
34
|
+
}
|
|
35
|
+
const isBlank = (line) => line.trim() === '';
|
|
36
|
+
/**
|
|
37
|
+
* Counts the code lines of a JS source: comments are blanked by acorn's
|
|
38
|
+
* tokenizer (module goal first, then script, since chrome subscripts are
|
|
39
|
+
* scripts) and the non-blank lines are counted. When neither goal
|
|
40
|
+
* tokenizes, the raw line count is returned with `parsed: false`. A regex
|
|
41
|
+
* fallback would under-count, which fails open.
|
|
42
|
+
*
|
|
43
|
+
* @param content - JS source text
|
|
44
|
+
*/
|
|
45
|
+
export function countCodeLines(content) {
|
|
46
|
+
const stripped = stripJsCommentsParsed(content);
|
|
47
|
+
if (stripped === null)
|
|
48
|
+
return { lines: countRawLines(content), parsed: false };
|
|
49
|
+
return {
|
|
50
|
+
lines: splitContentLines(stripped).filter((line) => !isBlank(line)).length,
|
|
51
|
+
parsed: true,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
const JS_FILE = /\.(?:m?js|jsm|cjs)$/;
|
|
55
|
+
const MARKUP_FILE = /\.(?:x?html|xml|svg|xul|dtd)$/;
|
|
56
|
+
const HASH_COMMENT_FILE = /(?:\.(?:ftl|properties|toml|ini|mn|build|py|conf|configure|sh|ya?ml|in|cfg|mozbuild)|(?:^|\/)(?:Makefile|mozconfig))$/;
|
|
57
|
+
/** Line-comment leaders per hash-comment file kind. */
|
|
58
|
+
function lineCommentPattern(file) {
|
|
59
|
+
if (/\.(?:ini|in)$/.test(file))
|
|
60
|
+
return /^\s*[#;]/;
|
|
61
|
+
if (file.endsWith('.properties'))
|
|
62
|
+
return /^\s*[#!]/;
|
|
63
|
+
return /^\s*#/;
|
|
64
|
+
}
|
|
65
|
+
/** Masks `<!-- … -->` comments, keeping newlines. Unclosed comments run to EOF. */
|
|
66
|
+
function maskMarkupComments(source) {
|
|
67
|
+
return source.replace(/<!--[\s\S]*?(?:-->|$)/g, (m) => m.replace(/[^\n]/g, ' '));
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Classifies every line of a file's post-image as code or not, by file
|
|
71
|
+
* kind: JS through acorn, CSS block comments, `<!-- -->` in markup, and
|
|
72
|
+
* whole-line `#` comments (`;` for `.ini`/`.in`, `!` for `.properties`) in
|
|
73
|
+
* Fluent, manifests, `moz.build` and similar. Any other file counts every
|
|
74
|
+
* non-blank line. In CSS, lines inside a Furnace fragment expansion
|
|
75
|
+
* (`@fireforge-include` … `@fireforge-end-include`) are not code of this
|
|
76
|
+
* file: they are a copy of a shared fragment.
|
|
77
|
+
*
|
|
78
|
+
* @param file - Engine-relative path, used only to pick the file kind
|
|
79
|
+
* @param content - The post-image text
|
|
80
|
+
*/
|
|
81
|
+
export function codeLineMask(file, content) {
|
|
82
|
+
if (JS_FILE.test(file)) {
|
|
83
|
+
const stripped = stripJsCommentsParsed(content);
|
|
84
|
+
const source = stripped ?? content;
|
|
85
|
+
return { code: source.split('\n').map((line) => !isBlank(line)), parsed: stripped !== null };
|
|
86
|
+
}
|
|
87
|
+
if (file.endsWith('.css')) {
|
|
88
|
+
const inFragment = expandedFragmentLineMask(content);
|
|
89
|
+
const code = maskCssComments(content)
|
|
90
|
+
.split('\n')
|
|
91
|
+
.map((line, i) => !isBlank(line) && inFragment[i] !== true);
|
|
92
|
+
return { code, parsed: true };
|
|
93
|
+
}
|
|
94
|
+
if (MARKUP_FILE.test(file)) {
|
|
95
|
+
return {
|
|
96
|
+
code: maskMarkupComments(content)
|
|
97
|
+
.split('\n')
|
|
98
|
+
.map((l) => !isBlank(l)),
|
|
99
|
+
parsed: true,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
const comment = HASH_COMMENT_FILE.test(file) ? lineCommentPattern(file) : undefined;
|
|
103
|
+
const code = content.split('\n').map((line) => !isBlank(line) && !comment?.test(line));
|
|
104
|
+
return { code, parsed: true };
|
|
105
|
+
}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* module.
|
|
11
11
|
*/
|
|
12
12
|
import type { PatchLintIssue, PatchMetadata } from '../types/commands/index.js';
|
|
13
|
-
import type { FireForgeConfig, PatchPolicyConfig } from '../types/config.js';
|
|
13
|
+
import type { FireForgeConfig, PatchLintTokenScale, PatchPolicyConfig } from '../types/config.js';
|
|
14
14
|
import type { ForwardRegistrationScope } from './patch-lint-forward-registration-extended.js';
|
|
15
15
|
/**
|
|
16
16
|
* One patch's contribution to {@link PatchQueueContext}.
|
|
@@ -82,6 +82,8 @@ export interface PatchQueueContext {
|
|
|
82
82
|
* `patchLint.forwardRegistration`. Absent = `support-files` only.
|
|
83
83
|
*/
|
|
84
84
|
forwardRegistration?: ForwardRegistrationScope;
|
|
85
|
+
/** `patchLint.tokenScales`, for the scales' `minFiles` floors. */
|
|
86
|
+
tokenScales?: PatchLintTokenScale[];
|
|
85
87
|
}
|
|
86
88
|
/**
|
|
87
89
|
* Builds a {@link PatchQueueContext} by reading every .patch file in the
|