@hominis/fireforge 0.43.1 → 0.44.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 +153 -0
- package/README.md +3 -3
- package/dist/bin/fireforge.d.ts +4 -9
- package/dist/bin/fireforge.js +42 -40
- package/dist/build-info.json +4 -4
- package/dist/src/cli.js +74 -8
- package/dist/src/commands/bootstrap.js +17 -20
- package/dist/src/commands/build.js +25 -32
- package/dist/src/commands/config.js +34 -41
- package/dist/src/commands/discard.js +8 -9
- package/dist/src/commands/doctor-check-core.d.ts +13 -18
- package/dist/src/commands/doctor-check-core.js +8 -35
- package/dist/src/commands/doctor-external-toolchains.js +2 -2
- package/dist/src/commands/doctor-furnace-config-sync.d.ts +18 -0
- package/dist/src/commands/{doctor-furnace-manifest-sync.js → doctor-furnace-config-sync.js} +27 -26
- package/dist/src/commands/doctor-furnace-jar.d.ts +7 -9
- package/dist/src/commands/doctor-furnace-jar.js +7 -9
- package/dist/src/commands/doctor-furnace.js +21 -24
- package/dist/src/commands/doctor-orphaned-harness.d.ts +16 -20
- package/dist/src/commands/doctor-orphaned-harness.js +18 -44
- package/dist/src/commands/doctor-patch-manifest.d.ts +8 -0
- package/dist/src/commands/doctor-patch-manifest.js +155 -0
- package/dist/src/commands/doctor-post-rebase-audit.d.ts +2 -0
- package/dist/src/commands/{doctor/post-rebase-audit.js → doctor-post-rebase-audit.js} +3 -3
- package/dist/src/commands/doctor-working-tree.d.ts +10 -12
- package/dist/src/commands/doctor-working-tree.js +11 -18
- package/dist/src/commands/doctor.d.ts +1 -1
- package/dist/src/commands/doctor.js +64 -96
- package/dist/src/commands/download.js +32 -48
- package/dist/src/commands/export-all.js +29 -33
- package/dist/src/commands/export-flow.js +6 -6
- package/dist/src/commands/export-placement-conflicts.js +10 -9
- package/dist/src/commands/export-placement-gate.js +5 -5
- package/dist/src/commands/export-shared.d.ts +30 -33
- package/dist/src/commands/export-shared.js +45 -43
- package/dist/src/commands/export.js +21 -27
- package/dist/src/commands/furnace/apply.js +14 -23
- package/dist/src/commands/furnace/chrome-doc-remove.js +14 -21
- package/dist/src/commands/furnace/chrome-doc-templates.d.ts +23 -23
- package/dist/src/commands/furnace/chrome-doc-templates.js +23 -23
- package/dist/src/commands/furnace/chrome-doc-tests.js +26 -29
- package/dist/src/commands/furnace/chrome-doc.d.ts +16 -17
- package/dist/src/commands/furnace/chrome-doc.js +31 -41
- package/dist/src/commands/furnace/create-browser-test.d.ts +4 -4
- package/dist/src/commands/furnace/create-browser-test.js +8 -8
- package/dist/src/commands/furnace/create-mochikit.d.ts +6 -7
- package/dist/src/commands/furnace/create-mochikit.js +8 -9
- package/dist/src/commands/furnace/create-readback.d.ts +12 -13
- package/dist/src/commands/furnace/create-readback.js +12 -13
- package/dist/src/commands/furnace/create-templates.d.ts +22 -28
- package/dist/src/commands/furnace/create-templates.js +35 -30
- package/dist/src/commands/furnace/create-xpcshell.js +2 -2
- package/dist/src/commands/furnace/create.js +33 -23
- package/dist/src/commands/furnace/deploy.js +16 -24
- package/dist/src/commands/furnace/diff.js +15 -10
- package/dist/src/commands/furnace/init.js +33 -36
- package/dist/src/commands/furnace/override.js +23 -25
- package/dist/src/commands/furnace/preview.js +47 -67
- package/dist/src/commands/furnace/refresh.js +12 -16
- package/dist/src/commands/furnace/remove-mutations.d.ts +3 -6
- package/dist/src/commands/furnace/remove-mutations.js +14 -17
- package/dist/src/commands/furnace/remove-state.js +1 -1
- package/dist/src/commands/furnace/remove.js +33 -38
- package/dist/src/commands/furnace/rename-xpcshell.d.ts +8 -11
- package/dist/src/commands/furnace/rename-xpcshell.js +8 -11
- package/dist/src/commands/furnace/rename.js +59 -69
- package/dist/src/commands/furnace/scan.js +19 -33
- package/dist/src/commands/furnace/status.js +12 -9
- package/dist/src/commands/furnace/sync.js +9 -16
- package/dist/src/commands/furnace/validate.js +20 -20
- package/dist/src/commands/import.js +48 -37
- package/dist/src/commands/lint-per-patch.js +15 -10
- package/dist/src/commands/lint-per-run-checkjs.d.ts +13 -13
- package/dist/src/commands/lint-per-run-checkjs.js +13 -13
- package/dist/src/commands/lint-report.js +6 -7
- package/dist/src/commands/lint.d.ts +15 -16
- package/dist/src/commands/lint.js +86 -102
- package/dist/src/commands/package.js +6 -11
- package/dist/src/commands/patch/compact.js +1 -1
- package/dist/src/commands/patch/delete.js +24 -33
- package/dist/src/commands/patch/index.d.ts +5 -6
- package/dist/src/commands/patch/index.js +10 -12
- package/dist/src/commands/patch/lint-ignore.js +14 -13
- package/dist/src/commands/patch/move-files-create.d.ts +6 -6
- package/dist/src/commands/patch/move-files-create.js +8 -8
- package/dist/src/commands/patch/move-files-into.d.ts +6 -6
- package/dist/src/commands/patch/move-files-into.js +8 -8
- package/dist/src/commands/patch/patch-context.d.ts +2 -3
- package/dist/src/commands/patch/patch-context.js +2 -3
- package/dist/src/commands/patch/rename.d.ts +10 -11
- package/dist/src/commands/patch/rename.js +11 -12
- package/dist/src/commands/patch/reorder.js +8 -9
- package/dist/src/commands/patch/split-plan.js +1 -1
- package/dist/src/commands/patch/split.d.ts +8 -10
- package/dist/src/commands/patch/split.js +9 -11
- package/dist/src/commands/patch/staged-dependency-validate.js +8 -8
- package/dist/src/commands/patch/staged-dependency.js +7 -3
- package/dist/src/commands/patch/tier.d.ts +9 -9
- package/dist/src/commands/patch/tier.js +18 -15
- package/dist/src/commands/re-export-adjacent.js +9 -8
- package/dist/src/commands/re-export-bulk-scan.d.ts +9 -9
- package/dist/src/commands/re-export-bulk-scan.js +22 -21
- package/dist/src/commands/re-export-drift.js +10 -10
- package/dist/src/commands/re-export-files.d.ts +6 -7
- package/dist/src/commands/re-export-files.js +34 -44
- package/dist/src/commands/re-export-lint.d.ts +10 -13
- package/dist/src/commands/re-export-lint.js +16 -14
- package/dist/src/commands/re-export-options.d.ts +6 -6
- package/dist/src/commands/re-export-options.js +6 -6
- package/dist/src/commands/re-export-register.d.ts +4 -10
- package/dist/src/commands/re-export-register.js +5 -11
- package/dist/src/commands/re-export-scan.js +1 -1
- package/dist/src/commands/re-export-single.d.ts +3 -3
- package/dist/src/commands/re-export-single.js +33 -25
- package/dist/src/commands/re-export.js +13 -21
- package/dist/src/commands/rebase/abort.js +3 -3
- package/dist/src/commands/rebase/confirm.js +2 -1
- package/dist/src/commands/rebase/continue.d.ts +1 -1
- package/dist/src/commands/rebase/continue.js +14 -9
- package/dist/src/commands/rebase/index.js +11 -11
- package/dist/src/commands/rebase/patch-loop.d.ts +7 -1
- package/dist/src/commands/rebase/patch-loop.js +60 -39
- package/dist/src/commands/rebase/summary.js +1 -1
- package/dist/src/commands/register.js +5 -7
- package/dist/src/commands/reset.js +2 -1
- package/dist/src/commands/resolve.d.ts +16 -13
- package/dist/src/commands/resolve.js +30 -33
- package/dist/src/commands/run.js +33 -35
- package/dist/src/commands/setup-support.js +15 -19
- package/dist/src/commands/setup.js +13 -9
- package/dist/src/commands/status-check.d.ts +6 -6
- package/dist/src/commands/status-json.d.ts +6 -6
- package/dist/src/commands/status-json.js +5 -0
- package/dist/src/commands/status-output.d.ts +5 -5
- package/dist/src/commands/status-output.js +6 -6
- package/dist/src/commands/status-ownership.d.ts +16 -14
- package/dist/src/commands/status-ownership.js +16 -14
- package/dist/src/commands/status.js +42 -34
- package/dist/src/commands/test-build-phase.js +26 -13
- package/dist/src/commands/test-diagnose.js +44 -44
- package/dist/src/commands/test-register.js +1 -0
- package/dist/src/commands/test-run.d.ts +14 -16
- package/dist/src/commands/test-run.js +21 -13
- package/dist/src/commands/test-stale-gate.d.ts +15 -16
- package/dist/src/commands/test-stale-gate.js +15 -16
- package/dist/src/commands/test-verdict.d.ts +20 -3
- package/dist/src/commands/test-verdict.js +30 -0
- package/dist/src/commands/test.js +83 -76
- package/dist/src/commands/token-coverage.js +3 -4
- package/dist/src/commands/token.js +16 -18
- package/dist/src/commands/tree.js +47 -31
- package/dist/src/commands/typecheck.d.ts +10 -12
- package/dist/src/commands/typecheck.js +24 -27
- package/dist/src/commands/verify.js +13 -15
- package/dist/src/commands/watch.js +21 -23
- package/dist/src/commands/wire.js +52 -62
- package/dist/src/core/ast-utils.d.ts +8 -7
- package/dist/src/core/ast-utils.js +8 -7
- package/dist/src/core/branding.d.ts +9 -14
- package/dist/src/core/branding.js +7 -11
- package/dist/src/core/browser-wire.d.ts +1 -1
- package/dist/src/core/browser-wire.js +14 -19
- package/dist/src/core/build-audit-platform.js +25 -33
- package/dist/src/core/build-audit-registration.js +17 -25
- package/dist/src/core/build-audit-resolve.d.ts +15 -17
- package/dist/src/core/build-audit-resolve.js +39 -36
- package/dist/src/core/build-audit-transforms.js +18 -19
- package/dist/src/core/build-audit.js +28 -42
- package/dist/src/core/build-baseline-types.d.ts +29 -35
- package/dist/src/core/build-baseline.d.ts +5 -4
- package/dist/src/core/build-baseline.js +14 -14
- package/dist/src/core/build-overwrite-guard.d.ts +7 -14
- package/dist/src/core/build-overwrite-guard.js +17 -27
- package/dist/src/core/build-prepare.d.ts +2 -2
- package/dist/src/core/build-prepare.js +8 -9
- package/dist/src/core/config-mutate.js +20 -19
- package/dist/src/core/config-state.js +12 -4
- package/dist/src/core/config-validate.js +8 -5
- package/dist/src/core/config.d.ts +5 -8
- package/dist/src/core/config.js +7 -16
- package/dist/src/core/coverage-extend.d.ts +15 -13
- package/dist/src/core/coverage-extend.js +15 -13
- package/dist/src/core/destructive.d.ts +31 -9
- package/dist/src/core/destructive.js +29 -26
- package/dist/src/core/diff-hunks.js +10 -12
- package/dist/src/core/discard-baseline.d.ts +8 -8
- package/dist/src/core/discard-baseline.js +16 -15
- package/dist/src/core/display-state.d.ts +12 -14
- package/dist/src/core/display-state.js +12 -14
- package/dist/src/core/engine-changes.d.ts +2 -4
- package/dist/src/core/engine-changes.js +2 -4
- package/dist/src/core/engine-precondition.d.ts +28 -13
- package/dist/src/core/engine-precondition.js +25 -10
- package/dist/src/core/engine-session-lock.d.ts +47 -21
- package/dist/src/core/engine-session-lock.js +168 -33
- package/dist/src/core/export-moved-code-shape.d.ts +10 -10
- package/dist/src/core/export-moved-code-shape.js +10 -10
- package/dist/src/core/file-lock.d.ts +62 -5
- package/dist/src/core/file-lock.js +196 -59
- package/dist/src/core/firefox-cache.js +1 -3
- package/dist/src/core/firefox-extract.js +10 -14
- package/dist/src/core/firefox.d.ts +7 -5
- package/dist/src/core/firefox.js +4 -5
- package/dist/src/core/furnace-apply-dry-run.d.ts +2 -2
- package/dist/src/core/furnace-apply-dry-run.js +3 -2
- package/dist/src/core/furnace-apply-ftl.d.ts +7 -9
- package/dist/src/core/furnace-apply-ftl.js +16 -13
- package/dist/src/core/furnace-apply-helpers.d.ts +7 -7
- package/dist/src/core/furnace-apply-helpers.js +30 -21
- package/dist/src/core/furnace-apply-overwrite-warn.d.ts +8 -9
- package/dist/src/core/furnace-apply-overwrite-warn.js +8 -9
- package/dist/src/core/furnace-apply-undeploy-actions.d.ts +3 -4
- package/dist/src/core/furnace-apply-undeploy-actions.js +3 -4
- package/dist/src/core/furnace-apply.d.ts +5 -8
- package/dist/src/core/furnace-apply.js +19 -24
- package/dist/src/core/furnace-checksum-utils.d.ts +14 -0
- package/dist/src/core/furnace-checksum-utils.js +16 -0
- package/dist/src/core/furnace-config.d.ts +21 -30
- package/dist/src/core/furnace-config.js +32 -54
- package/dist/src/core/furnace-constants.d.ts +8 -0
- package/dist/src/core/furnace-constants.js +10 -2
- package/dist/src/core/furnace-css-fragments.d.ts +5 -5
- package/dist/src/core/furnace-css-fragments.js +5 -5
- package/dist/src/core/furnace-jsconfig.d.ts +11 -12
- package/dist/src/core/furnace-jsconfig.js +11 -12
- package/dist/src/core/furnace-marker.d.ts +7 -8
- package/dist/src/core/furnace-marker.js +7 -8
- package/dist/src/core/furnace-operation.d.ts +31 -0
- package/dist/src/core/furnace-operation.js +54 -17
- package/dist/src/core/furnace-precondition.d.ts +61 -0
- package/dist/src/core/furnace-precondition.js +67 -0
- package/dist/src/core/furnace-registration-remove.d.ts +5 -6
- package/dist/src/core/furnace-registration-remove.js +6 -7
- package/dist/src/core/furnace-registration-validate.d.ts +13 -0
- package/dist/src/core/furnace-registration-validate.js +20 -1
- package/dist/src/core/furnace-registration.d.ts +5 -6
- package/dist/src/core/furnace-registration.js +10 -12
- package/dist/src/core/furnace-rollback.js +7 -7
- package/dist/src/core/furnace-scanner.d.ts +1 -0
- package/dist/src/core/furnace-scanner.js +1 -2
- package/dist/src/core/furnace-stale-export.d.ts +10 -10
- package/dist/src/core/furnace-stale-export.js +10 -10
- package/dist/src/core/furnace-state-persist.d.ts +6 -8
- package/dist/src/core/furnace-state-persist.js +6 -8
- package/dist/src/core/furnace-validate-accessibility.d.ts +22 -0
- package/dist/src/core/furnace-validate-accessibility.js +310 -1
- package/dist/src/core/furnace-validate-compatibility.js +141 -1
- package/dist/src/core/furnace-validate-helpers.d.ts +5 -116
- package/dist/src/core/furnace-validate-helpers.js +0 -491
- package/dist/src/core/furnace-validate-registration.d.ts +7 -0
- package/dist/src/core/furnace-validate-registration.js +115 -41
- package/dist/src/core/furnace-validate.d.ts +16 -0
- package/dist/src/core/furnace-validate.js +188 -145
- package/dist/src/core/furnace-version-drift.d.ts +10 -11
- package/dist/src/core/furnace-version-drift.js +10 -11
- package/dist/src/core/git-base.d.ts +21 -9
- package/dist/src/core/git-base.js +24 -9
- package/dist/src/core/git-diff.d.ts +20 -9
- package/dist/src/core/git-diff.js +148 -63
- package/dist/src/core/git-file-ops.d.ts +19 -19
- package/dist/src/core/git-file-ops.js +19 -19
- package/dist/src/core/git-readonly-index.d.ts +53 -19
- package/dist/src/core/git-readonly-index.js +75 -31
- package/dist/src/core/git-status.d.ts +5 -6
- package/dist/src/core/git-status.js +5 -6
- package/dist/src/core/git.d.ts +9 -10
- package/dist/src/core/git.js +57 -71
- package/dist/src/core/license-headers.d.ts +17 -23
- package/dist/src/core/license-headers.js +17 -23
- package/dist/src/core/mach-build-artifacts.d.ts +9 -9
- package/dist/src/core/mach-build-artifacts.js +57 -19
- package/dist/src/core/mach-error-hints.js +42 -29
- package/dist/src/core/mach-known-noise-filter.d.ts +15 -16
- package/dist/src/core/mach-known-noise-filter.js +18 -20
- package/dist/src/core/mach-mozconfig.d.ts +14 -0
- package/dist/src/core/mach-mozconfig.js +30 -0
- package/dist/src/core/mach-resource-shim.d.ts +43 -58
- package/dist/src/core/mach-resource-shim.js +50 -67
- package/dist/src/core/mach.d.ts +37 -41
- package/dist/src/core/mach.js +50 -51
- package/dist/src/core/marionette-port.d.ts +36 -1
- package/dist/src/core/marionette-port.js +96 -31
- package/dist/src/core/marionette-preflight.d.ts +8 -12
- package/dist/src/core/marionette-preflight.js +86 -52
- package/dist/src/core/mochitest-server-port.d.ts +42 -0
- package/dist/src/core/mochitest-server-port.js +119 -0
- package/dist/src/core/module-resolution-preflight.d.ts +9 -11
- package/dist/src/core/module-resolution-preflight.js +9 -11
- package/dist/src/core/moz-manifest-helpers.d.ts +79 -0
- package/dist/src/core/moz-manifest-helpers.js +163 -0
- package/dist/src/core/{manifest-register.d.ts → moz-manifest-register.d.ts} +1 -1
- package/dist/src/core/{manifest-register.js → moz-manifest-register.js} +13 -28
- package/dist/src/core/{manifest-rules.d.ts → moz-manifest-rules.d.ts} +10 -1
- package/dist/src/core/{manifest-rules.js → moz-manifest-rules.js} +31 -24
- package/dist/src/core/{manifest-tokenizers.d.ts → moz-manifest-tokenizers.d.ts} +3 -5
- package/dist/src/core/{manifest-tokenizers.js → moz-manifest-tokenizers.js} +9 -12
- package/dist/src/core/ownership-table.d.ts +14 -16
- package/dist/src/core/ownership-table.js +14 -16
- package/dist/src/core/parser-fallback.d.ts +15 -1
- package/dist/src/core/parser-fallback.js +22 -3
- package/dist/src/core/patch-apply-fuzz.d.ts +10 -12
- package/dist/src/core/patch-apply-fuzz.js +15 -18
- package/dist/src/core/patch-apply.d.ts +13 -34
- package/dist/src/core/patch-apply.js +16 -76
- package/dist/src/core/patch-artifact-normalize.d.ts +13 -15
- package/dist/src/core/patch-artifact-normalize.js +13 -15
- package/dist/src/core/patch-export-metadata.d.ts +12 -2
- package/dist/src/core/patch-export-metadata.js +13 -4
- package/dist/src/core/patch-export-update.d.ts +13 -1
- package/dist/src/core/patch-export-update.js +25 -8
- package/dist/src/core/patch-export.d.ts +15 -8
- package/dist/src/core/patch-export.js +10 -11
- package/dist/src/core/patch-files.d.ts +5 -6
- package/dist/src/core/patch-files.js +5 -6
- package/dist/src/core/patch-identifier-suggest.d.ts +7 -12
- package/dist/src/core/patch-identifier-suggest.js +14 -19
- package/dist/src/core/patch-lint-binary.d.ts +51 -0
- package/dist/src/core/patch-lint-binary.js +39 -0
- package/dist/src/core/{lint-cache.d.ts → patch-lint-cache.d.ts} +5 -5
- package/dist/src/core/{lint-cache.js → patch-lint-cache.js} +21 -23
- package/dist/src/core/patch-lint-checkjs.d.ts +16 -16
- package/dist/src/core/patch-lint-checkjs.js +41 -20
- package/dist/src/core/patch-lint-chrome-jsdoc.d.ts +6 -9
- package/dist/src/core/patch-lint-chrome-jsdoc.js +10 -14
- package/dist/src/core/patch-lint-creators.d.ts +8 -8
- package/dist/src/core/patch-lint-creators.js +8 -8
- package/dist/src/core/patch-lint-cross.d.ts +17 -20
- package/dist/src/core/patch-lint-cross.js +16 -16
- package/dist/src/core/patch-lint-css.d.ts +3 -5
- package/dist/src/core/patch-lint-css.js +17 -22
- package/dist/src/core/patch-lint-diff-tag.d.ts +14 -16
- package/dist/src/core/patch-lint-diff-tag.js +14 -16
- package/dist/src/core/patch-lint-jsdoc.d.ts +7 -8
- package/dist/src/core/patch-lint-jsdoc.js +26 -19
- package/dist/src/core/patch-lint-mozbuild.js +20 -20
- package/dist/src/core/patch-lint-observer.d.ts +7 -7
- package/dist/src/core/patch-lint-observer.js +7 -7
- package/dist/src/core/patch-lint.d.ts +38 -29
- package/dist/src/core/patch-lint.js +89 -121
- package/dist/src/core/patch-lock.d.ts +1 -1
- package/dist/src/core/patch-lock.js +45 -9
- package/dist/src/core/patch-manifest-consistency.d.ts +57 -6
- package/dist/src/core/patch-manifest-consistency.js +111 -40
- package/dist/src/core/patch-manifest-files-affected.d.ts +43 -0
- package/dist/src/core/patch-manifest-files-affected.js +77 -0
- package/dist/src/core/patch-manifest-io.js +14 -18
- package/dist/src/core/patch-manifest-resolve.d.ts +9 -12
- package/dist/src/core/patch-manifest-resolve.js +9 -12
- package/dist/src/core/patch-manifest-validate.d.ts +6 -1
- package/dist/src/core/patch-manifest-validate.js +25 -13
- package/dist/src/core/patch-manifest.d.ts +2 -1
- package/dist/src/core/patch-manifest.js +2 -1
- package/dist/src/core/patch-parse.d.ts +24 -13
- package/dist/src/core/patch-parse.js +19 -14
- package/dist/src/core/patch-policy.d.ts +2 -2
- package/dist/src/core/patch-policy.js +2 -2
- package/dist/src/core/patch-registration-refs.d.ts +7 -8
- package/dist/src/core/patch-registration-refs.js +9 -9
- package/dist/src/core/process-cpu-time.d.ts +12 -0
- package/dist/src/core/process-cpu-time.js +52 -0
- package/dist/src/core/rebase-session.d.ts +38 -26
- package/dist/src/core/rebase-session.js +55 -28
- package/dist/src/core/register-browser-content.js +9 -74
- package/dist/src/core/{register-test-manifest.js → register-browser-test.js} +7 -42
- package/dist/src/core/register-module.js +10 -43
- package/dist/src/core/register-scaffold.d.ts +8 -8
- package/dist/src/core/register-scaffold.js +10 -10
- package/dist/src/core/register-shared-css.d.ts +9 -12
- package/dist/src/core/register-shared-css.js +17 -87
- package/dist/src/core/register-xpcshell-test.d.ts +6 -7
- package/dist/src/core/register-xpcshell-test.js +7 -8
- package/dist/src/core/shared-ftl.js +12 -4
- package/dist/src/core/state-file.d.ts +45 -0
- package/dist/src/core/state-file.js +34 -0
- package/dist/src/core/status-binary.d.ts +18 -11
- package/dist/src/core/status-binary.js +19 -12
- package/dist/src/core/status-classify.d.ts +30 -36
- package/dist/src/core/status-classify.js +21 -26
- package/dist/src/core/test-changed-prefs.d.ts +30 -0
- package/dist/src/core/test-changed-prefs.js +78 -0
- package/dist/src/core/test-harness-crash.d.ts +25 -63
- package/dist/src/core/test-harness-crash.js +121 -142
- package/dist/src/core/test-harness-signature.d.ts +18 -0
- package/dist/src/core/test-harness-signature.js +13 -0
- package/dist/src/core/test-path-scope.d.ts +12 -15
- package/dist/src/core/test-path-scope.js +15 -18
- package/dist/src/core/test-stale-check.d.ts +17 -17
- package/dist/src/core/test-stale-check.js +50 -43
- package/dist/src/core/test-stall-triage.d.ts +51 -0
- package/dist/src/core/test-stall-triage.js +126 -0
- package/dist/src/core/token-category.js +66 -14
- package/dist/src/core/token-coverage.js +9 -9
- package/dist/src/core/token-dark-mode.d.ts +9 -11
- package/dist/src/core/token-dark-mode.js +29 -13
- package/dist/src/core/token-docs.d.ts +2 -0
- package/dist/src/core/token-docs.js +3 -1
- package/dist/src/core/token-manager.d.ts +10 -2
- package/dist/src/core/token-manager.js +17 -8
- package/dist/src/core/token-scaffold.d.ts +7 -7
- package/dist/src/core/token-scaffold.js +7 -7
- package/dist/src/core/token-variant.d.ts +4 -4
- package/dist/src/core/token-variant.js +28 -6
- package/dist/src/core/toolchain-preflight.d.ts +20 -21
- package/dist/src/core/toolchain-preflight.js +28 -31
- package/dist/src/core/tree-guard.js +12 -2
- package/dist/src/core/tree-store.d.ts +41 -27
- package/dist/src/core/tree-store.js +68 -43
- package/dist/src/core/typecheck-shim.d.ts +23 -24
- package/dist/src/core/typecheck-shim.js +23 -24
- package/dist/src/core/typecheck.js +15 -9
- package/dist/src/core/wire-destroy.d.ts +3 -3
- package/dist/src/core/wire-destroy.js +7 -15
- package/dist/src/core/wire-dom-fragment.d.ts +9 -17
- package/dist/src/core/wire-dom-fragment.js +11 -44
- package/dist/src/core/wire-init.d.ts +2 -3
- package/dist/src/core/wire-init.js +8 -19
- package/dist/src/core/wire-subscript.d.ts +2 -3
- package/dist/src/core/wire-subscript.js +4 -13
- package/dist/src/core/wire-utils.d.ts +7 -8
- package/dist/src/core/wire-utils.js +7 -8
- package/dist/src/core/xpcshell-appdir.d.ts +38 -45
- package/dist/src/core/xpcshell-appdir.js +38 -45
- package/dist/src/errors/base.d.ts +37 -16
- package/dist/src/errors/base.js +37 -16
- package/dist/src/errors/build.d.ts +13 -1
- package/dist/src/errors/build.js +14 -2
- package/dist/src/errors/codes.d.ts +16 -0
- package/dist/src/errors/codes.js +16 -0
- package/dist/src/errors/furnace.d.ts +4 -4
- package/dist/src/errors/git.d.ts +6 -10
- package/dist/src/errors/git.js +6 -10
- package/dist/src/errors/patch.d.ts +7 -7
- package/dist/src/errors/patch.js +7 -7
- package/dist/src/errors/rebase.d.ts +4 -4
- package/dist/src/errors/rebase.js +4 -4
- package/dist/src/index.d.ts +7 -1
- package/dist/src/index.js +5 -0
- package/dist/src/types/commands/index.d.ts +2 -2
- package/dist/src/types/commands/options.d.ts +111 -70
- package/dist/src/types/commands/patches.d.ts +24 -34
- package/dist/src/types/commands/project.d.ts +5 -34
- package/dist/src/types/config.d.ts +25 -23
- package/dist/src/types/config.js +6 -1
- package/dist/src/types/furnace.d.ts +37 -13
- package/dist/src/types/furnace.js +19 -1
- package/dist/src/types/index.d.ts +3 -3
- package/dist/src/utils/build-info.d.ts +7 -8
- package/dist/src/utils/build-info.js +12 -11
- package/dist/src/utils/errors.d.ts +6 -8
- package/dist/src/utils/errors.js +6 -8
- package/dist/src/utils/logger.d.ts +27 -10
- package/dist/src/utils/logger.js +28 -16
- package/dist/src/utils/machine-output.d.ts +12 -0
- package/dist/src/utils/machine-output.js +33 -0
- package/dist/src/utils/options.d.ts +31 -14
- package/dist/src/utils/options.js +86 -30
- package/dist/src/utils/paths.d.ts +10 -8
- package/dist/src/utils/paths.js +10 -8
- package/dist/src/utils/platform.d.ts +0 -25
- package/dist/src/utils/platform.js +1 -42
- package/dist/src/utils/process-group.d.ts +9 -4
- package/dist/src/utils/process-group.js +19 -5
- package/dist/src/utils/process.d.ts +42 -7
- package/dist/src/utils/process.js +44 -17
- package/dist/src/utils/ps-duration.d.ts +31 -0
- package/dist/src/utils/ps-duration.js +70 -0
- package/dist/src/utils/regex.d.ts +9 -10
- package/dist/src/utils/regex.js +9 -10
- package/dist/src/utils/validation.d.ts +58 -28
- package/dist/src/utils/validation.js +60 -33
- package/package.json +3 -3
- package/dist/src/commands/doctor/post-rebase-audit.d.ts +0 -2
- package/dist/src/commands/doctor-furnace-manifest-sync.d.ts +0 -18
- package/dist/src/core/manifest-helpers.d.ts +0 -38
- package/dist/src/core/manifest-helpers.js +0 -120
- /package/dist/src/core/{lint-projection.d.ts → patch-lint-projection.d.ts} +0 -0
- /package/dist/src/core/{lint-projection.js → patch-lint-projection.js} +0 -0
- /package/dist/src/core/{register-test-manifest.d.ts → register-browser-test.d.ts} +0 -0
|
@@ -1,495 +1,4 @@
|
|
|
1
|
-
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
-
import { join } from 'node:path';
|
|
3
|
-
import { pathExists, readText } from '../utils/fs.js';
|
|
4
|
-
import { getProjectPaths } from './config.js';
|
|
5
|
-
import { extractComponentChecksums } from './furnace-checksum-utils.js';
|
|
6
1
|
/** Creates a normalized validation issue object. */
|
|
7
2
|
export function createIssue(component, severity, check, message) {
|
|
8
3
|
return { component, severity, check, message };
|
|
9
4
|
}
|
|
10
|
-
/** Detects whether template or script content assigns an ARIA role. */
|
|
11
|
-
export function hasAriaRole(content) {
|
|
12
|
-
return (/role\s*=\s*["']/.test(content) ||
|
|
13
|
-
/\.role\s*=/.test(content) ||
|
|
14
|
-
/setAttribute\(\s*["']role["']/.test(content));
|
|
15
|
-
}
|
|
16
|
-
/** Detects generic elements being used as custom interactive controls. */
|
|
17
|
-
export function hasGenericInteractiveElement(content) {
|
|
18
|
-
return /<(div|span)\b(?=[^>]*(?:@click|@key(?:down|press|up)|\btabindex\s*=|\.onclick\s*=))/i.test(content);
|
|
19
|
-
}
|
|
20
|
-
/** Detects a positive tabindex value, which disrupts natural tab order. */
|
|
21
|
-
export function hasPositiveTabindex(content) {
|
|
22
|
-
const match = content.match(/tabindex\s*=\s*["']?(\d+)/g);
|
|
23
|
-
if (!match)
|
|
24
|
-
return false;
|
|
25
|
-
return match.some((m) => {
|
|
26
|
-
const value = /(\d+)/.exec(m)?.[1];
|
|
27
|
-
return value !== undefined && parseInt(value, 10) > 0;
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Collects `[start, end)` spans of `<label>…</label>` elements whose content
|
|
32
|
-
* includes actual label text. Labels cannot nest per HTML, so the non-greedy
|
|
33
|
-
* inner match is sound. A span qualifies only when the inner content minus
|
|
34
|
-
* tags still contains non-whitespace — an empty or tag-only wrapper provides
|
|
35
|
-
* no accessible name. A `${…}` Lit binding counts as label text: dynamic
|
|
36
|
-
* (usually localized) text is a legitimate accessible name.
|
|
37
|
-
*/
|
|
38
|
-
function collectLabelledSpans(content) {
|
|
39
|
-
const spans = [];
|
|
40
|
-
const labelPattern = /<label\b[^>]*>([\s\S]*?)<\/label>/gi;
|
|
41
|
-
let labelMatch;
|
|
42
|
-
while ((labelMatch = labelPattern.exec(content)) !== null) {
|
|
43
|
-
const inner = labelMatch[1] ?? '';
|
|
44
|
-
if (/\S/.test(inner.replace(/<[^>]*>/g, ' '))) {
|
|
45
|
-
spans.push({ start: labelMatch.index, end: labelMatch.index + labelMatch[0].length });
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
return spans;
|
|
49
|
-
}
|
|
50
|
-
/** Detects form inputs without associated labels. */
|
|
51
|
-
export function hasUnlabelledFormInput(content) {
|
|
52
|
-
// Look for <input> or <select> or <textarea> without aria-label, aria-labelledby, or id
|
|
53
|
-
// (id implies an external <label for="..."> could exist). A control wrapped
|
|
54
|
-
// in a <label> that carries actual text is implicitly associated and is
|
|
55
|
-
// exempt as well.
|
|
56
|
-
const labelledSpans = collectLabelledSpans(content);
|
|
57
|
-
const inputPattern = /<(input|select|textarea)\b([^>]*)>/gi;
|
|
58
|
-
let inputMatch;
|
|
59
|
-
while ((inputMatch = inputPattern.exec(content)) !== null) {
|
|
60
|
-
const attrs = inputMatch[2] ?? '';
|
|
61
|
-
if (/aria-label\s*=/.test(attrs) ||
|
|
62
|
-
/aria-labelledby\s*=/.test(attrs) ||
|
|
63
|
-
/\bid\s*=/.test(attrs) ||
|
|
64
|
-
/type\s*=\s*["']hidden["']/i.test(attrs)) {
|
|
65
|
-
continue;
|
|
66
|
-
}
|
|
67
|
-
const index = inputMatch.index;
|
|
68
|
-
if (labelledSpans.some((span) => index >= span.start && index < span.end)) {
|
|
69
|
-
continue;
|
|
70
|
-
}
|
|
71
|
-
return true;
|
|
72
|
-
}
|
|
73
|
-
return false;
|
|
74
|
-
}
|
|
75
|
-
/** Detects Lit-style template click handlers. */
|
|
76
|
-
export function hasTemplateClickHandler(content) {
|
|
77
|
-
return /@click\s*=\s*\$\{/.test(content);
|
|
78
|
-
}
|
|
79
|
-
/** Detects Lit-style template keyboard handlers. */
|
|
80
|
-
export function hasTemplateKeyboardHandler(content) {
|
|
81
|
-
return /@key(down|press|up)\s*=\s*\$\{/.test(content);
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Native HTML elements that dispatch `click` on Enter and Space via the
|
|
85
|
-
* platform. Attaching `@click` to these is NOT a keyboard-a11y bug because
|
|
86
|
-
* the browser already handles the keyboard activation path — a duplicate
|
|
87
|
-
* `@keydown`/`@keypress` handler would usually double-fire the action.
|
|
88
|
-
*
|
|
89
|
-
* `<a>` is accepted only when an `href` attribute is present; bare `<a>` is
|
|
90
|
-
* non-interactive and is treated as synthetic.
|
|
91
|
-
*/
|
|
92
|
-
const NATIVE_CLICK_INTERACTIVE_TAGS = new Set([
|
|
93
|
-
'button',
|
|
94
|
-
'input',
|
|
95
|
-
'select',
|
|
96
|
-
'textarea',
|
|
97
|
-
'summary',
|
|
98
|
-
'details',
|
|
99
|
-
// Mozilla widgets that extend the native pattern and keep Enter/Space activation.
|
|
100
|
-
'moz-button',
|
|
101
|
-
'moz-toggle',
|
|
102
|
-
'moz-checkbox',
|
|
103
|
-
'moz-radio',
|
|
104
|
-
'moz-radio-group',
|
|
105
|
-
'moz-menulist',
|
|
106
|
-
]);
|
|
107
|
-
/**
|
|
108
|
-
* Returns true when `customConfig` declares that the component's keyboard
|
|
109
|
-
* activation path is covered by a wrapped native-interactive inner element,
|
|
110
|
-
* either through an explicit opt-out (`keyboardCovered: true`) or by
|
|
111
|
-
* composing a tag that lives in {@link NATIVE_CLICK_INTERACTIVE_TAGS}.
|
|
112
|
-
*
|
|
113
|
-
* Uses `.some` rather than `.every` so that a wrapper composing e.g.
|
|
114
|
-
* `['moz-button', 'my-tooltip']` still skips the warning: the keyboard
|
|
115
|
-
* activation path flows through the button, even if other composed
|
|
116
|
-
* children are synthetic.
|
|
117
|
-
*/
|
|
118
|
-
export function isKeyboardCoveredByComposition(customConfig) {
|
|
119
|
-
if (!customConfig)
|
|
120
|
-
return false;
|
|
121
|
-
if (customConfig.keyboardCovered === true)
|
|
122
|
-
return true;
|
|
123
|
-
const composes = customConfig.composes ?? [];
|
|
124
|
-
return composes.some((tag) => NATIVE_CLICK_INTERACTIVE_TAGS.has(tag));
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Returns true when `content` has at least one `@click=${...}` handler on a
|
|
128
|
-
* *synthetic* interactive element (e.g. `<div @click>`), which lacks native
|
|
129
|
-
* keyboard activation and therefore needs an explicit key handler for
|
|
130
|
-
* Enter/Space. Returns false when every `@click` handler sits on a native
|
|
131
|
-
* interactive element — those already fire `click` on keyboard activation.
|
|
132
|
-
*/
|
|
133
|
-
export function hasTemplateClickOnSyntheticInteractive(content) {
|
|
134
|
-
const pattern = /@click\s*=\s*\$\{/g;
|
|
135
|
-
let match;
|
|
136
|
-
while ((match = pattern.exec(content)) !== null) {
|
|
137
|
-
if (isClickOnSyntheticInteractive(content, match.index)) {
|
|
138
|
-
return true;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
return false;
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* Given the offset of an `@click=${...}` occurrence, walks backwards to find
|
|
145
|
-
* the opening `<tag` that owns it and decides whether that tag is a native
|
|
146
|
-
* interactive element (no warning needed) or a synthetic one (warning needed).
|
|
147
|
-
*/
|
|
148
|
-
function isClickOnSyntheticInteractive(content, clickIndex) {
|
|
149
|
-
// Find the nearest preceding `<` that starts a tag (skip `</` closers).
|
|
150
|
-
let i = clickIndex - 1;
|
|
151
|
-
let tagOpenIndex = -1;
|
|
152
|
-
while (i >= 0) {
|
|
153
|
-
if (content[i] === '<' && content[i + 1] !== '/') {
|
|
154
|
-
tagOpenIndex = i;
|
|
155
|
-
break;
|
|
156
|
-
}
|
|
157
|
-
// A `>` before an unclosed `<` means we're outside the attribute list,
|
|
158
|
-
// which shouldn't happen for a well-formed template but we defensively
|
|
159
|
-
// treat it as synthetic to preserve the prior-behaviour warning.
|
|
160
|
-
if (content[i] === '>') {
|
|
161
|
-
return true;
|
|
162
|
-
}
|
|
163
|
-
i--;
|
|
164
|
-
}
|
|
165
|
-
if (tagOpenIndex < 0)
|
|
166
|
-
return true;
|
|
167
|
-
const tagMatch = /^<([a-zA-Z][a-zA-Z0-9-]*)/.exec(content.slice(tagOpenIndex));
|
|
168
|
-
if (!tagMatch?.[1])
|
|
169
|
-
return true;
|
|
170
|
-
const tagName = tagMatch[1].toLowerCase();
|
|
171
|
-
if (tagName === 'a') {
|
|
172
|
-
// Bare <a> (no href) is non-interactive; require a keyboard handler.
|
|
173
|
-
// Look forward from the tag open for the closing `>` and scan the
|
|
174
|
-
// attribute text in between for an href attribute.
|
|
175
|
-
const tagEnd = content.indexOf('>', tagOpenIndex);
|
|
176
|
-
if (tagEnd < 0)
|
|
177
|
-
return true;
|
|
178
|
-
const attrs = content.slice(tagOpenIndex, tagEnd);
|
|
179
|
-
return !/\shref\s*=/.test(attrs);
|
|
180
|
-
}
|
|
181
|
-
return !NATIVE_CLICK_INTERACTIVE_TAGS.has(tagName);
|
|
182
|
-
}
|
|
183
|
-
/** ASCII punctuation that reads as decoration rather than localizable text. */
|
|
184
|
-
const SYMBOL_ONLY_ASCII = '+-*=<>|/\\^~@#&!?%';
|
|
185
|
-
/**
|
|
186
|
-
* Reports whether `text` is decoration (arrows, maths, emoji, bare
|
|
187
|
-
* punctuation) rather than user-facing prose that needs localizing.
|
|
188
|
-
*
|
|
189
|
-
* The letter/number/mark test comes first and is script-agnostic. Until
|
|
190
|
-
* 0.41.0 the only non-ASCII rule was `code > 0xff`, which classified *every*
|
|
191
|
-
* code point above U+00FF as a symbol — so all CJK, Cyrillic, Greek, Arabic,
|
|
192
|
-
* Hebrew, Devanagari and Thai text was exempted from a **localization**
|
|
193
|
-
* validator, i.e. the rule was blind to precisely the strings most likely to
|
|
194
|
-
* need translating.
|
|
195
|
-
*
|
|
196
|
-
* Combining marks are deliberately NOT counted as text: the check is an
|
|
197
|
-
* `every()`, so a script's base letters already disqualify the string, and
|
|
198
|
-
* treating marks as text would flag emoji carrying a variation selector
|
|
199
|
-
* (U+FE0F is category Mn — `⚙️` is U+2699 + U+FE0F).
|
|
200
|
-
*
|
|
201
|
-
* High code points that are not letters — emoji, arrows, CJK punctuation —
|
|
202
|
-
* stay exempt, which is the rule's original intent.
|
|
203
|
-
*
|
|
204
|
-
* A handful of emoji are ALSO Unicode letters, and the letter test alone gets
|
|
205
|
-
* them wrong. U+2139 (`ℹ`, the base of the very common `ℹ️`) is category Ll, so
|
|
206
|
-
* the `\p{L}` branch classified an info badge as prose needing localization.
|
|
207
|
-
* Non-ASCII code points carrying `Emoji` are therefore read as symbols before
|
|
208
|
-
* the letter test. The ASCII guard matters: `\p{Emoji}` also covers the digits
|
|
209
|
-
* `0`-`9`, `#` and `*`, which must keep their existing classification.
|
|
210
|
-
*/
|
|
211
|
-
function isSymbolOnlyText(text) {
|
|
212
|
-
return Array.from(text).every((character) => {
|
|
213
|
-
const code = character.codePointAt(0) ?? 0;
|
|
214
|
-
if (code > 0x7f && /\p{Emoji}/u.test(character))
|
|
215
|
-
return true;
|
|
216
|
-
if (/[\p{L}\p{N}]/u.test(character))
|
|
217
|
-
return false;
|
|
218
|
-
return code > 0xff || SYMBOL_ONLY_ASCII.includes(character);
|
|
219
|
-
});
|
|
220
|
-
}
|
|
221
|
-
function isWithinLocalizedElement(content, matchIndex) {
|
|
222
|
-
const contentBefore = content.slice(0, matchIndex + 1);
|
|
223
|
-
const lastTagOpen = contentBefore.lastIndexOf('<');
|
|
224
|
-
if (lastTagOpen === -1) {
|
|
225
|
-
return false;
|
|
226
|
-
}
|
|
227
|
-
const tagContent = contentBefore.slice(lastTagOpen, matchIndex + 1);
|
|
228
|
-
return /data-l10n-id\s*=/.test(tagContent);
|
|
229
|
-
}
|
|
230
|
-
/**
|
|
231
|
-
* Detects hardcoded user-visible template text that should usually be
|
|
232
|
-
* localized.
|
|
233
|
-
*
|
|
234
|
-
* Scoped to three positive contexts rather than scanning the whole file,
|
|
235
|
-
* because a bare `>…<` regex catches JS comparisons (`if (x > 0 && y <
|
|
236
|
-
* 100)`), diagnostic strings (`console.error("Failed <id> lookup")`), and
|
|
237
|
-
* identifier literals that are never shown to a user. Only matches that
|
|
238
|
-
* actually enter a UI render path count:
|
|
239
|
-
*
|
|
240
|
-
* 1. Content inside a Lit `` html`…` `` tagged template literal.
|
|
241
|
-
* 2. The string literal on the RHS of `.textContent = "…"` or
|
|
242
|
-
* `.innerHTML = "…"`.
|
|
243
|
-
* 3. The string literal assigned to an XUL-widget `label=`,
|
|
244
|
-
* `title=`, or `tooltiptext=` attribute when constructing DOM in JS.
|
|
245
|
-
*
|
|
246
|
-
* A file-wide `// furnace-ignore: hardcoded-text` comment suppresses all
|
|
247
|
-
* findings (matches the pre-existing escape hatch).
|
|
248
|
-
*/
|
|
249
|
-
export function containsHardcodedTemplateText(content) {
|
|
250
|
-
if (/furnace-ignore:\s*hardcoded-text/.test(content)) {
|
|
251
|
-
return false;
|
|
252
|
-
}
|
|
253
|
-
return (hasFlaggedTextInLitTemplates(content) ||
|
|
254
|
-
hasFlaggedTextInDomAssignment(content) ||
|
|
255
|
-
hasFlaggedTextInXulAttribute(content));
|
|
256
|
-
}
|
|
257
|
-
function isFlaggableText(text) {
|
|
258
|
-
const trimmed = text.trim();
|
|
259
|
-
if (!trimmed)
|
|
260
|
-
return false;
|
|
261
|
-
if (/\$\{/.test(trimmed))
|
|
262
|
-
return false;
|
|
263
|
-
if (Array.from(trimmed).length <= 1)
|
|
264
|
-
return false;
|
|
265
|
-
if (isSymbolOnlyText(trimmed))
|
|
266
|
-
return false;
|
|
267
|
-
return true;
|
|
268
|
-
}
|
|
269
|
-
function hasFlaggedTextInLitTemplates(content) {
|
|
270
|
-
// Match `html\`…\`` regions, anchored on a non-identifier char before `html`
|
|
271
|
-
// so substrings like `otherhtml` do not spuriously open a template.
|
|
272
|
-
const htmlPattern = /(?:^|[^a-zA-Z0-9_$])html`([\s\S]*?)`/g;
|
|
273
|
-
let litMatch;
|
|
274
|
-
while ((litMatch = htmlPattern.exec(content)) !== null) {
|
|
275
|
-
const region = litMatch[1] ?? '';
|
|
276
|
-
const textPattern = />([^<$\s][^<$]*)</g;
|
|
277
|
-
let textMatch;
|
|
278
|
-
while ((textMatch = textPattern.exec(region)) !== null) {
|
|
279
|
-
const text = textMatch[1] ?? '';
|
|
280
|
-
if (!isFlaggableText(text))
|
|
281
|
-
continue;
|
|
282
|
-
if (isWithinLocalizedElement(region, textMatch.index))
|
|
283
|
-
continue;
|
|
284
|
-
return true;
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
return false;
|
|
288
|
-
}
|
|
289
|
-
function hasFlaggedTextInDomAssignment(content) {
|
|
290
|
-
// `<expr>.textContent = "abc"` and `<expr>.innerHTML = "abc"` — these are
|
|
291
|
-
// user-visible render paths. Template-literal RHS is excluded (usually
|
|
292
|
-
// dynamic), matching the `${` guard used elsewhere in this helper.
|
|
293
|
-
const assignPattern = /\.(?:textContent|innerHTML)\s*=\s*(["'])((?:\\.|(?!\1).)*)\1/g;
|
|
294
|
-
let match;
|
|
295
|
-
while ((match = assignPattern.exec(content)) !== null) {
|
|
296
|
-
const text = match[2] ?? '';
|
|
297
|
-
if (isFlaggableText(text))
|
|
298
|
-
return true;
|
|
299
|
-
}
|
|
300
|
-
return false;
|
|
301
|
-
}
|
|
302
|
-
function hasFlaggedTextInXulAttribute(content) {
|
|
303
|
-
// Assignments like `node.setAttribute("label", "Save")` or JS-built XUL
|
|
304
|
-
// attributes `label="…"` / `title="…"` / `tooltiptext="…"` in template
|
|
305
|
-
// literals outside Lit blocks. Covers DOM built via createXULElement.
|
|
306
|
-
const setAttrPattern = /setAttribute\s*\(\s*["'](?:label|title|tooltiptext)["']\s*,\s*(["'])((?:\\.|(?!\1).)*)\1/g;
|
|
307
|
-
let setAttrMatch;
|
|
308
|
-
while ((setAttrMatch = setAttrPattern.exec(content)) !== null) {
|
|
309
|
-
const text = setAttrMatch[2] ?? '';
|
|
310
|
-
if (isFlaggableText(text))
|
|
311
|
-
return true;
|
|
312
|
-
}
|
|
313
|
-
return false;
|
|
314
|
-
}
|
|
315
|
-
/** Detects whether a component opts into shadow-root focus delegation. */
|
|
316
|
-
export function hasDelegatesFocusEnabled(content) {
|
|
317
|
-
return /shadowRootOptions[\s\S]*?delegatesFocus\s*:\s*true/.test(content);
|
|
318
|
-
}
|
|
319
|
-
/** Removes CSS block comments before running simple string-based checks. */
|
|
320
|
-
export function stripCssBlockComments(content) {
|
|
321
|
-
return content.replace(/\/\*[\s\S]*?\*\//g, '');
|
|
322
|
-
}
|
|
323
|
-
/** Detects relative ES module imports in a component module file. */
|
|
324
|
-
export function hasRelativeModuleImport(mjsContent) {
|
|
325
|
-
return (/^\s*import\s.*from\s+["']\.\.?\//m.test(mjsContent) ||
|
|
326
|
-
/^\s*import\s+["']\.\.?\//m.test(mjsContent));
|
|
327
|
-
}
|
|
328
|
-
/** Detects whether a module defines a custom element at runtime. */
|
|
329
|
-
export function hasCustomElementDefineCall(mjsContent) {
|
|
330
|
-
return /customElements\.define\s*\(/.test(mjsContent);
|
|
331
|
-
}
|
|
332
|
-
/**
|
|
333
|
-
* Detects whether the module's `customElements.define(...)` call includes a
|
|
334
|
-
* literal `extends:` option (third argument). That shape is the marker for
|
|
335
|
-
* a customized built-in element — the class extends a specific
|
|
336
|
-
* `HTMLxxxElement` rather than the autonomous `MozLitElement` path.
|
|
337
|
-
*
|
|
338
|
-
* Firefox's own widgets use this pattern for toolkit anchors (e.g.
|
|
339
|
-
* `moz-support-link` extends `HTMLAnchorElement` with
|
|
340
|
-
* `customElements.define("moz-support-link", ..., { extends: "a" })`), and
|
|
341
|
-
* the validator's `not-moz-lit-element` check must allow them through or
|
|
342
|
-
* `furnace override` of a valid upstream component fails its own
|
|
343
|
-
* `furnace validate` pass with nothing the operator can fix.
|
|
344
|
-
*/
|
|
345
|
-
function hasCustomElementExtendsOption(mjsContent) {
|
|
346
|
-
// Match `customElements.define(..., { ..., extends: "..." })`. Tolerant of
|
|
347
|
-
// whitespace, line breaks, and other object properties. The `[^)]*` stops
|
|
348
|
-
// the inner greedy match at the closing define call paren so a later
|
|
349
|
-
// `define` call on a different custom element in the same module does
|
|
350
|
-
// not bleed its options in.
|
|
351
|
-
return /customElements\.define\s*\([^)]*\bextends\s*:\s*["'`]/.test(mjsContent);
|
|
352
|
-
}
|
|
353
|
-
/**
|
|
354
|
-
* Checks whether a declared component class extends a valid element base.
|
|
355
|
-
*
|
|
356
|
-
* Two shapes are accepted:
|
|
357
|
-
*
|
|
358
|
-
* 1. Autonomous custom element: `class X extends MozLitElement` — the
|
|
359
|
-
* default FireForge pattern for fork-authored components and most
|
|
360
|
-
* toolkit widgets.
|
|
361
|
-
* 2. Customized built-in: `class X extends HTML<Something>Element` paired
|
|
362
|
-
* with a `customElements.define(..., ..., { extends: "<tagname>" })`
|
|
363
|
-
* call. Firefox's `moz-support-link`, `moz-button-group` tabbing
|
|
364
|
-
* widgets, and a handful of other toolkit components use this form;
|
|
365
|
-
* `furnace override` of those components writes the original source
|
|
366
|
-
* verbatim and the validator must not reject them.
|
|
367
|
-
*
|
|
368
|
-
* A class that extends a plain `HTMLElement` WITHOUT a `extends:` option
|
|
369
|
-
* is still rejected — that's the legitimate `not-moz-lit-element` case
|
|
370
|
-
* the rule was originally designed to catch.
|
|
371
|
-
*/
|
|
372
|
-
export function classExtendsMozLitElement(mjsContent) {
|
|
373
|
-
const hasClassDeclaration = /class\s+\w+\s+extends\s+/.test(mjsContent);
|
|
374
|
-
if (!hasClassDeclaration) {
|
|
375
|
-
// No class declaration — skip this check since the component may use a
|
|
376
|
-
// different pattern (e.g. function-based). Other validators will catch
|
|
377
|
-
// structural issues.
|
|
378
|
-
return true;
|
|
379
|
-
}
|
|
380
|
-
if (/class\s+\w+\s+extends\s+MozLitElement\b/.test(mjsContent)) {
|
|
381
|
-
return true;
|
|
382
|
-
}
|
|
383
|
-
// Customized built-in: extend a specific HTMLxxxElement AND the define
|
|
384
|
-
// call carries an `extends:` option. Both halves are required — a class
|
|
385
|
-
// that extends `HTMLAnchorElement` without the matching define option is
|
|
386
|
-
// almost certainly an author mistake, and a define call with `extends:`
|
|
387
|
-
// without a matching class is unreachable.
|
|
388
|
-
const extendsCustomizedBuiltin = /class\s+\w+\s+extends\s+HTML[A-Z]\w*Element\b/.test(mjsContent);
|
|
389
|
-
if (extendsCustomizedBuiltin && hasCustomElementExtendsOption(mjsContent)) {
|
|
390
|
-
return true;
|
|
391
|
-
}
|
|
392
|
-
return false;
|
|
393
|
-
}
|
|
394
|
-
/** Collects CSS custom property references used via var(--token-name). */
|
|
395
|
-
export function collectCssVariableReferences(cssContent) {
|
|
396
|
-
const referencedVariables = [];
|
|
397
|
-
const variablePattern = /var\(\s*(--[\w-]+)/g;
|
|
398
|
-
let match;
|
|
399
|
-
while ((match = variablePattern.exec(cssContent)) !== null) {
|
|
400
|
-
const variableName = match[1];
|
|
401
|
-
if (variableName) {
|
|
402
|
-
referencedVariables.push(variableName);
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
return referencedVariables;
|
|
406
|
-
}
|
|
407
|
-
/**
|
|
408
|
-
* Collects CSS custom property *declarations* — names appearing on the
|
|
409
|
-
* left-hand side of a `--name:` declaration. Used to auto-exempt
|
|
410
|
-
* component-local runtime variables from the token-prefix check: if the
|
|
411
|
-
* component both declares and consumes a variable in its own CSS file, it
|
|
412
|
-
* is a local runtime channel, not a design-token reference.
|
|
413
|
-
*
|
|
414
|
-
* The anchor `(?:^|[{;,\s])` rules out `var(--name)` occurrences (which are
|
|
415
|
-
* always preceded by `(`), so references are not mistaken for declarations.
|
|
416
|
-
*/
|
|
417
|
-
export function collectCssVariableDeclarations(cssContent) {
|
|
418
|
-
const declared = new Set();
|
|
419
|
-
const pattern = /(?:^|[{;,\s])(--[\w-]+)\s*:/g;
|
|
420
|
-
let match;
|
|
421
|
-
while ((match = pattern.exec(cssContent)) !== null) {
|
|
422
|
-
const name = match[1];
|
|
423
|
-
if (name)
|
|
424
|
-
declared.add(name);
|
|
425
|
-
}
|
|
426
|
-
return declared;
|
|
427
|
-
}
|
|
428
|
-
async function collectInheritedOverrideVariables(tagName, config, root) {
|
|
429
|
-
const inheritedVariables = new Set();
|
|
430
|
-
const basePath = config.overrides[tagName]?.basePath;
|
|
431
|
-
if (!basePath) {
|
|
432
|
-
return inheritedVariables;
|
|
433
|
-
}
|
|
434
|
-
const { engine: engineDir } = getProjectPaths(root);
|
|
435
|
-
const originalCssPath = join(engineDir, basePath, `${tagName}.css`);
|
|
436
|
-
if (!(await pathExists(originalCssPath))) {
|
|
437
|
-
return inheritedVariables;
|
|
438
|
-
}
|
|
439
|
-
const originalCssContent = stripCssBlockComments(await readText(originalCssPath));
|
|
440
|
-
for (const variableName of collectCssVariableReferences(originalCssContent)) {
|
|
441
|
-
inheritedVariables.add(variableName);
|
|
442
|
-
}
|
|
443
|
-
return inheritedVariables;
|
|
444
|
-
}
|
|
445
|
-
/** Builds token-validation context from the config allowlist and inherited override CSS. */
|
|
446
|
-
export async function getTokenPrefixContext(tagName, type, config, root) {
|
|
447
|
-
const allowlist = new Set(config.tokenAllowlist ?? []);
|
|
448
|
-
const runtimeVariables = new Set(config.runtimeVariables ?? []);
|
|
449
|
-
if (type !== 'override' || !root) {
|
|
450
|
-
return { allowlist, inheritedOverrideVars: new Set(), runtimeVariables };
|
|
451
|
-
}
|
|
452
|
-
return {
|
|
453
|
-
allowlist,
|
|
454
|
-
inheritedOverrideVars: await collectInheritedOverrideVariables(tagName, config, root),
|
|
455
|
-
runtimeVariables,
|
|
456
|
-
};
|
|
457
|
-
}
|
|
458
|
-
/**
|
|
459
|
-
* Flags engine-side files that a previous deploy of `tagName` left behind
|
|
460
|
-
* after their workspace source was renamed or removed (field report D1).
|
|
461
|
-
*
|
|
462
|
-
* Detection keys on the furnace state file: every `appliedChecksums` entry
|
|
463
|
-
* under `custom/<tagName>/` whose workspace source no longer exists but
|
|
464
|
-
* whose engine target is still present is an orphan — the next deploy will
|
|
465
|
-
* prune it, but until then jar.mn and the deployed directory disagree with
|
|
466
|
-
* the workspace, and a re-export could capture the stale state into a patch.
|
|
467
|
-
*
|
|
468
|
-
* Custom components only: override undeploys restore the upstream baseline
|
|
469
|
-
* rather than deleting files, so "orphan" has no meaning there.
|
|
470
|
-
*/
|
|
471
|
-
export async function findOrphanedEngineFiles(root, config, tagName, state, ftlDir) {
|
|
472
|
-
const customConfig = config.custom[tagName];
|
|
473
|
-
if (!customConfig)
|
|
474
|
-
return [];
|
|
475
|
-
const previous = extractComponentChecksums(state.appliedChecksums, 'custom', tagName);
|
|
476
|
-
const fileNames = Object.keys(previous);
|
|
477
|
-
if (fileNames.length === 0)
|
|
478
|
-
return [];
|
|
479
|
-
const { engine: engineDir, componentsDir } = getProjectPaths(root);
|
|
480
|
-
const componentDir = join(componentsDir, 'custom', tagName);
|
|
481
|
-
const issues = [];
|
|
482
|
-
for (const fileName of fileNames) {
|
|
483
|
-
if (await pathExists(join(componentDir, fileName)))
|
|
484
|
-
continue;
|
|
485
|
-
const enginePath = fileName.endsWith('.ftl')
|
|
486
|
-
? join(engineDir, ftlDir, fileName)
|
|
487
|
-
: join(engineDir, customConfig.targetPath, fileName);
|
|
488
|
-
if (!(await pathExists(enginePath)))
|
|
489
|
-
continue;
|
|
490
|
-
issues.push(createIssue(tagName, 'warning', 'orphaned-engine-file', `Engine file ${fileName} was deployed by a previous apply but its workspace source ` +
|
|
491
|
-
`is gone (renamed or deleted). The deployed copy${customConfig.register ? ' and any stale jar.mn entry' : ''} ` +
|
|
492
|
-
`will linger until the next deploy prunes it. Run "fireforge furnace deploy ${tagName}".`));
|
|
493
|
-
}
|
|
494
|
-
return issues;
|
|
495
|
-
}
|
|
@@ -30,6 +30,13 @@ export declare function checkRegistrationConsistency(root: string, name: string,
|
|
|
30
30
|
* @returns Array of validation issues for missing jar.mn entries
|
|
31
31
|
*/
|
|
32
32
|
export declare function validateJarMnEntries(root: string, config: FurnaceConfig): Promise<ValidationIssue[]>;
|
|
33
|
+
/**
|
|
34
|
+
* Runs `body` with the per-run caches enabled, then clears them.
|
|
35
|
+
*
|
|
36
|
+
* @param body - The batch to run
|
|
37
|
+
* @returns Whatever `body` resolves to
|
|
38
|
+
*/
|
|
39
|
+
export declare function withRegistrationValidationCache<T>(body: () => Promise<T>): Promise<T>;
|
|
33
40
|
/**
|
|
34
41
|
* Validates that components using design tokens have the tokens CSS
|
|
35
42
|
* linked in at least one chrome host document. Without the link, tokens
|