@hominis/fireforge 0.15.1 → 0.15.3
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 +39 -3
- package/README.md +76 -3
- package/dist/src/commands/build.js +41 -3
- package/dist/src/commands/furnace/chrome-doc-templates.d.ts +49 -0
- package/dist/src/commands/furnace/chrome-doc-templates.js +151 -0
- package/dist/src/commands/furnace/chrome-doc.d.ts +34 -0
- package/dist/src/commands/furnace/chrome-doc.js +168 -0
- package/dist/src/commands/furnace/create-mochikit.d.ts +30 -0
- package/dist/src/commands/furnace/create-mochikit.js +70 -0
- package/dist/src/commands/furnace/create-templates.d.ts +53 -0
- package/dist/src/commands/furnace/create-templates.js +118 -0
- package/dist/src/commands/furnace/create-xpcshell.d.ts +27 -0
- package/dist/src/commands/furnace/create-xpcshell.js +53 -0
- package/dist/src/commands/furnace/create.d.ts +17 -0
- package/dist/src/commands/furnace/create.js +59 -12
- package/dist/src/commands/furnace/index.d.ts +2 -1
- package/dist/src/commands/furnace/index.js +20 -2
- package/dist/src/commands/lint.d.ts +13 -1
- package/dist/src/commands/lint.js +33 -7
- package/dist/src/commands/setup.d.ts +1 -1
- package/dist/src/commands/setup.js +3 -2
- package/dist/src/core/build-audit.d.ts +46 -0
- package/dist/src/core/build-audit.js +251 -0
- package/dist/src/core/build-baseline.d.ts +59 -0
- package/dist/src/core/build-baseline.js +83 -0
- package/dist/src/core/build-prepare.d.ts +20 -1
- package/dist/src/core/build-prepare.js +94 -4
- package/dist/src/core/furnace-apply-helpers.d.ts +1 -1
- package/dist/src/core/furnace-config-tokens.d.ts +6 -0
- package/dist/src/core/furnace-config-tokens.js +15 -0
- package/dist/src/core/furnace-config.js +10 -4
- package/dist/src/core/furnace-operation.d.ts +2 -1
- package/dist/src/core/furnace-operation.js +13 -7
- package/dist/src/core/furnace-registration-ast.d.ts +2 -2
- package/dist/src/core/furnace-registration-ast.js +1 -1
- package/dist/src/core/furnace-validate-compatibility.js +18 -7
- package/dist/src/core/furnace-validate-helpers.d.ts +31 -1
- package/dist/src/core/furnace-validate-helpers.js +101 -18
- package/dist/src/core/furnace-validate-registration.d.ts +1 -1
- package/dist/src/core/furnace-validate-registration.js +1 -1
- package/dist/src/core/mach-error-hints.d.ts +29 -0
- package/dist/src/core/mach-error-hints.js +43 -0
- package/dist/src/core/mach.d.ts +5 -2
- package/dist/src/core/mach.js +31 -4
- package/dist/src/core/marionette-preflight.d.ts +14 -7
- package/dist/src/core/marionette-preflight.js +94 -44
- package/dist/src/core/patch-lint-cross.d.ts +1 -1
- package/dist/src/core/patch-lint-cross.js +1 -1
- package/dist/src/core/patch-lint-diff-tag.d.ts +33 -0
- package/dist/src/core/patch-lint-diff-tag.js +83 -0
- package/dist/src/core/patch-lint.js +29 -9
- package/dist/src/types/commands/options.d.ts +25 -0
- package/dist/src/types/commands/patches.d.ts +9 -0
- package/dist/src/types/config.d.ts +1 -1
- package/dist/src/types/furnace.d.ts +13 -2
- package/package.json +1 -1
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
/**
|
|
3
|
+
* Diff-scoping for `fireforge lint`.
|
|
4
|
+
*
|
|
5
|
+
* Pre-existing patch-state errors and errors introduced by the current task
|
|
6
|
+
* print identically today, so triaging "is the diff I just produced clean?"
|
|
7
|
+
* requires mentally subtracting the pre-existing noise. This module
|
|
8
|
+
* classifies each lint issue as either `introduced` (the file was touched
|
|
9
|
+
* since the user-supplied git revision) or `cumulative` (pre-existing
|
|
10
|
+
* drift), without changing what the underlying rules emit.
|
|
11
|
+
*/
|
|
12
|
+
import { toError } from '../utils/errors.js';
|
|
13
|
+
import { verbose } from '../utils/logger.js';
|
|
14
|
+
import { isMissingHeadError } from './git.js';
|
|
15
|
+
import { git } from './git-base.js';
|
|
16
|
+
import { getUntrackedFiles } from './git-status.js';
|
|
17
|
+
/**
|
|
18
|
+
* Collects engine-relative paths that changed between `rev` and `HEAD`,
|
|
19
|
+
* plus any workdir modifications and untracked files. An empty set means
|
|
20
|
+
* "no diff we can prove" — downstream treats every issue as `cumulative`
|
|
21
|
+
* in that case (operator ran `lint --since HEAD` with no pending work).
|
|
22
|
+
* @param engineDir Path to the engine git repository.
|
|
23
|
+
* @param rev Git revision to diff against (e.g. `HEAD`, a branch, a SHA).
|
|
24
|
+
*/
|
|
25
|
+
export async function collectDiffFilePaths(engineDir, rev) {
|
|
26
|
+
const files = new Set();
|
|
27
|
+
try {
|
|
28
|
+
const commitDiff = await git(['diff', '--name-only', `${rev}...HEAD`], engineDir);
|
|
29
|
+
for (const line of commitDiff.split('\n')) {
|
|
30
|
+
const trimmed = line.trim();
|
|
31
|
+
if (trimmed)
|
|
32
|
+
files.add(trimmed);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
if (!isMissingHeadError(error)) {
|
|
37
|
+
verbose(`lint --since: could not diff against ${rev} — ${toError(error).message}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
const worktreeDiff = await git(['diff', '--name-only', 'HEAD'], engineDir);
|
|
42
|
+
for (const line of worktreeDiff.split('\n')) {
|
|
43
|
+
const trimmed = line.trim();
|
|
44
|
+
if (trimmed)
|
|
45
|
+
files.add(trimmed);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
verbose(`lint --since: could not enumerate workdir diff — ${toError(error).message}`);
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
for (const file of await getUntrackedFiles(engineDir)) {
|
|
53
|
+
files.add(file);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
verbose(`lint --since: could not list untracked files — ${toError(error).message}`);
|
|
58
|
+
}
|
|
59
|
+
return files;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Annotates a list of lint issues with `introduced` / `cumulative` tags
|
|
63
|
+
* based on whether the issue's file is part of the supplied diff set.
|
|
64
|
+
* Mutates each issue in place AND returns the list for chaining.
|
|
65
|
+
*
|
|
66
|
+
* Issues with no file (`issue.file === ''`) — e.g. cross-patch rules that
|
|
67
|
+
* describe queue-wide state — are always `cumulative` under `--since`
|
|
68
|
+
* because they describe drift accumulated across many commits, not a
|
|
69
|
+
* single current-task edit.
|
|
70
|
+
* @param issues Issues returned by the lint orchestrator.
|
|
71
|
+
* @param diffFiles File paths touched since the user's revision.
|
|
72
|
+
*/
|
|
73
|
+
export function tagLintIssues(issues, diffFiles) {
|
|
74
|
+
for (const issue of issues) {
|
|
75
|
+
if (!issue.file) {
|
|
76
|
+
issue.tag = 'cumulative';
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
issue.tag = diffFiles.has(issue.file) ? 'introduced' : 'cumulative';
|
|
80
|
+
}
|
|
81
|
+
return issues;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=patch-lint-diff-tag.js.map
|
|
@@ -110,12 +110,14 @@ export async function lintPatchedCss(repoDir, affectedFiles, diffContent, config
|
|
|
110
110
|
// Load furnace config gracefully — skip token-prefix check if unavailable
|
|
111
111
|
let tokenPrefix;
|
|
112
112
|
let tokenAllowlist;
|
|
113
|
+
let runtimeVariables;
|
|
113
114
|
try {
|
|
114
115
|
const root = join(repoDir, '..');
|
|
115
116
|
const furnaceConfig = await loadFurnaceConfig(root);
|
|
116
117
|
if (furnaceConfig.tokenPrefix) {
|
|
117
118
|
tokenPrefix = furnaceConfig.tokenPrefix;
|
|
118
119
|
tokenAllowlist = new Set(furnaceConfig.tokenAllowlist ?? []);
|
|
120
|
+
runtimeVariables = new Set(furnaceConfig.runtimeVariables ?? []);
|
|
119
121
|
}
|
|
120
122
|
}
|
|
121
123
|
catch (error) {
|
|
@@ -154,20 +156,38 @@ export async function lintPatchedCss(repoDir, affectedFiles, diffContent, config
|
|
|
154
156
|
});
|
|
155
157
|
}
|
|
156
158
|
}
|
|
157
|
-
// Check for non-tokenized custom properties
|
|
159
|
+
// Check for non-tokenized custom properties. A variable that is both
|
|
160
|
+
// declared and consumed inside the same file is auto-exempted as a
|
|
161
|
+
// runtime state channel (see furnace.json → runtimeVariables).
|
|
158
162
|
if (tokenPrefix) {
|
|
163
|
+
const declarationPattern = /(?:^|[{;,\s])(--[\w-]+)\s*:/g;
|
|
164
|
+
const localDeclarations = new Set();
|
|
165
|
+
let declMatch;
|
|
166
|
+
while ((declMatch = declarationPattern.exec(cssContent)) !== null) {
|
|
167
|
+
const name = declMatch[1];
|
|
168
|
+
if (name)
|
|
169
|
+
localDeclarations.add(name);
|
|
170
|
+
}
|
|
159
171
|
const varPattern = /var\(\s*(--[\w-]+)/g;
|
|
160
172
|
let match;
|
|
161
173
|
while ((match = varPattern.exec(cssContent)) !== null) {
|
|
162
174
|
const prop = match[1];
|
|
163
|
-
if (
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
175
|
+
if (!prop)
|
|
176
|
+
continue;
|
|
177
|
+
if (prop.startsWith(tokenPrefix))
|
|
178
|
+
continue;
|
|
179
|
+
if (tokenAllowlist?.has(prop))
|
|
180
|
+
continue;
|
|
181
|
+
if (runtimeVariables?.has(prop))
|
|
182
|
+
continue;
|
|
183
|
+
if (localDeclarations.has(prop))
|
|
184
|
+
continue;
|
|
185
|
+
issues.push({
|
|
186
|
+
file,
|
|
187
|
+
check: 'token-prefix-violation',
|
|
188
|
+
message: `CSS references var(${prop}) which does not match the required token prefix "${tokenPrefix}". Use a design token, add to tokenAllowlist, or (for runtime state channels) list the variable in runtimeVariables.`,
|
|
189
|
+
severity: 'error',
|
|
190
|
+
});
|
|
171
191
|
}
|
|
172
192
|
}
|
|
173
193
|
}
|
|
@@ -271,6 +271,31 @@ export interface FurnaceCreateOptions {
|
|
|
271
271
|
register?: boolean;
|
|
272
272
|
/** Scaffold Mochitest directory and register in moz.build */
|
|
273
273
|
withTests?: boolean;
|
|
274
|
+
/**
|
|
275
|
+
* Scaffold an xpcshell test harness (headless, no tabbrowser) instead of
|
|
276
|
+
* browser-chrome. Required for forks without a `tabbrowser` (storage-only
|
|
277
|
+
* code, observer-driven modules). Implies `withTests` when set. Writes an
|
|
278
|
+
* `xpcshell.toml` + `test_<name>.js` under
|
|
279
|
+
* `engine/browser/base/content/test/<binary-name>-xpcshell/` and leaves
|
|
280
|
+
* moz.build registration to the operator (add the directory to
|
|
281
|
+
* `XPCSHELL_TESTS_MANIFESTS`).
|
|
282
|
+
*/
|
|
283
|
+
xpcshell?: boolean;
|
|
284
|
+
/**
|
|
285
|
+
* Test harness style to scaffold when `--with-tests` is set.
|
|
286
|
+
*
|
|
287
|
+
* - `mochikit` (default when `--with-tests` is set alone) — a MochiKit
|
|
288
|
+
* test at `engine/toolkit/content/tests/widgets/test_<tag>.html` that
|
|
289
|
+
* loads the component module directly via `chrome://global/` and
|
|
290
|
+
* asserts against `customElements`. Runs today on forks whose
|
|
291
|
+
* top-level chrome document (e.g. `mybrowser.xhtml`) lacks a
|
|
292
|
+
* `tabbrowser`, because it doesn't go through `URILoadingHelper`.
|
|
293
|
+
* - `browser-chrome` — today's browser-mochitest scaffold, requires a
|
|
294
|
+
* working tabbrowser. Use for components that talk to the browser
|
|
295
|
+
* window or open URLs.
|
|
296
|
+
* - `xpcshell` — equivalent to setting `--xpcshell`; headless, storage-only.
|
|
297
|
+
*/
|
|
298
|
+
testStyle?: 'mochikit' | 'browser-chrome' | 'xpcshell';
|
|
274
299
|
/** Stock component tag names composed internally by this component */
|
|
275
300
|
compose?: string[];
|
|
276
301
|
}
|
|
@@ -96,4 +96,13 @@ export interface PatchLintIssue {
|
|
|
96
96
|
message: string;
|
|
97
97
|
/** Severity: errors block export, warnings are advisory, notices are informational (not counted) */
|
|
98
98
|
severity: 'error' | 'warning' | 'notice';
|
|
99
|
+
/**
|
|
100
|
+
* Diff-scoping tag populated by `lint --since <rev>`. Absent when the
|
|
101
|
+
* caller did not request diff-scoping.
|
|
102
|
+
*
|
|
103
|
+
* - `introduced` — the issue's file was touched in the diff since `<rev>`.
|
|
104
|
+
* - `cumulative` — the issue is pre-existing patch-state drift not
|
|
105
|
+
* introduced by the current task.
|
|
106
|
+
*/
|
|
107
|
+
tag?: 'introduced' | 'cumulative';
|
|
99
108
|
}
|
|
@@ -47,7 +47,7 @@ export interface FireForgeConfig {
|
|
|
47
47
|
/**
|
|
48
48
|
* Project marker prefix appended to lines FireForge writes into
|
|
49
49
|
* upstream Firefox source files (e.g. the `customElements.js` tag list).
|
|
50
|
-
* `"
|
|
50
|
+
* `"MYBROWSER"` emits a trailing ` // MYBROWSER:` on each inserted line.
|
|
51
51
|
* Keeps modifications discoverable and re-applies idempotent.
|
|
52
52
|
*/
|
|
53
53
|
markerComment?: string;
|
|
@@ -63,10 +63,21 @@ export interface FurnaceConfig {
|
|
|
63
63
|
tokenPrefix?: string;
|
|
64
64
|
/** Custom properties allowed even though they don't match tokenPrefix (e.g. ["--background-color-box"]) */
|
|
65
65
|
tokenAllowlist?: string[];
|
|
66
|
+
/**
|
|
67
|
+
* Custom properties used as runtime state channels — written and read by the
|
|
68
|
+
* component itself (e.g. per-frame camera/tile positions) rather than
|
|
69
|
+
* consumed as design tokens. Listed names are exempt from the
|
|
70
|
+
* `token-prefix-violation` check even when they do not match `tokenPrefix`
|
|
71
|
+
* and are not in `tokenAllowlist`. Use this for cross-component runtime
|
|
72
|
+
* variables (e.g. set in JS, read in CSS of a child). Component-local
|
|
73
|
+
* variables that are both declared and consumed inside the same component's
|
|
74
|
+
* own CSS file are auto-exempted and do not need an entry here.
|
|
75
|
+
*/
|
|
76
|
+
runtimeVariables?: string[];
|
|
66
77
|
/**
|
|
67
78
|
* Chrome documents scanned by the `missing-token-link` validator to confirm
|
|
68
79
|
* the tokens CSS file is `<link>`ed. Forks with multiple chrome host
|
|
69
|
-
* documents (e.g. `
|
|
80
|
+
* documents (e.g. `mybrowser.xhtml` beside the stock `browser.xhtml`) should
|
|
70
81
|
* list every document that may own the link. When omitted, defaults to
|
|
71
82
|
* `['browser/base/content/browser.xhtml']` — the upstream Firefox path.
|
|
72
83
|
*/
|
|
@@ -95,7 +106,7 @@ export interface FurnaceConfig {
|
|
|
95
106
|
* state before clearing authoring markers. The string is surfaced in doctor's
|
|
96
107
|
* failure message verbatim, so new entries should be self-explanatory.
|
|
97
108
|
*/
|
|
98
|
-
export type FurnacePendingRepairOperation = 'preview-teardown' | 'apply-rollback' | 'deploy-rollback' | 'remove-rollback' | 'create-rollback' | 'override-rollback' | 'scan-rollback' | 'rename-rollback' | 'refresh-rollback';
|
|
109
|
+
export type FurnacePendingRepairOperation = 'preview-teardown' | 'apply-rollback' | 'deploy-rollback' | 'remove-rollback' | 'create-rollback' | 'override-rollback' | 'scan-rollback' | 'rename-rollback' | 'refresh-rollback' | 'chrome-doc-rollback';
|
|
99
110
|
/**
|
|
100
111
|
* Marker persisted into `.fireforge/furnace-state.json` when a furnace
|
|
101
112
|
* mutation failed to roll back cleanly. Its presence tells the next
|