@hominis/fireforge 0.52.0 → 0.53.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 +26 -0
- package/dist/build-info.json +4 -4
- package/dist/src/commands/bootstrap.js +2 -3
- package/dist/src/commands/build-prelock.d.ts +3 -3
- package/dist/src/commands/build-prelock.js +3 -3
- package/dist/src/commands/build.js +4 -0
- package/dist/src/commands/declarations-report.d.ts +9 -3
- package/dist/src/commands/declarations-report.js +18 -11
- package/dist/src/commands/discard.js +3 -3
- package/dist/src/commands/doctor-furnace-config-sync.js +4 -4
- package/dist/src/commands/doctor-furnace.js +5 -5
- package/dist/src/commands/export-adopt-check.d.ts +5 -6
- package/dist/src/commands/export-adopt-check.js +5 -6
- package/dist/src/commands/export-flow.js +6 -9
- package/dist/src/commands/export-staged-registration.d.ts +4 -4
- package/dist/src/commands/export-staged-registration.js +4 -4
- package/dist/src/commands/forward-import-remedy.d.ts +2 -3
- package/dist/src/commands/forward-import-remedy.js +2 -3
- package/dist/src/commands/furnace/create-dry-run.d.ts +2 -2
- package/dist/src/commands/furnace/deploy-fragment-includers.d.ts +2 -2
- package/dist/src/commands/furnace/deploy-fragment-includers.js +2 -2
- package/dist/src/commands/furnace/index.js +2 -2
- package/dist/src/commands/lint.js +4 -4
- package/dist/src/commands/patch/compact.js +1 -1
- package/dist/src/commands/patch/lint-ignore-from.d.ts +3 -4
- package/dist/src/commands/patch/lint-ignore-from.js +3 -4
- package/dist/src/commands/patch/move-files-adopt.d.ts +33 -0
- package/dist/src/commands/patch/move-files-adopt.js +65 -0
- package/dist/src/commands/patch/move-files-create.js +41 -20
- package/dist/src/commands/patch/move-files-into.d.ts +18 -0
- package/dist/src/commands/patch/move-files-into.js +125 -60
- package/dist/src/commands/patch/move-files-retire.d.ts +39 -0
- package/dist/src/commands/patch/move-files-retire.js +91 -0
- package/dist/src/commands/patch/move-files.d.ts +3 -0
- package/dist/src/commands/patch/move-files.js +42 -12
- package/dist/src/commands/patch/move-size-tier.d.ts +27 -0
- package/dist/src/commands/patch/move-size-tier.js +66 -0
- package/dist/src/commands/patch/rename.js +1 -1
- package/dist/src/commands/patch/reorder-projection.d.ts +17 -0
- package/dist/src/commands/patch/reorder-projection.js +49 -0
- package/dist/src/commands/patch/reorder-shift.d.ts +30 -0
- package/dist/src/commands/patch/reorder-shift.js +307 -0
- package/dist/src/commands/patch/reorder.d.ts +9 -15
- package/dist/src/commands/patch/reorder.js +52 -50
- package/dist/src/commands/patch/split-plan.d.ts +31 -3
- package/dist/src/commands/patch/split-plan.js +36 -12
- package/dist/src/commands/patch/split-staged.d.ts +2 -2
- package/dist/src/commands/patch/split-staged.js +2 -2
- package/dist/src/commands/patch/split.js +18 -5
- package/dist/src/commands/patch/staged-dependency-entries.d.ts +9 -1
- package/dist/src/commands/patch/staged-dependency-entries.js +32 -4
- package/dist/src/commands/patch/staged-dependency-from.js +15 -9
- package/dist/src/commands/patch/staged-dependency.js +13 -9
- package/dist/src/commands/patch/tier.js +2 -2
- package/dist/src/commands/patch-rename-map.d.ts +14 -3
- package/dist/src/commands/patch-rename-map.js +21 -3
- package/dist/src/commands/re-export-adjacent.d.ts +4 -5
- package/dist/src/commands/re-export-lint.d.ts +4 -3
- package/dist/src/commands/re-export-lint.js +4 -3
- package/dist/src/commands/re-export-preflight.js +1 -2
- package/dist/src/commands/re-export-purity-scope.d.ts +1 -1
- package/dist/src/commands/re-export-purity-scope.js +13 -7
- package/dist/src/commands/re-export-retired-declarations.d.ts +22 -0
- package/dist/src/commands/re-export-retired-declarations.js +113 -0
- package/dist/src/commands/re-export-single.js +2 -2
- package/dist/src/commands/re-export-stale-registrations.d.ts +27 -6
- package/dist/src/commands/re-export-stale-registrations.js +65 -21
- package/dist/src/commands/re-export.js +4 -0
- package/dist/src/commands/rebase/continue.js +3 -3
- package/dist/src/commands/register.js +5 -4
- package/dist/src/commands/status.js +1 -1
- package/dist/src/commands/test-build-furnace.d.ts +1 -2
- package/dist/src/commands/test-build-furnace.js +1 -2
- package/dist/src/commands/test-build-phase.d.ts +8 -0
- package/dist/src/commands/test-build-phase.js +42 -7
- package/dist/src/commands/test-control-restore.d.ts +40 -0
- package/dist/src/commands/test-control-restore.js +86 -0
- package/dist/src/commands/test-dispatch.js +68 -7
- package/dist/src/commands/test-multi-verdict.js +1 -0
- package/dist/src/commands/test-orchestrate.d.ts +6 -0
- package/dist/src/commands/test-orchestrate.js +28 -0
- package/dist/src/commands/test-perf-scope.d.ts +1 -1
- package/dist/src/commands/test-perf-scope.js +1 -1
- package/dist/src/commands/test-prelock.d.ts +7 -8
- package/dist/src/commands/test-prelock.js +15 -12
- package/dist/src/commands/test-register.js +2 -2
- package/dist/src/commands/test-results.d.ts +10 -1
- package/dist/src/commands/test-results.js +20 -3
- package/dist/src/commands/test-run.d.ts +6 -0
- package/dist/src/commands/test-run.js +23 -4
- package/dist/src/commands/test-shards.d.ts +7 -3
- package/dist/src/commands/test-shards.js +24 -7
- package/dist/src/commands/test-stale-gate.d.ts +6 -1
- package/dist/src/commands/test-stale-gate.js +40 -2
- package/dist/src/commands/test-verdict.d.ts +5 -3
- package/dist/src/commands/test.js +10 -0
- package/dist/src/commands/token.js +2 -2
- package/dist/src/commands/verify.js +1 -1
- package/dist/src/commands/watch.js +1 -1
- package/dist/src/commands/wire.js +1 -1
- package/dist/src/core/build-audit-resolve.d.ts +4 -5
- package/dist/src/core/build-audit-resolve.js +4 -5
- package/dist/src/core/build-audit-skip.d.ts +2 -2
- package/dist/src/core/build-audit.d.ts +3 -4
- package/dist/src/core/build-baseline-types.d.ts +24 -3
- package/dist/src/core/build-baseline-validate.d.ts +30 -1
- package/dist/src/core/build-baseline-validate.js +127 -35
- package/dist/src/core/build-baseline.d.ts +8 -2
- package/dist/src/core/build-baseline.js +25 -16
- package/dist/src/core/build-jar-escalation.d.ts +4 -4
- package/dist/src/core/build-jar-escalation.js +4 -4
- package/dist/src/core/build-prepare.js +4 -4
- package/dist/src/core/config-validate.js +4 -4
- package/dist/src/core/coverage-extend.d.ts +5 -3
- package/dist/src/core/coverage-extend.js +8 -3
- package/dist/src/core/coverage-records.d.ts +4 -5
- package/dist/src/core/coverage-records.js +4 -5
- package/dist/src/core/destructive.d.ts +2 -2
- package/dist/src/core/destructive.js +2 -2
- package/dist/src/core/discard-baseline.d.ts +2 -2
- package/dist/src/core/discard-baseline.js +3 -3
- package/dist/src/core/engine-session-lock.d.ts +1 -1
- package/dist/src/core/engine-session-lock.js +1 -1
- package/dist/src/core/file-lock-owner.d.ts +5 -5
- package/dist/src/core/file-lock-owner.js +5 -5
- package/dist/src/core/file-lock-queue.js +6 -8
- package/dist/src/core/file-lock-shared.d.ts +4 -4
- package/dist/src/core/file-lock-shared.js +4 -4
- package/dist/src/core/file-lock.js +7 -10
- package/dist/src/core/firefox.js +2 -2
- package/dist/src/core/furnace-apply-overwrite-warn.d.ts +1 -1
- package/dist/src/core/furnace-apply-overwrite-warn.js +1 -1
- package/dist/src/core/furnace-apply.js +3 -3
- package/dist/src/core/furnace-operation.js +5 -5
- package/dist/src/core/furnace-registration-jar-inplace.js +5 -6
- package/dist/src/core/furnace-registration-rename.d.ts +5 -5
- package/dist/src/core/furnace-registration-rename.js +5 -5
- package/dist/src/core/furnace-registration-validate.d.ts +2 -1
- package/dist/src/core/furnace-registration-validate.js +2 -1
- package/dist/src/core/furnace-registration.js +2 -2
- package/dist/src/core/git-base.js +4 -3
- package/dist/src/core/git-diff.js +1 -1
- package/dist/src/core/git.js +1 -1
- package/dist/src/core/harness-orphans.d.ts +6 -6
- package/dist/src/core/harness-orphans.js +6 -6
- package/dist/src/core/harness-port-reservation.d.ts +60 -0
- package/dist/src/core/harness-port-reservation.js +122 -0
- package/dist/src/core/history-log-file.d.ts +9 -9
- package/dist/src/core/history-log-file.js +15 -15
- package/dist/src/core/history-log.d.ts +3 -3
- package/dist/src/core/history-log.js +3 -3
- package/dist/src/core/launchable-build.d.ts +39 -0
- package/dist/src/core/launchable-build.js +85 -0
- package/dist/src/core/marionette-port.js +1 -3
- package/dist/src/core/moz-manifest-rules.js +3 -2
- package/dist/src/core/negative-control-compiled.d.ts +13 -3
- package/dist/src/core/negative-control-compiled.js +27 -5
- package/dist/src/core/parser-fallback.d.ts +5 -5
- package/dist/src/core/parser-fallback.js +5 -5
- package/dist/src/core/patch-identifier-suggest.d.ts +6 -0
- package/dist/src/core/patch-identifier-suggest.js +11 -4
- package/dist/src/core/patch-lint-checkjs.d.ts +1 -1
- package/dist/src/core/patch-lint-checkjs.js +1 -1
- package/dist/src/core/patch-lint-css.js +2 -2
- package/dist/src/core/patch-lint-file-size.d.ts +5 -7
- package/dist/src/core/patch-lint-file-size.js +5 -7
- package/dist/src/core/patch-lint-ignore.d.ts +3 -3
- package/dist/src/core/patch-lint-ignore.js +3 -3
- package/dist/src/core/patch-lint-prettier.d.ts +4 -6
- package/dist/src/core/patch-lint-prettier.js +4 -6
- package/dist/src/core/patch-lint-projection.d.ts +1 -1
- package/dist/src/core/patch-lint-projection.js +1 -1
- package/dist/src/core/patch-lint-queue-types.d.ts +2 -2
- package/dist/src/core/patch-lint-queue-types.js +2 -2
- package/dist/src/core/patch-manifest-consistency.d.ts +2 -2
- package/dist/src/core/patch-manifest-consistency.js +2 -2
- package/dist/src/core/patch-manifest-io.d.ts +5 -1
- package/dist/src/core/patch-manifest-io.js +12 -10
- package/dist/src/core/patch-manifest-key-order.d.ts +3 -4
- package/dist/src/core/patch-manifest-key-order.js +3 -4
- package/dist/src/core/patch-parse.d.ts +3 -3
- package/dist/src/core/patch-parse.js +3 -3
- package/dist/src/core/patch-policy.d.ts +1 -1
- package/dist/src/core/patch-policy.js +1 -1
- package/dist/src/core/patch-source-metadata.d.ts +1 -1
- package/dist/src/core/patch-source-metadata.js +1 -1
- package/dist/src/core/patch-subset.d.ts +5 -3
- package/dist/src/core/patch-subset.js +8 -7
- package/dist/src/core/patch-transform.d.ts +2 -2
- package/dist/src/core/patch-transform.js +2 -2
- package/dist/src/core/rebase-session.js +4 -6
- package/dist/src/core/register-xpcshell-test.d.ts +28 -7
- package/dist/src/core/register-xpcshell-test.js +76 -27
- package/dist/src/core/run-log.d.ts +8 -8
- package/dist/src/core/run-log.js +8 -8
- package/dist/src/core/status-classify.d.ts +1 -2
- package/dist/src/core/status-classify.js +1 -2
- package/dist/src/core/test-harness-crash.d.ts +5 -3
- package/dist/src/core/test-harness-crash.js +13 -14
- package/dist/src/core/test-harness-infra.d.ts +32 -0
- package/dist/src/core/test-harness-infra.js +69 -0
- package/dist/src/core/test-harness-signature.d.ts +6 -0
- package/dist/src/core/test-stale-check.d.ts +38 -0
- package/dist/src/core/test-stale-check.js +82 -1
- package/dist/src/core/test-stall-triage.js +5 -7
- package/dist/src/core/token-category.js +2 -2
- package/dist/src/core/token-inventory.js +3 -3
- package/dist/src/core/token-manager.d.ts +2 -2
- package/dist/src/core/token-manager.js +5 -7
- package/dist/src/core/token-variant.d.ts +6 -6
- package/dist/src/core/token-variant.js +7 -7
- package/dist/src/core/typecheck-shim.js +1 -1
- package/dist/src/core/wire-destroy.d.ts +1 -1
- package/dist/src/core/wire-destroy.js +1 -1
- package/dist/src/core/wire-dom-fragment.js +1 -1
- package/dist/src/core/wire-init.d.ts +1 -1
- package/dist/src/core/wire-init.js +1 -1
- package/dist/src/core/wire-subscript.d.ts +1 -1
- package/dist/src/core/wire-subscript.js +1 -1
- package/dist/src/core/wire-utils.d.ts +2 -2
- package/dist/src/core/wire-utils.js +3 -3
- package/dist/src/errors/base.d.ts +1 -1
- package/dist/src/errors/base.js +1 -1
- package/dist/src/errors/rebase.d.ts +1 -1
- package/dist/src/errors/rebase.js +1 -1
- package/dist/src/types/commands/options.d.ts +26 -3
- package/dist/src/types/config.d.ts +5 -7
- package/dist/src/utils/options.js +2 -2
- package/dist/src/utils/process.js +2 -2
- package/dist/src/utils/regex.d.ts +2 -2
- package/dist/src/utils/regex.js +3 -3
- package/dist/src/utils/sleep.d.ts +5 -6
- package/dist/src/utils/sleep.js +5 -6
- package/dist/src/utils/validation.js +2 -2
- package/docs/configuration.md +21 -23
- package/docs/exit-codes.md +8 -11
- package/docs/furnace.md +3 -3
- package/docs/lifecycle-invariants.md +36 -45
- package/docs/machine-output.md +41 -24
- package/docs/patch-workflow.md +129 -24
- package/docs/run-logs.md +8 -9
- package/docs/testing.md +105 -46
- package/package.json +1 -1
|
@@ -22,6 +22,8 @@
|
|
|
22
22
|
* legitimately have a fresh `dist/` with no FireForge-recorded baseline
|
|
23
23
|
* update.
|
|
24
24
|
*/
|
|
25
|
+
import { stat } from 'node:fs/promises';
|
|
26
|
+
import { join, relative } from 'node:path';
|
|
25
27
|
import { toError } from '../utils/errors.js';
|
|
26
28
|
import { verbose, warn } from '../utils/logger.js';
|
|
27
29
|
import { normalizePathSlashes } from '../utils/paths.js';
|
|
@@ -30,6 +32,8 @@ import { readBuildBaseline } from './build-baseline.js';
|
|
|
30
32
|
import { hashEngineFile } from './coverage-extend.js';
|
|
31
33
|
import { isTestManifestPath } from './coverage-records.js';
|
|
32
34
|
import { collectChangedEnginePaths, dropPathsMatchingFingerprints } from './engine-changes.js';
|
|
35
|
+
import { readLinkedAt } from './launchable-build.js';
|
|
36
|
+
import { isCompiledSourcePath } from './negative-control-compiled.js';
|
|
33
37
|
import { formatStaleExemptions, partitionStaleCandidates, } from './test-stale-exempt.js';
|
|
34
38
|
/** Cap on the number of changed paths rendered inline. */
|
|
35
39
|
const STALE_PATHS_LIMIT = 10;
|
|
@@ -91,6 +95,83 @@ export function formatStaleBuildWarning(result) {
|
|
|
91
95
|
'"fireforge build --ui") first. Passing --build skips this check.' +
|
|
92
96
|
exemptLine);
|
|
93
97
|
}
|
|
98
|
+
/**
|
|
99
|
+
* Path segments whose compiled sources never reach the binary under test
|
|
100
|
+
* (gtests, cppunittests, CI config YAML): an edit there must not make the
|
|
101
|
+
* browser read as stale.
|
|
102
|
+
*/
|
|
103
|
+
const NON_RUNTIME_SEGMENTS = new Set(['test', 'tests', 'gtest', 'testing', 'taskcluster']);
|
|
104
|
+
/**
|
|
105
|
+
* Changed compiled sources (C++, Rust, IDL, WebIDL, IPDL, StaticPrefList
|
|
106
|
+
* YAML, …) whose mtime is newer than the launchable build's last link.
|
|
107
|
+
* `mach build faster` compiles none of them, so such a run tests the
|
|
108
|
+
* binary from before the edit, which reads as a failed fix rather than a
|
|
109
|
+
* stale build. Candidates are the engine paths changed since the baseline
|
|
110
|
+
* plus every workdir edit; a fork's persistent patch diff is older than any
|
|
111
|
+
* build that followed it, so only genuine post-build edits remain.
|
|
112
|
+
* Returns undefined when there is nothing to compare against (no
|
|
113
|
+
* launchable binary).
|
|
114
|
+
*
|
|
115
|
+
* @param engineDir - Absolute engine directory
|
|
116
|
+
* @param baseline - Last-build baseline, when one exists
|
|
117
|
+
* @param launchablePath - Engine-relative launchable binary path
|
|
118
|
+
*/
|
|
119
|
+
export async function findCompiledSourcesNewerThanBinary(engineDir, baseline, launchablePath) {
|
|
120
|
+
if (launchablePath === undefined)
|
|
121
|
+
return undefined;
|
|
122
|
+
const linked = await readLinkedAt(engineDir, launchablePath);
|
|
123
|
+
if (linked === undefined)
|
|
124
|
+
return undefined;
|
|
125
|
+
const changed = await collectChangedEnginePaths(engineDir, baseline, 'Stale-compiled preflight');
|
|
126
|
+
const candidates = changed.filter((path) => isCompiledSourcePath(path) &&
|
|
127
|
+
!path.split('/').some((segment) => NON_RUNTIME_SEGMENTS.has(segment)));
|
|
128
|
+
const paths = [];
|
|
129
|
+
for (const path of candidates) {
|
|
130
|
+
try {
|
|
131
|
+
const { mtimeMs } = await stat(join(engineDir, path));
|
|
132
|
+
if (mtimeMs > linked.mtimeMs)
|
|
133
|
+
paths.push(path);
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
// A deleted source cannot be newer than anything; the build that
|
|
137
|
+
// drops it is the stale-build check's business.
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
paths: paths.sort(),
|
|
142
|
+
linkedPath: relative(engineDir, linked.path),
|
|
143
|
+
linkedAt: new Date(linked.mtimeMs),
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* The `stale-compiled` refusal (or, under `--allow-stale-build`, warning).
|
|
148
|
+
*
|
|
149
|
+
* @param result - A non-empty {@link StaleCompiledResult}
|
|
150
|
+
*/
|
|
151
|
+
export function formatStaleCompiledRefusal(result) {
|
|
152
|
+
const head = result.paths.slice(0, STALE_PATHS_LIMIT).map((path) => `engine/${path}`);
|
|
153
|
+
const truncated = result.paths.length - head.length;
|
|
154
|
+
const list = head.join(', ') + (truncated > 0 ? `, … (+${truncated} more)` : '');
|
|
155
|
+
return (`Compiled sources changed after the binary under test was linked ` +
|
|
156
|
+
`(engine/${result.linkedPath}, ${result.linkedAt.toISOString()}): ${list}.\n` +
|
|
157
|
+
'The run would test the binary from before those edits, so a red reads as a failed fix ' +
|
|
158
|
+
'and a green proves nothing about them. Run "fireforge build" first, or rerun with ' +
|
|
159
|
+
'"fireforge test --build", which escalates to a full mach build when compiled sources ' +
|
|
160
|
+
'changed. --allow-stale-build turns this refusal into a warning.');
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* The notice that explains why a `test --build` pre-test build escalated
|
|
164
|
+
* to a full `mach build` for stale compiled sources.
|
|
165
|
+
*
|
|
166
|
+
* @param result - A non-empty {@link StaleCompiledResult}
|
|
167
|
+
*/
|
|
168
|
+
export function formatStaleCompiledBuildNotice(result) {
|
|
169
|
+
const head = result.paths.slice(0, STALE_PATHS_LIMIT).map((path) => `engine/${path}`);
|
|
170
|
+
const truncated = result.paths.length - head.length;
|
|
171
|
+
return (`Compiled sources changed after the binary was linked (${head.join(', ')}` +
|
|
172
|
+
`${truncated > 0 ? `, … (+${truncated} more)` : ''}); escalating this pre-test build to a ` +
|
|
173
|
+
'full mach build, since mach build faster compiles nothing.');
|
|
174
|
+
}
|
|
94
175
|
/**
|
|
95
176
|
* Sentinel returned by {@link findUncoveredRequestPaths} when a full-suite
|
|
96
177
|
* request (no paths) is checked against a scoped coverage record.
|
|
@@ -200,7 +281,7 @@ export function formatTestCoverageRefusal(uncovered, coverage, changedManifests
|
|
|
200
281
|
};
|
|
201
282
|
const rebuildTargets = uncovered.filter((p) => p !== FULL_SUITE_REQUEST);
|
|
202
283
|
// Per-path retention is the default, so rebuilding only the uncovered
|
|
203
|
-
// paths no
|
|
284
|
+
// paths costs no one else's claim. Saying so is what keeps a
|
|
204
285
|
// peer from rebuilding everything "to be safe".
|
|
205
286
|
const keepHint = rebuildTargets.length > 0
|
|
206
287
|
? ' That scoped build keeps every other recorded path whose own staging inputs (manifest directory and the fixtures its manifest names) and engine/mozconfig are unchanged.'
|
|
@@ -37,9 +37,8 @@ const NO_OUTPUT_STALL_CONTROL_STEP = 'First, run a known-good control test. If t
|
|
|
37
37
|
* - (4) is mechanical and was root-caused downstream: the harness serves
|
|
38
38
|
* its manifest from `server.js` on 8888, and a survivor of an
|
|
39
39
|
* interrupted run keeps the port. Its probe is exact, and the preflight
|
|
40
|
-
* in `mochitest-server-port.ts`
|
|
41
|
-
* - (3) is
|
|
42
|
-
* earlier revision recorded. A `chrome://` (or `resource://`) URL that
|
|
40
|
+
* in `mochitest-server-port.ts` refuses it before a run starts.
|
|
41
|
+
* - (3) is mechanical and root-caused. A `chrome://` (or `resource://`) URL that
|
|
43
42
|
* resolves to nothing reaches `CheckForBrokenChromeURL`
|
|
44
43
|
* (netwerk/base/nsNetUtil.cpp), which outside automation only
|
|
45
44
|
* `printf_stderr`s `Missing chrome or resource URL: <uri>`, but under
|
|
@@ -47,9 +46,8 @@ const NO_OUTPUT_STALL_CONTROL_STEP = 'First, run a known-good control test. If t
|
|
|
47
46
|
* `MOZ_CRASH_UNSAFE_PRINTF("Missing chrome or resource URLs: %s")`. A
|
|
48
47
|
* downstream reproduction symbolicated the faulting frame as
|
|
49
48
|
* `CheckForBrokenChromeURL`, which is the established diagnosis the bar
|
|
50
|
-
* in `mach-error-hints.ts` asks for.
|
|
51
|
-
*
|
|
52
|
-
* failed image load in Gecko fires `error` and does not gate the
|
|
49
|
+
* in `mach-error-hints.ts` asks for. It is not a "stalls first paint"
|
|
50
|
+
* problem: a failed image load in Gecko fires `error` and does not gate the
|
|
53
51
|
* document load event.
|
|
54
52
|
*
|
|
55
53
|
* Detection by log line is not specified for (3), because of the mechanism
|
|
@@ -62,7 +60,7 @@ const NO_OUTPUT_STALL_CONTROL_STEP = 'First, run a known-good control test. If t
|
|
|
62
60
|
* the census points at the two artefacts that do carry it: the OS crash
|
|
63
61
|
* report (whose faulting frame names `CheckForBrokenChromeURL`) and the
|
|
64
62
|
* out-of-automation smoke probe (which prints the non-crashing spelling
|
|
65
|
-
* and
|
|
63
|
+
* and counts it as an unallowed error so the exit code
|
|
66
64
|
* agrees with the capture).
|
|
67
65
|
*/
|
|
68
66
|
const NO_OUTPUT_STALL_TRIAGE = [
|
|
@@ -18,8 +18,8 @@ import { escapeRegex } from '../utils/regex.js';
|
|
|
18
18
|
* Body of the first `/* … *\/` comment on `line`, or `undefined` when the
|
|
19
19
|
* line carries no closed block comment.
|
|
20
20
|
*
|
|
21
|
-
* This uses index arithmetic rather than a regex:
|
|
22
|
-
* "banner comment"
|
|
21
|
+
* This uses index arithmetic rather than a regex: the natural regex
|
|
22
|
+
* spellings of "banner comment" are super-linear on a line that
|
|
23
23
|
* repeats the opening shape (CodeQL `js/polynomial-redos`), and `tokens.css`
|
|
24
24
|
* is a file FireForge reads out of a consumer's engine tree, so a
|
|
25
25
|
* pathological line needs no attacker to arrive.
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
* tokens each declares, and what a single token resolves to in every theme
|
|
5
5
|
* block that mentions it.
|
|
6
6
|
*
|
|
7
|
-
* `token add` requires `--category
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* `token add` requires `--category`, so it needs a report of the categories
|
|
8
|
+
* a project actually has; without one, the only way to name one correctly
|
|
9
|
+
* is to hand-parse a neighbouring `= Category =` banner out of the file.
|
|
10
10
|
* This module is that report. It reuses the banner and
|
|
11
11
|
* category-region model from `token-category.ts` rather than parsing
|
|
12
12
|
* tokens CSS a second way: two readers that disagree on what a banner is
|
|
@@ -4,7 +4,7 @@ import { type TokenDeclarationLocation } from './token-category.js';
|
|
|
4
4
|
*
|
|
5
5
|
* Derived from {@link TOKEN_MODES} so the runtime allowlist and the type
|
|
6
6
|
* cannot drift: adding a member here without updating the list (or the
|
|
7
|
-
* reverse) is
|
|
7
|
+
* reverse) is impossible, because there is only one list.
|
|
8
8
|
*/
|
|
9
9
|
export declare const TOKEN_MODES: readonly ["auto", "static", "override"];
|
|
10
10
|
/** Dark mode behaviour for a token. */
|
|
@@ -21,7 +21,7 @@ export interface AddTokenOptions {
|
|
|
21
21
|
value: string;
|
|
22
22
|
/**
|
|
23
23
|
* Token category matching section headers in the CSS file. Required for a
|
|
24
|
-
* base declaration. Ignored, and
|
|
24
|
+
* base declaration. Ignored, and not required, under
|
|
25
25
|
* {@link AddTokenOptions.variant}, which routes into a `:root<selector>`
|
|
26
26
|
* block and never touches a category section.
|
|
27
27
|
*/
|
|
@@ -17,7 +17,7 @@ import { findVariantBlockDeclaration, insertVariantDeclaration, validateVariantS
|
|
|
17
17
|
*
|
|
18
18
|
* Derived from {@link TOKEN_MODES} so the runtime allowlist and the type
|
|
19
19
|
* cannot drift: adding a member here without updating the list (or the
|
|
20
|
-
* reverse) is
|
|
20
|
+
* reverse) is impossible, because there is only one list.
|
|
21
21
|
*/
|
|
22
22
|
export const TOKEN_MODES = ['auto', 'static', 'override'];
|
|
23
23
|
/** Narrows an arbitrary string to a {@link TokenMode}. */
|
|
@@ -109,12 +109,10 @@ function normalizeVariantOption(options) {
|
|
|
109
109
|
* Narrows {@link AddTokenOptions.category} for the base-declaration path,
|
|
110
110
|
* which cannot proceed without one.
|
|
111
111
|
*
|
|
112
|
-
* `--category`
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
* a fair goal that produced a mandatory argument describing nothing. Under
|
|
117
|
-
* a variant it is now optional. Everywhere else this states the reason
|
|
112
|
+
* `--category` is optional under `--variant`, where the declaration is
|
|
113
|
+
* routed into a `:root<selector>` block and the category names nothing
|
|
114
|
+
* about where the token lands, so requiring it there would make a
|
|
115
|
+
* mandatory argument describing nothing. Everywhere else this states the reason
|
|
118
116
|
* rather than leaving commander to print a bare "required option not
|
|
119
117
|
* specified".
|
|
120
118
|
*
|
|
@@ -28,12 +28,12 @@ export type VariantValidation = {
|
|
|
28
28
|
* Boolean-attribute fragments are returned unchanged.
|
|
29
29
|
*
|
|
30
30
|
* Structure is decided by {@link rootAttributeSelector}, the matcher's own
|
|
31
|
-
* parse, rather than by a second regex.
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* `:root[data-skin="humanist"]:not([data-private])`
|
|
35
|
-
*
|
|
36
|
-
*
|
|
31
|
+
* parse, rather than by a second regex. The matcher consumes consecutive
|
|
32
|
+
* `[…]` groups and stops at a pseudo-class tail, and a separate validator
|
|
33
|
+
* that does not follow it leaves blocks such as
|
|
34
|
+
* `:root[data-skin="humanist"]:not([data-private])` findable but
|
|
35
|
+
* unnameable. Running both halves off one parse keeps them from drifting
|
|
36
|
+
* apart. Character-level safety stays a
|
|
37
37
|
* separate, per-group check, because the matcher finds bracket boundaries
|
|
38
38
|
* and validates no characters at all.
|
|
39
39
|
*
|
|
@@ -68,12 +68,12 @@ function normalizeAttributeFragment(group) {
|
|
|
68
68
|
* Boolean-attribute fragments are returned unchanged.
|
|
69
69
|
*
|
|
70
70
|
* Structure is decided by {@link rootAttributeSelector}, the matcher's own
|
|
71
|
-
* parse, rather than by a second regex.
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
* `:root[data-skin="humanist"]:not([data-private])`
|
|
75
|
-
*
|
|
76
|
-
*
|
|
71
|
+
* parse, rather than by a second regex. The matcher consumes consecutive
|
|
72
|
+
* `[…]` groups and stops at a pseudo-class tail, and a separate validator
|
|
73
|
+
* that does not follow it leaves blocks such as
|
|
74
|
+
* `:root[data-skin="humanist"]:not([data-private])` findable but
|
|
75
|
+
* unnameable. Running both halves off one parse keeps them from drifting
|
|
76
|
+
* apart. Character-level safety stays a
|
|
77
77
|
* separate, per-group check, because the matcher finds bracket boundaries
|
|
78
78
|
* and validates no characters at all.
|
|
79
79
|
*
|
|
@@ -194,7 +194,7 @@ function findVariantBlock(lines, variant) {
|
|
|
194
194
|
if (selector === undefined || canonicalSelector(selector.attributes) !== want)
|
|
195
195
|
continue;
|
|
196
196
|
// An unqualified request still matches a qualified block: that is the
|
|
197
|
-
//
|
|
197
|
+
// behaviour `variantBlockQualifier` exists to report, since
|
|
198
198
|
// silently skipping the block is the worse failure. A request that names
|
|
199
199
|
// a qualifier, though, means it, so it must match.
|
|
200
200
|
if (wantQualifier !== '' && canonicalSelector(selector.qualifier) !== wantQualifier)
|
|
@@ -291,7 +291,7 @@ export const UNDEFINED_IDENTIFIER_CODES = new Set([
|
|
|
291
291
|
]);
|
|
292
292
|
/**
|
|
293
293
|
* Typed Lit, opt-in through `typecheck.litTypes`. Declares the two chrome
|
|
294
|
-
* modules widgets import Lit from, so they
|
|
294
|
+
* modules widgets import Lit from, so they do not fall to the
|
|
295
295
|
* `chrome:*` wildcard as `any`: `LitElement` (with `ReactiveElement`'s
|
|
296
296
|
* lifecycle) and `MozLitElement` carry closed member lists, so a misspelt
|
|
297
297
|
* member of a widget host is TS2339, as `Cu` is in the built-in shim.
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
export declare function addDestroyAST(content: string, expression: string, marker?: string): string;
|
|
13
13
|
/**
|
|
14
|
-
*
|
|
14
|
+
* Regex/line-based fallback implementation.
|
|
15
15
|
*/
|
|
16
16
|
export declare function legacyAddDestroy(content: string, expression: string, marker?: string): string;
|
|
17
17
|
/**
|
|
@@ -65,7 +65,7 @@ export function addDestroyAST(content, expression, marker = DEFAULT_MARKER) {
|
|
|
65
65
|
return ms.toString();
|
|
66
66
|
}
|
|
67
67
|
/**
|
|
68
|
-
*
|
|
68
|
+
* Regex/line-based fallback implementation.
|
|
69
69
|
*/
|
|
70
70
|
export function legacyAddDestroy(content, expression, marker = DEFAULT_MARKER) {
|
|
71
71
|
const name = extractNameFromExpression(expression);
|
|
@@ -66,7 +66,7 @@ export async function probeDomFragmentInsertionPoint(engineDir, domFilePath, tar
|
|
|
66
66
|
// dry-run is allowed to proceed too.
|
|
67
67
|
return;
|
|
68
68
|
}
|
|
69
|
-
// Check the tokenised and
|
|
69
|
+
// Check the tokenised and line-based insertion paths symmetrically with
|
|
70
70
|
// the real run. Either helper returning without throwing is sufficient
|
|
71
71
|
// evidence that the real run can land the directive.
|
|
72
72
|
addDomFragmentTokenized(content, includeDirective);
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
export declare function addInitAST(content: string, expression: string, after?: string, marker?: string): string;
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
16
|
+
* Regex/line-based fallback implementation.
|
|
17
17
|
*/
|
|
18
18
|
export declare function legacyAddInit(content: string, expression: string, after?: string, marker?: string): string;
|
|
19
19
|
/**
|
|
@@ -112,7 +112,7 @@ export function addInitAST(content, expression, after, marker = DEFAULT_MARKER)
|
|
|
112
112
|
return ms.toString();
|
|
113
113
|
}
|
|
114
114
|
/**
|
|
115
|
-
*
|
|
115
|
+
* Regex/line-based fallback implementation.
|
|
116
116
|
*/
|
|
117
117
|
export function legacyAddInit(content, expression, after, marker = DEFAULT_MARKER) {
|
|
118
118
|
const name = extractNameFromExpression(expression);
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
export declare function addSubscriptAST(content: string, name: string, marker?: string): string;
|
|
12
12
|
/**
|
|
13
|
-
*
|
|
13
|
+
* Regex/line-based fallback implementation.
|
|
14
14
|
*/
|
|
15
15
|
export declare function legacyAddSubscript(content: string, name: string, marker?: string): string;
|
|
16
16
|
/**
|
|
@@ -73,7 +73,7 @@ export function addSubscriptAST(content, name, marker = DEFAULT_MARKER) {
|
|
|
73
73
|
return ms.toString();
|
|
74
74
|
}
|
|
75
75
|
/**
|
|
76
|
-
*
|
|
76
|
+
* Regex/line-based fallback implementation.
|
|
77
77
|
*/
|
|
78
78
|
export function legacyAddSubscript(content, name, marker = DEFAULT_MARKER) {
|
|
79
79
|
const lines = content.split('\n');
|
|
@@ -104,7 +104,7 @@ export declare function walkToTryBlockEnd(lines: string[], startLine: number, op
|
|
|
104
104
|
}): number;
|
|
105
105
|
/**
|
|
106
106
|
* Scans the entire file and returns the net brace balance so callers can
|
|
107
|
-
* assert that a
|
|
107
|
+
* assert that a line-based fallback mutation did not silently introduce or
|
|
108
108
|
* drop a `{` / `}`. The helper reuses {@link countBraceDepth} so strings,
|
|
109
109
|
* comments, and regex literals are handled consistently with the walker.
|
|
110
110
|
*
|
|
@@ -117,7 +117,7 @@ export declare function computeFileBraceBalance(content: string): {
|
|
|
117
117
|
balanced: boolean;
|
|
118
118
|
};
|
|
119
119
|
/**
|
|
120
|
-
* Round-trip guard used after a
|
|
120
|
+
* Round-trip guard used after a line-based fallback mutation: if the file's
|
|
121
121
|
* net brace balance drifts between `before` and `after`, something went
|
|
122
122
|
* wrong and the fallback is refusing to write a corrupted file. Expects
|
|
123
123
|
* the delta to be exactly zero, since wire fallbacks only insert whole
|
|
@@ -159,7 +159,7 @@ export function tokenizeXhtml(lines) {
|
|
|
159
159
|
});
|
|
160
160
|
}
|
|
161
161
|
// ---------------------------------------------------------------------------
|
|
162
|
-
//
|
|
162
|
+
// Line-based helpers, shared by fallback implementations in
|
|
163
163
|
// the wire target modules. Extracted to reduce duplication and make the brace-
|
|
164
164
|
// walking logic independently testable.
|
|
165
165
|
// ---------------------------------------------------------------------------
|
|
@@ -224,7 +224,7 @@ export function walkToTryBlockEnd(lines, startLine, options) {
|
|
|
224
224
|
}
|
|
225
225
|
/**
|
|
226
226
|
* Scans the entire file and returns the net brace balance so callers can
|
|
227
|
-
* assert that a
|
|
227
|
+
* assert that a line-based fallback mutation did not silently introduce or
|
|
228
228
|
* drop a `{` / `}`. The helper reuses {@link countBraceDepth} so strings,
|
|
229
229
|
* comments, and regex literals are handled consistently with the walker.
|
|
230
230
|
*
|
|
@@ -244,7 +244,7 @@ export function computeFileBraceBalance(content) {
|
|
|
244
244
|
return { depth, balanced: depth === 0 };
|
|
245
245
|
}
|
|
246
246
|
/**
|
|
247
|
-
* Round-trip guard used after a
|
|
247
|
+
* Round-trip guard used after a line-based fallback mutation: if the file's
|
|
248
248
|
* net brace balance drifts between `before` and `after`, something went
|
|
249
249
|
* wrong and the fallback is refusing to write a corrupted file. Expects
|
|
250
250
|
* the delta to be exactly zero, since wire fallbacks only insert whole
|
|
@@ -80,7 +80,7 @@ export declare class InternalInvariantError extends FireForgeError {
|
|
|
80
80
|
get userMessage(): string;
|
|
81
81
|
}
|
|
82
82
|
/**
|
|
83
|
-
* Raised when a
|
|
83
|
+
* Raised when a regex/brace-depth fallback parser decides it
|
|
84
84
|
* cannot safely perform its mutation, e.g. because a block it expected
|
|
85
85
|
* to walk never closes, because the inserted result fails a round-trip
|
|
86
86
|
* brace balance check, or because an expected pattern is missing.
|
package/dist/src/errors/base.js
CHANGED
|
@@ -106,7 +106,7 @@ export class InternalInvariantError extends FireForgeError {
|
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
108
|
/**
|
|
109
|
-
* Raised when a
|
|
109
|
+
* Raised when a regex/brace-depth fallback parser decides it
|
|
110
110
|
* cannot safely perform its mutation, e.g. because a block it expected
|
|
111
111
|
* to walk never closes, because the inserted result fails a round-trip
|
|
112
112
|
* brace balance check, or because an expected pattern is missing.
|
|
@@ -33,7 +33,7 @@ export declare class CorruptRebaseSessionError extends RebaseError {
|
|
|
33
33
|
}
|
|
34
34
|
/**
|
|
35
35
|
* Thrown by `rebase --dry-run` when the replay rejects at least one patch.
|
|
36
|
-
* A dry run that exited 0 regardless
|
|
36
|
+
* A dry run that exited 0 regardless would read as "the rebase is ready".
|
|
37
37
|
*/
|
|
38
38
|
export declare class RebaseDryRunRejectError extends RebaseError {
|
|
39
39
|
readonly rejected: readonly string[];
|
|
@@ -51,7 +51,7 @@ export class CorruptRebaseSessionError extends RebaseError {
|
|
|
51
51
|
}
|
|
52
52
|
/**
|
|
53
53
|
* Thrown by `rebase --dry-run` when the replay rejects at least one patch.
|
|
54
|
-
* A dry run that exited 0 regardless
|
|
54
|
+
* A dry run that exited 0 regardless would read as "the rebase is ready".
|
|
55
55
|
*/
|
|
56
56
|
export class RebaseDryRunRejectError extends RebaseError {
|
|
57
57
|
rejected;
|
|
@@ -516,6 +516,8 @@ export interface PatchSplitOptions extends Confirmable, PatchLockWaitable, Unsaf
|
|
|
516
516
|
skipLint?: boolean;
|
|
517
517
|
/** Where a refusal writes its one `--from`-ready declaration report. */
|
|
518
518
|
declarationsOut?: string;
|
|
519
|
+
/** Write the committed old-to-new filename map of renumbered patches here as JSON. */
|
|
520
|
+
mapOut?: string;
|
|
519
521
|
}
|
|
520
522
|
/**
|
|
521
523
|
* Options for the `fireforge patch move-files` subcommand. Without
|
|
@@ -541,6 +543,16 @@ export interface PatchMoveFilesOptions extends Confirmable, PatchLockWaitable, U
|
|
|
541
543
|
skipLint?: boolean;
|
|
542
544
|
/** Where a refusal writes its one `--from`-ready declaration report. */
|
|
543
545
|
declarationsOut?: string;
|
|
546
|
+
/**
|
|
547
|
+
* New engine files no patch owns, adopted into the destination in the
|
|
548
|
+
* same transaction (engine-relative, repeatable).
|
|
549
|
+
*/
|
|
550
|
+
scanFile?: string[];
|
|
551
|
+
/**
|
|
552
|
+
* Allow the move to empty the source: re-point the declarations it owns
|
|
553
|
+
* to the destination and retire its slot. Not valid with `create`.
|
|
554
|
+
*/
|
|
555
|
+
retireEmpty?: boolean;
|
|
544
556
|
}
|
|
545
557
|
/**
|
|
546
558
|
* Options for the rebase command.
|
|
@@ -673,8 +685,8 @@ export interface TestOptions extends EngineLockWaitable {
|
|
|
673
685
|
* build would overwrite engine content recorded in neither a patch body
|
|
674
686
|
* nor the pristine baseline. Same meaning as `fireforge build`'s flag of
|
|
675
687
|
* the same name. A scripted `test --build` is exactly the shape the
|
|
676
|
-
* multi-session hazard shows up in,
|
|
677
|
-
*
|
|
688
|
+
* multi-session hazard shows up in, so it must be able to arm the
|
|
689
|
+
* refusal too. Valid only with `--build`/`--build-only`.
|
|
678
690
|
*/
|
|
679
691
|
refuseUnexportedDrift?: boolean;
|
|
680
692
|
/**
|
|
@@ -1073,7 +1085,7 @@ export interface PatchRenameOptions extends Confirmable, DryRunnable, PatchLockW
|
|
|
1073
1085
|
/**
|
|
1074
1086
|
* New category (validated against configured categories). Rewrites
|
|
1075
1087
|
* the filename prefix and the manifest row in one transaction, so
|
|
1076
|
-
* recategorising
|
|
1088
|
+
* recategorising does not require `patch delete` + fresh export.
|
|
1077
1089
|
*/
|
|
1078
1090
|
category?: string;
|
|
1079
1091
|
/**
|
|
@@ -1096,6 +1108,17 @@ export interface PatchReorderOptions extends PatchLockWaitable {
|
|
|
1096
1108
|
to?: number;
|
|
1097
1109
|
before?: string;
|
|
1098
1110
|
after?: string;
|
|
1111
|
+
/**
|
|
1112
|
+
* Shift a run of patches up by this many orders (`--shift <n> --from
|
|
1113
|
+
* <order> [--through <order>]`) instead of moving one patch.
|
|
1114
|
+
*/
|
|
1115
|
+
shift?: number;
|
|
1116
|
+
/** First order of the run `shift` moves. */
|
|
1117
|
+
from?: number;
|
|
1118
|
+
/** Last order of the run `shift` moves (default: the end of the run). */
|
|
1119
|
+
through?: number;
|
|
1120
|
+
/** Write the committed old-to-new filename map here as JSON. */
|
|
1121
|
+
mapOut?: string;
|
|
1099
1122
|
yes?: boolean;
|
|
1100
1123
|
dryRun?: boolean;
|
|
1101
1124
|
forceUnsafe?: boolean;
|
|
@@ -433,11 +433,10 @@ export interface PatchLintFileSizeTier {
|
|
|
433
433
|
/**
|
|
434
434
|
* Overrides for the `file-too-large` thresholds, per file class.
|
|
435
435
|
*
|
|
436
|
-
*
|
|
437
|
-
*
|
|
438
|
-
*
|
|
439
|
-
*
|
|
440
|
-
* lines over 750 has a hard failure with no dial, at exactly the moment
|
|
436
|
+
* Configurable because the recommended gate posture is `--max-warnings 0`:
|
|
437
|
+
* under it the `warning` band is not a soft limit at all, so with fixed
|
|
438
|
+
* thresholds a project whose controllers legitimately sit a few lines over
|
|
439
|
+
* 750 would have a hard failure with no dial, at exactly the moment
|
|
441
440
|
* someone is deciding whether to restructure a file.
|
|
442
441
|
*/
|
|
443
442
|
export interface PatchLintFileSizeThresholds {
|
|
@@ -466,8 +465,7 @@ export interface PatchLintPatchSizeTier {
|
|
|
466
465
|
/**
|
|
467
466
|
* Overrides for the patch-size thresholds, per tier.
|
|
468
467
|
*
|
|
469
|
-
*
|
|
470
|
-
* general 800/1500/3000, test 1500/3000/6000, branding 8000/18000/30000;
|
|
468
|
+
* Defaults: lines general 800/1500/3000, test 1500/3000/6000, branding 8000/18000/30000;
|
|
471
469
|
* files warn above 5 (general, test) or 60 (branding). The files triple has
|
|
472
470
|
* no notice or error band by default: an unset `files.notice` follows the
|
|
473
471
|
* effective `files.warning`, and an unset `files.error` never fires.
|
|
@@ -71,8 +71,8 @@ export const WAIT_LOCK_ENV_VAR = 'FIREFORGE_WAIT_LOCK';
|
|
|
71
71
|
/**
|
|
72
72
|
* Bounds shared by the flag and the environment variable. The ceiling is a
|
|
73
73
|
* day: on a shared engine a re-export or `test --build` queued behind a
|
|
74
|
-
* peer's long series can need more than
|
|
75
|
-
* longer wait
|
|
74
|
+
* peer's long series can need more than an hour, and a cap below that turns
|
|
75
|
+
* a longer wait into a requeue after exit 15.
|
|
76
76
|
*/
|
|
77
77
|
const MIN_WAIT_LOCK_SECONDS = 1;
|
|
78
78
|
export const MAX_WAIT_LOCK_SECONDS = 86_400;
|
|
@@ -173,7 +173,7 @@ async function spawnTracked(spec) {
|
|
|
173
173
|
let rejection;
|
|
174
174
|
child.on('error', (error) => {
|
|
175
175
|
// Abort/startup failure: make sure a partially-started tree does not
|
|
176
|
-
// outlive the dispatch (a mach dying at startup
|
|
176
|
+
// outlive the dispatch (a mach dying at startup would otherwise strand
|
|
177
177
|
// multiprocessing workers).
|
|
178
178
|
if (options.processGroup === true) {
|
|
179
179
|
killProcessTree(child, 'SIGKILL', usesProcessGroup);
|
|
@@ -229,7 +229,7 @@ export async function execStream(command, args, options = {}) {
|
|
|
229
229
|
args,
|
|
230
230
|
options,
|
|
231
231
|
graceMs: 1500,
|
|
232
|
-
// A detached group leader
|
|
232
|
+
// A detached group leader does not receive the terminal's Ctrl+C, so
|
|
233
233
|
// the forwarder is mandatory (not just graceful-UX) when processGroup
|
|
234
234
|
// is set. A plain streamed child does not get one.
|
|
235
235
|
forwardWithoutProcessGroup: false,
|
|
@@ -18,7 +18,7 @@ export declare function hasRawCssColors(content: string): boolean;
|
|
|
18
18
|
* the line is blanked, corrupting whatever lint pass consumes the stripped
|
|
19
19
|
* text. The source is tokenized as a module, then as a script. Firefox
|
|
20
20
|
* chrome sources can contain constructs acorn tokenizes under neither goal.
|
|
21
|
-
* Those fall back to the
|
|
21
|
+
* Those fall back to the regex-only strip, which handles strings but not
|
|
22
22
|
* regex literals.
|
|
23
23
|
*/
|
|
24
24
|
export declare function stripJsComments(source: string): string;
|
|
@@ -30,7 +30,7 @@ export declare function stripJsComments(source: string): string;
|
|
|
30
30
|
* legacy octal escape is a tokenizer error only under the module goal.
|
|
31
31
|
* Callers that must not under-count when tokenizing fails (the code-line
|
|
32
32
|
* size metric) read the `null` and pick their own fallback rather than the
|
|
33
|
-
*
|
|
33
|
+
* regex-only strip, which can blank code.
|
|
34
34
|
*/
|
|
35
35
|
export declare function stripJsCommentsParsed(source: string): string | null;
|
|
36
36
|
/**
|
package/dist/src/utils/regex.js
CHANGED
|
@@ -34,7 +34,7 @@ export function hasRawCssColors(content) {
|
|
|
34
34
|
* the line is blanked, corrupting whatever lint pass consumes the stripped
|
|
35
35
|
* text. The source is tokenized as a module, then as a script. Firefox
|
|
36
36
|
* chrome sources can contain constructs acorn tokenizes under neither goal.
|
|
37
|
-
* Those fall back to the
|
|
37
|
+
* Those fall back to the regex-only strip, which handles strings but not
|
|
38
38
|
* regex literals.
|
|
39
39
|
*/
|
|
40
40
|
export function stripJsComments(source) {
|
|
@@ -48,7 +48,7 @@ export function stripJsComments(source) {
|
|
|
48
48
|
* legacy octal escape is a tokenizer error only under the module goal.
|
|
49
49
|
* Callers that must not under-count when tokenizing fails (the code-line
|
|
50
50
|
* size metric) read the `null` and pick their own fallback rather than the
|
|
51
|
-
*
|
|
51
|
+
* regex-only strip, which can blank code.
|
|
52
52
|
*/
|
|
53
53
|
export function stripJsCommentsParsed(source) {
|
|
54
54
|
const comments = collectJsComments(source, 'module') ?? collectJsComments(source, 'script');
|
|
@@ -91,7 +91,7 @@ function collectJsComments(source, sourceType) {
|
|
|
91
91
|
return comments;
|
|
92
92
|
}
|
|
93
93
|
/**
|
|
94
|
-
*
|
|
94
|
+
* Pure-regex comment strip, used only when acorn cannot tokenize
|
|
95
95
|
* the source (preprocessor directives, syntax errors). Strings survive.
|
|
96
96
|
* Regex literals are not modeled, so `//` inside a regex blanks the rest
|
|
97
97
|
* of the line.
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The single awaitable delay used across FireForge.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* `
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* Both behaviours now live here, and callers state which one they need.
|
|
4
|
+
* Callers use this rather than a private `sleep`/`delay` or an inline
|
|
5
|
+
* `new Promise((resolve) => setTimeout(resolve, ms))`, because such copies
|
|
6
|
+
* disagree on the one property that actually matters (whether the pending
|
|
7
|
+
* timer holds the event loop open) and the disagreement is invisible at each
|
|
8
|
+
* call site. Both behaviours live here, and callers state which one they need.
|
|
10
9
|
*
|
|
11
10
|
* The default is a ref'd timer, because the dangerous mistake is the other
|
|
12
11
|
* one: an unref'd delay awaited between a SIGTERM and its escalation lets Node
|