@hominis/fireforge 0.18.8 → 0.18.10
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/dist/src/commands/lint.d.ts +36 -0
- package/dist/src/commands/lint.js +61 -1
- package/dist/src/commands/patch/index.d.ts +5 -3
- package/dist/src/commands/patch/index.js +8 -4
- package/dist/src/commands/patch/lint-ignore.d.ts +8 -0
- package/dist/src/commands/patch/lint-ignore.js +8 -4
- package/dist/src/commands/patch/rename.d.ts +36 -0
- package/dist/src/commands/patch/rename.js +244 -0
- package/dist/src/commands/test.js +50 -3
- package/dist/src/core/ast-utils.d.ts +5 -1
- package/dist/src/core/ast-utils.js +10 -3
- package/dist/src/core/build-audit-resolve.d.ts +5 -3
- package/dist/src/core/build-audit-resolve.js +12 -3
- package/dist/src/core/config-paths.d.ts +1 -1
- package/dist/src/core/config-paths.js +1 -0
- package/dist/src/core/config-validate.js +4 -0
- package/dist/src/core/license-headers.d.ts +5 -0
- package/dist/src/core/license-headers.js +46 -5
- package/dist/src/core/marionette-port.d.ts +29 -0
- package/dist/src/core/marionette-port.js +82 -0
- package/dist/src/core/patch-export.d.ts +10 -0
- package/dist/src/core/patch-export.js +8 -2
- package/dist/src/core/patch-lint-chrome-jsdoc.d.ts +47 -0
- package/dist/src/core/patch-lint-chrome-jsdoc.js +87 -0
- package/dist/src/core/patch-lint-cross.js +6 -1
- package/dist/src/core/patch-lint-jsdoc.d.ts +37 -0
- package/dist/src/core/patch-lint-jsdoc.js +24 -3
- package/dist/src/core/patch-lint-ownership.d.ts +21 -3
- package/dist/src/core/patch-lint-ownership.js +45 -18
- package/dist/src/core/patch-lint.d.ts +7 -2
- package/dist/src/core/patch-lint.js +24 -6
- package/dist/src/types/commands/index.d.ts +1 -1
- package/dist/src/types/commands/options.d.ts +36 -0
- package/dist/src/types/config.d.ts +12 -1
- package/package.json +1 -1
|
@@ -1,13 +1,41 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
2
|
/**
|
|
3
|
-
* Patch ownership resolution for
|
|
3
|
+
* Patch ownership resolution for JS-shaped files.
|
|
4
4
|
*
|
|
5
5
|
* A file is "patch-owned" when it was created by the project's patch
|
|
6
6
|
* queue rather than being an upstream Firefox file that happens to be
|
|
7
|
-
* modified. This module computes the set of patch-owned
|
|
8
|
-
*
|
|
7
|
+
* modified. This module computes the set of patch-owned paths so lint
|
|
8
|
+
* rules can scope enforcement to project code only.
|
|
9
|
+
*
|
|
10
|
+
* The two resolvers are kept separate (one per extension predicate)
|
|
11
|
+
* because the downstream rules differ: `.sys.mjs` files go through
|
|
12
|
+
* `runCheckJs` (TypeScript checkJs) and the export-walker JSDoc rule;
|
|
13
|
+
* chrome subscripts (`.js` non-`.sys.mjs`) only get the script-walker
|
|
14
|
+
* JSDoc rule. Mixing them in a single set would silently broaden
|
|
15
|
+
* `runCheckJs` to chrome subscripts, which it is not designed for.
|
|
9
16
|
*/
|
|
10
17
|
import { collectNewFileCreatorsByPath } from './patch-lint-cross.js';
|
|
18
|
+
/**
|
|
19
|
+
* Returns the set of patch-owned files matching `predicate`. Internal
|
|
20
|
+
* helper shared by the per-extension resolvers below.
|
|
21
|
+
*/
|
|
22
|
+
function resolveOwned(currentNewFiles, patchQueueCtx, predicate) {
|
|
23
|
+
const owned = new Set();
|
|
24
|
+
for (const file of currentNewFiles) {
|
|
25
|
+
if (predicate(file)) {
|
|
26
|
+
owned.add(file);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
if (patchQueueCtx) {
|
|
30
|
+
const creators = collectNewFileCreatorsByPath(patchQueueCtx);
|
|
31
|
+
for (const [file, owners] of creators) {
|
|
32
|
+
if (predicate(file) && owners.length > 0) {
|
|
33
|
+
owned.add(file);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return owned;
|
|
38
|
+
}
|
|
11
39
|
/**
|
|
12
40
|
* Returns the set of file paths that are patch-owned `.sys.mjs` files.
|
|
13
41
|
*
|
|
@@ -24,20 +52,19 @@ import { collectNewFileCreatorsByPath } from './patch-lint-cross.js';
|
|
|
24
52
|
* @returns Set of patch-owned `.sys.mjs` file paths
|
|
25
53
|
*/
|
|
26
54
|
export function resolvePatchOwnedSysMjs(currentNewFiles, patchQueueCtx) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
return owned;
|
|
55
|
+
return resolveOwned(currentNewFiles, patchQueueCtx, (file) => file.endsWith('.sys.mjs'));
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Returns the set of file paths that are patch-owned chrome subscripts
|
|
59
|
+
* (`.js` files that are not `.sys.mjs` modules — typically
|
|
60
|
+
* `browser/base/content/<binaryName>*.js` and similar). Same ownership
|
|
61
|
+
* semantics as {@link resolvePatchOwnedSysMjs}.
|
|
62
|
+
*
|
|
63
|
+
* @param currentNewFiles - Files newly created in the current diff
|
|
64
|
+
* @param patchQueueCtx - Optional cross-patch context for queue-wide ownership
|
|
65
|
+
* @returns Set of patch-owned chrome-subscript file paths
|
|
66
|
+
*/
|
|
67
|
+
export function resolvePatchOwnedChromeScripts(currentNewFiles, patchQueueCtx) {
|
|
68
|
+
return resolveOwned(currentNewFiles, patchQueueCtx, (file) => file.endsWith('.js') && !file.endsWith('.sys.mjs'));
|
|
42
69
|
}
|
|
43
70
|
//# sourceMappingURL=patch-lint-ownership.js.map
|
|
@@ -5,7 +5,7 @@ export { runCheckJs } from './patch-lint-checkjs.js';
|
|
|
5
5
|
export { buildPatchQueueContext, collectNewFileCreatorsByPath, type ExtractedSpecifier, extractImportSpecifiers, extractImportSpecifiersWithLines, findForwardImportIgnoreLines, FORWARD_IMPORT_IGNORE_MARKER, isForwardImportableFile, lintPatchQueue, lintPatchQueueDuplicateCreations, lintPatchQueueForwardImports, type PatchQueueContext, type PatchQueueEntry, } from './patch-lint-cross.js';
|
|
6
6
|
export { buildModifiedFileAdditionsFromDiff, detectNewFilesInDiff } from './patch-lint-diff.js';
|
|
7
7
|
export { type JsDocCheck, type JsDocIssue, validateExportJsDoc } from './patch-lint-jsdoc.js';
|
|
8
|
-
export { resolvePatchOwnedSysMjs } from './patch-lint-ownership.js';
|
|
8
|
+
export { resolvePatchOwnedChromeScripts, resolvePatchOwnedSysMjs } from './patch-lint-ownership.js';
|
|
9
9
|
/**
|
|
10
10
|
* Counts the total lines in a unified diff and the number of non-binary
|
|
11
11
|
* text lines, so binary hunks do not inflate patch size checks.
|
|
@@ -55,9 +55,14 @@ export declare function lintNewFileHeaders(repoDir: string, newFiles: string[],
|
|
|
55
55
|
* @param newFiles - Set of files that are newly created in this patch
|
|
56
56
|
* @param config - Project configuration
|
|
57
57
|
* @param patchOwnedFiles - Optional set of patch-owned `.sys.mjs` paths for scoped JSDoc enforcement
|
|
58
|
+
* @param patchOwnedChromeScripts - Optional set of patch-owned chrome
|
|
59
|
+
* subscripts (`.js` non-`.sys.mjs`) for scoped chrome-script JSDoc
|
|
60
|
+
* enforcement. Built by {@link resolvePatchOwnedChromeScripts}; passed
|
|
61
|
+
* separately from `patchOwnedFiles` so the `runCheckJs` consumer (which
|
|
62
|
+
* only accepts `.sys.mjs`) is not silently broadened.
|
|
58
63
|
* @returns Array of lint issues
|
|
59
64
|
*/
|
|
60
|
-
export declare function lintPatchedJs(repoDir: string, affectedFiles: string[], newFiles: Set<string>, config: FireForgeConfig, patchOwnedFiles?: Set<string>): Promise<PatchLintIssue[]>;
|
|
65
|
+
export declare function lintPatchedJs(repoDir: string, affectedFiles: string[], newFiles: Set<string>, config: FireForgeConfig, patchOwnedFiles?: Set<string>, patchOwnedChromeScripts?: Set<string>): Promise<PatchLintIssue[]>;
|
|
61
66
|
/**
|
|
62
67
|
* Checks that modifications to existing (non-new) JS/MJS files include at
|
|
63
68
|
* least one `// BINARYNAME:` comment in the added lines.
|
|
@@ -7,10 +7,11 @@ import { hasRawCssColors, stripJsComments } from '../utils/regex.js';
|
|
|
7
7
|
import { loadFurnaceConfig } from './furnace-config.js';
|
|
8
8
|
import { containsUpstreamLicenseText, getLicenseHeader, hasAnyLicenseHeader, hasAnyLicenseHeaderAnyStyle, } from './license-headers.js';
|
|
9
9
|
import { runCheckJs } from './patch-lint-checkjs.js';
|
|
10
|
+
import { lintChromeScriptJsDocForFile } from './patch-lint-chrome-jsdoc.js';
|
|
10
11
|
import { detectNewFilesInDiff, extractAddedLinesPerFile } from './patch-lint-diff.js';
|
|
11
12
|
import { AGGREGATE_PATCH_FILE } from './patch-lint-diff-tag.js';
|
|
12
13
|
import { validateExportJsDoc } from './patch-lint-jsdoc.js';
|
|
13
|
-
import { resolvePatchOwnedSysMjs } from './patch-lint-ownership.js';
|
|
14
|
+
import { resolvePatchOwnedChromeScripts, resolvePatchOwnedSysMjs } from './patch-lint-ownership.js';
|
|
14
15
|
// ---------------------------------------------------------------------------
|
|
15
16
|
// Cross-patch lint re-exports
|
|
16
17
|
// ---------------------------------------------------------------------------
|
|
@@ -24,7 +25,7 @@ export { runCheckJs } from './patch-lint-checkjs.js';
|
|
|
24
25
|
export { buildPatchQueueContext, collectNewFileCreatorsByPath, extractImportSpecifiers, extractImportSpecifiersWithLines, findForwardImportIgnoreLines, FORWARD_IMPORT_IGNORE_MARKER, isForwardImportableFile, lintPatchQueue, lintPatchQueueDuplicateCreations, lintPatchQueueForwardImports, } from './patch-lint-cross.js';
|
|
25
26
|
export { buildModifiedFileAdditionsFromDiff, detectNewFilesInDiff } from './patch-lint-diff.js';
|
|
26
27
|
export { validateExportJsDoc } from './patch-lint-jsdoc.js';
|
|
27
|
-
export { resolvePatchOwnedSysMjs } from './patch-lint-ownership.js';
|
|
28
|
+
export { resolvePatchOwnedChromeScripts, resolvePatchOwnedSysMjs } from './patch-lint-ownership.js';
|
|
28
29
|
// ---------------------------------------------------------------------------
|
|
29
30
|
// Helpers
|
|
30
31
|
// ---------------------------------------------------------------------------
|
|
@@ -403,9 +404,14 @@ export async function lintNewFileHeaders(repoDir, newFiles, config) {
|
|
|
403
404
|
* @param newFiles - Set of files that are newly created in this patch
|
|
404
405
|
* @param config - Project configuration
|
|
405
406
|
* @param patchOwnedFiles - Optional set of patch-owned `.sys.mjs` paths for scoped JSDoc enforcement
|
|
407
|
+
* @param patchOwnedChromeScripts - Optional set of patch-owned chrome
|
|
408
|
+
* subscripts (`.js` non-`.sys.mjs`) for scoped chrome-script JSDoc
|
|
409
|
+
* enforcement. Built by {@link resolvePatchOwnedChromeScripts}; passed
|
|
410
|
+
* separately from `patchOwnedFiles` so the `runCheckJs` consumer (which
|
|
411
|
+
* only accepts `.sys.mjs`) is not silently broadened.
|
|
406
412
|
* @returns Array of lint issues
|
|
407
413
|
*/
|
|
408
|
-
export async function lintPatchedJs(repoDir, affectedFiles, newFiles, config, patchOwnedFiles) {
|
|
414
|
+
export async function lintPatchedJs(repoDir, affectedFiles, newFiles, config, patchOwnedFiles, patchOwnedChromeScripts) {
|
|
409
415
|
const jsFiles = affectedFiles.filter(isJsFile);
|
|
410
416
|
if (jsFiles.length === 0)
|
|
411
417
|
return [];
|
|
@@ -476,9 +482,20 @@ export async function lintPatchedJs(repoDir, affectedFiles, newFiles, config, pa
|
|
|
476
482
|
});
|
|
477
483
|
}
|
|
478
484
|
}
|
|
479
|
-
//
|
|
485
|
+
// 3a. JSDoc on top-level declarations in patch-owned chrome subscripts.
|
|
486
|
+
// Dispatched out-of-line to keep this file under the per-file line
|
|
487
|
+
// budget. See `patch-lint-chrome-jsdoc.ts` for the rule body.
|
|
488
|
+
const isChromeOwned = file.endsWith('.js') &&
|
|
489
|
+
!isSysMjs &&
|
|
490
|
+
(patchOwnedChromeScripts ? patchOwnedChromeScripts.has(file) : isNew);
|
|
491
|
+
const chromeMode = config.patchLint?.chromeScriptJsDoc;
|
|
492
|
+
issues.push(...lintChromeScriptJsDocForFile(file, content, isChromeOwned, chromeMode));
|
|
493
|
+
// 3b. Assertion floor for browser-chrome tests touched by this patch
|
|
494
|
+
// (covers both newly introduced files and modified upstream tests —
|
|
495
|
+
// a patch that strips the last `Assert.equal` from an existing
|
|
496
|
+
// browser_*.js silently passed under the old `isNew` gate).
|
|
480
497
|
const assertionFloor = config.patchLint?.testAssertionFloor;
|
|
481
|
-
if (assertionFloor && assertionFloor !== 'off' &&
|
|
498
|
+
if (assertionFloor && assertionFloor !== 'off' && isBrowserChromeTestFile(file)) {
|
|
482
499
|
const ASSERTION_TOKENS = ['Assert.', 'ok(', 'is(', 'isnot(', 'isDeeply('];
|
|
483
500
|
const hasAssertion = ASSERTION_TOKENS.some((tok) => strippedContent.includes(tok));
|
|
484
501
|
if (!hasAssertion) {
|
|
@@ -703,10 +720,11 @@ export async function lintExportedPatch(repoDir, affectedFiles, diffContent, con
|
|
|
703
720
|
const newFiles = detectNewFilesInDiff(diffContent);
|
|
704
721
|
const { textLines: lineCount } = countNonBinaryDiffLines(diffContent);
|
|
705
722
|
const patchOwnedFiles = resolvePatchOwnedSysMjs(newFiles, patchQueueCtx);
|
|
723
|
+
const patchOwnedChromeScripts = resolvePatchOwnedChromeScripts(newFiles, patchQueueCtx);
|
|
706
724
|
const [cssIssues, headerIssues, jsIssues, modifiedHeaderIssues] = await Promise.all([
|
|
707
725
|
lintPatchedCss(repoDir, affectedFiles, diffContent, config),
|
|
708
726
|
lintNewFileHeaders(repoDir, [...newFiles], config),
|
|
709
|
-
lintPatchedJs(repoDir, affectedFiles, newFiles, config, patchOwnedFiles),
|
|
727
|
+
lintPatchedJs(repoDir, affectedFiles, newFiles, config, patchOwnedFiles, patchOwnedChromeScripts),
|
|
710
728
|
lintModifiedFileHeaders(repoDir, affectedFiles, newFiles),
|
|
711
729
|
]);
|
|
712
730
|
const modCommentIssues = lintModificationComments(diffContent, config);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Re-exports all command-related types from focused sub-modules.
|
|
3
3
|
*/
|
|
4
|
-
export type { BuildOptions, DiscardOptions, DoctorOptions, DownloadOptions, ExportOptions, FurnaceApplyOptions, FurnaceCreateOptions, FurnaceDeployOptions, FurnaceOverrideOptions, FurnacePreviewOptions, FurnaceRefreshOptions, FurnaceRemoveOptions, FurnaceSyncOptions, FurnaceValidateOptions, GlobalOptions, ImportOptions, PackageOptions, PatchCompactOptions, PatchDeleteOptions, PatchLintIgnoreOptions, PatchReorderOptions, PatchTierOptions, RebaseOptions, ReExportOptions, RegisterOptions, ResetOptions, RunOptions, SetupOptions, StatusOptions, TestOptions, TokenAddOptions, WireOptions, } from './options.js';
|
|
4
|
+
export type { BuildOptions, DiscardOptions, DoctorOptions, DownloadOptions, ExportOptions, FurnaceApplyOptions, FurnaceCreateOptions, FurnaceDeployOptions, FurnaceOverrideOptions, FurnacePreviewOptions, FurnaceRefreshOptions, FurnaceRemoveOptions, FurnaceSyncOptions, FurnaceValidateOptions, GlobalOptions, ImportOptions, PackageOptions, PatchCompactOptions, PatchDeleteOptions, PatchLintIgnoreOptions, PatchRenameOptions, PatchReorderOptions, PatchTierOptions, RebaseOptions, ReExportOptions, RegisterOptions, ResetOptions, RunOptions, SetupOptions, StatusOptions, TestOptions, TokenAddOptions, WireOptions, } from './options.js';
|
|
5
5
|
export type { ImportSummary, PatchCategory, PatchesManifest, PatchInfo, PatchLintIssue, PatchMetadata, PatchResult, } from './patches.js';
|
|
6
6
|
export type { DoctorCheck, ProjectStatus, TokenCoverageFileEntry, TokenCoverageReport, } from './project.js';
|
|
@@ -316,6 +316,14 @@ export interface TestOptions {
|
|
|
316
316
|
* values appear after `--headless` if both are set.
|
|
317
317
|
*/
|
|
318
318
|
machArg?: string[];
|
|
319
|
+
/**
|
|
320
|
+
* Override the Marionette control port (default 2828) used by the
|
|
321
|
+
* stale-browser probe, the `--doctor` preflight, and the auto-forwarded
|
|
322
|
+
* `--setpref=marionette.port=<n>` arg passed to mach. Set this when a
|
|
323
|
+
* stale process holds the default port and `kill` is not an option, or
|
|
324
|
+
* when a CI runner reserves a different port for parallel test runs.
|
|
325
|
+
*/
|
|
326
|
+
marionettePort?: number;
|
|
319
327
|
}
|
|
320
328
|
/**
|
|
321
329
|
* Options for the furnace apply command.
|
|
@@ -493,6 +501,34 @@ export interface PatchDeleteOptions {
|
|
|
493
501
|
/** Bypass the hard refusal when later patches depend on the target. */
|
|
494
502
|
forceUnsafe?: boolean;
|
|
495
503
|
}
|
|
504
|
+
/**
|
|
505
|
+
* Options for the `fireforge patch rename` subcommand. Updates the
|
|
506
|
+
* patch's filename, manifest `name`, and (optionally) `description`
|
|
507
|
+
* atomically without rewriting the `.patch` file body. Companion to
|
|
508
|
+
* `re-export --files` for the case where the body is already correct
|
|
509
|
+
* but the patch's identity (filename + description) describes a
|
|
510
|
+
* pre-shrink scope; before this verb existed the only workaround was
|
|
511
|
+
* `delete` + re-export, which briefly dropped the patch from the queue.
|
|
512
|
+
*/
|
|
513
|
+
export interface PatchRenameOptions {
|
|
514
|
+
/**
|
|
515
|
+
* New human-readable name. Sanitised the same way `export --name`
|
|
516
|
+
* sanitises into the filename slug (lowercase, non-alphanumerics
|
|
517
|
+
* collapsed to `-`, length-capped). The patch's `name` field stores
|
|
518
|
+
* the raw value; the filename uses the sanitised slug.
|
|
519
|
+
*/
|
|
520
|
+
to?: string;
|
|
521
|
+
/**
|
|
522
|
+
* Replacement description. Omit to leave the description unchanged
|
|
523
|
+
* (intentional — operators frequently want to relabel the slug
|
|
524
|
+
* without touching the description).
|
|
525
|
+
*/
|
|
526
|
+
description?: string;
|
|
527
|
+
/** Print the planned change without writing. */
|
|
528
|
+
dryRun?: boolean;
|
|
529
|
+
/** Skip the confirmation prompt (required for non-TTY). */
|
|
530
|
+
yes?: boolean;
|
|
531
|
+
}
|
|
496
532
|
/**
|
|
497
533
|
* Options for the patch reorder command.
|
|
498
534
|
*/
|
|
@@ -74,8 +74,19 @@ export interface PatchLintConfig {
|
|
|
74
74
|
rawColorAllowlist?: string[];
|
|
75
75
|
/** Enforce JSDoc on class-method exports in patch-owned .sys.mjs files. Default: 'off'. */
|
|
76
76
|
jsdocClassMethods?: PatchLintSeverityGate;
|
|
77
|
-
/** Require ≥1 assertion in patch-
|
|
77
|
+
/** Require ≥1 assertion in any patch-touched browser_*.js test file (new or modified). Default: 'off'. */
|
|
78
78
|
testAssertionFloor?: PatchLintSeverityGate;
|
|
79
|
+
/**
|
|
80
|
+
* Enforce JSDoc on top-level classes (and their methods) and functions
|
|
81
|
+
* in patch-owned chrome subscripts (`.js` files loaded via
|
|
82
|
+
* `Services.scriptloader.loadSubScript`, e.g.
|
|
83
|
+
* `browser/base/content/<binaryName>*.js`). Distinct from
|
|
84
|
+
* `jsdocClassMethods` because chrome subscripts are parsed as scripts,
|
|
85
|
+
* not ES modules — using one flag for both would silently disable the
|
|
86
|
+
* rule when a chrome subscript was fed to the module parser. Default:
|
|
87
|
+
* 'off'.
|
|
88
|
+
*/
|
|
89
|
+
chromeScriptJsDoc?: PatchLintSeverityGate;
|
|
79
90
|
}
|
|
80
91
|
/**
|
|
81
92
|
* Build mode for mach.
|