@hominis/fireforge 0.19.1 → 0.19.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 CHANGED
@@ -5,10 +5,16 @@
5
5
  ### Features
6
6
 
7
7
  - **`patchLint.checkJsStrict` and `patchLint.checkJsCompilerOptions`.** The patch-lint `checkJs` pass now defaults to the historical loose preset (`strict: false`, `noImplicitAny: false`). Set `"patchLint": { "checkJs": true, "checkJsStrict": true }` to enforce `strict` and `noImplicitAny` on patch-owned `.sys.mjs` so implicit-any parameters surface as `checkjs-type-error`, aligning with strict whole-project checkJs without changing module resolution (`noResolve` and `resource://` suppression unchanged). Optional `checkJsCompilerOptions` (requires `checkJsStrict`) merges allowlisted boolean compiler overrides — for example `{ "strictNullChecks": false }` — after the strict preset for gradual adoption. The Firefox globals shim and `SUPPRESSED_DIAGNOSTIC_CODES` remain shared with `fireforge typecheck` via `typecheck-shim.ts`.
8
+ - **`checkJs` — ambient modules for Firefox URL imports.** The shared shim in `typecheck-shim.ts` now includes shorthand `declare module 'resource:*'` and `declare module 'chrome:*'`, matching typical `resource://…` / `chrome://…` specifiers without the broken `Record` + `export=` shape under `moduleResolution` Bundler (which typed dynamic imports as `{ default: … }` and broke `.namedExport` access). Bulk `fireforge re-export` with `patchLint.checkJs` no longer routinely needs `--skip-lint` for `.sys.mjs` queues that lazily URL-import storage and infra helpers.
8
9
 
9
10
  ### Hardening
10
11
 
11
12
  - **`modified-file-missing-header` — standard Mozilla MPL-2.0 block headers with wrapped line breaks.** The upstream fallback scan required a contiguous `Mozilla Public License` substring in the first few lines, so files that follow Mozilla’s usual `/* … Mozilla Public` / ` * License, v. 2.0 … */` wrap (including after Emacs/vim directive blocks) were warned despite a valid notice. `containsUpstreamLicenseText` in `src/core/license-headers.ts` now normalizes common block-comment continuation prefixes before matching, so forks need not add SPDX solely to satisfy patch lint.
13
+ - **`fireforge test` — `--marionette-port` auto-forward matches toolkit mochitests and mixed suites.** Auto-forward of `--setpref=marionette.port=<n>` previously keyed off a path heuristic that missed `toolkit/content/tests/**` widget HTML tests (no `/mochitest/` segment), so the preflight could use the operator’s port while mach still defaulted to **2828**. Forwarding now runs whenever `--marionette-port` is set unless `--mach-arg` explicitly includes `--flavor=xpcshell` / `xpcshell-tests` (the pref is unused there). `isMarionetteFlavor` also treats `toolkit/content/tests/` paths as Marionette-relevant unless they sit under `/tests/xpcshell/`, for consistency with other callers of that helper.
14
+
15
+ ### Documentation
16
+
17
+ - **README — mochitest timeouts vs Marionette.** The Test harness section documents long idle timeouts (~370s, `TEST_END: TIMEOUT`) on fork custom chrome, `--marionette-port` behaviour with xpcshell flavor, and pointers to fork-side prefs and investigation (for example Hominis `AGENT_RULES.md`).
12
18
 
13
19
  ## 0.18.0
14
20
 
package/README.md CHANGED
@@ -255,7 +255,7 @@ By default, a standalone `fireforge lint` (no arguments) lints the **aggregate**
255
255
 
256
256
  **JSDoc validation** uses AST-based analysis (Acorn) to validate exported APIs in patch-owned `.sys.mjs` files. A file is "patch-owned" if it was newly created by the current diff or by an existing patch in the queue. Functions must document every `@param` (names must match) and include `@returns` when the function returns a value. Exported constants and classes require a JSDoc block.
257
257
 
258
- **Optional `checkJs` pass.** Enable a TypeScript-esque bastardization of type checking for patch-owned `.sys.mjs` files by adding `"patchLint": { "checkJs": true }` to `fireforge.json`. This uses the TypeScript compiler API with `allowJs + checkJs + noEmit`, scoped only to patch-owned files. Firefox globals (`Services`, `ChromeUtils`, `lazy`, etc.) are shimmed automatically. Module-resolution errors from Firefox's `resource://` and `chrome://` URL schemes are suppressed since TypeScript cannot follow these. By default the pass uses a **loose** compiler preset (`strict: false`, `noImplicitAny: false`) so implicit `any` from untyped parameters does not flood the output. Set `"patchLint": { "checkJsStrict": true }` (requires `checkJs: true`) to enable `strict` and `noImplicitAny` for parity with strict whole-project checkJs — implicit-any parameters then surface as `checkjs-type-error`. Optional `"patchLint": { "checkJsCompilerOptions": { "strictNullChecks": false } }` (requires `checkJsStrict: true`) merges **allowlisted boolean** strict flags after that preset so forks can tighten `noImplicitAny` while relaxing e.g. null checks. The same built-in shim and the same eight suppressed diagnostic codes as `fireforge typecheck` apply; only explicit strictness differs. Projects that need to extend the built-in shim (e.g. for `MozLitElement`, `MozXULElement`, or fork-specific component bases) can point at an additional `.d.ts` via `"patchLint": { "checkJsExtraShim": "tools/types/<fork>-globals.d.ts" }`; the file is concatenated to the built-in shim — augment, don't redeclare.
258
+ **Optional `checkJs` pass.** Enable a TypeScript-esque bastardization of type checking for patch-owned `.sys.mjs` files by adding `"patchLint": { "checkJs": true }` to `fireforge.json`. This uses the TypeScript compiler API with `allowJs + checkJs + noEmit`, scoped only to patch-owned files. Firefox globals (`Services`, `ChromeUtils`, `lazy`, etc.) are shimmed automatically. Module-resolution errors from Firefox's `resource://` and `chrome://` URL schemes are suppressed since TypeScript cannot follow these; the built-in shim also declares ambient `resource:*` and `chrome:*` modules so lazy `import("resource:-…")` / `import("chrome:-…")` stay loosely typed under `noResolve` instead of degrading into spurious `checkjs-type-error` cascades — refine further with `"patchLint": { "checkJsExtraShim": "..." }`. By default the pass uses a **loose** compiler preset (`strict: false`, `noImplicitAny: false`) so implicit `any` from untyped parameters does not flood the output. Set `"patchLint": { "checkJsStrict": true }` (requires `checkJs: true`) to enable `strict` and `noImplicitAny` for parity with strict whole-project checkJs — implicit-any parameters then surface as `checkjs-type-error`. Optional `"patchLint": { "checkJsCompilerOptions": { "strictNullChecks": false } }` (requires `checkJsStrict: true`) merges **allowlisted boolean** strict flags after that preset so forks can tighten `noImplicitAny` while relaxing e.g. null checks. The same built-in shim and the same eight suppressed diagnostic codes as `fireforge typecheck` apply; only explicit strictness differs. Projects that need to extend the built-in shim (e.g. for `MozLitElement`, `MozXULElement`, or fork-specific component bases) can point at an additional `.d.ts` via `"patchLint": { "checkJsExtraShim": "tools/types/<fork>-globals.d.ts" }`; the file is concatenated to the built-in shim — augment, don't redeclare.
259
259
 
260
260
  **Whole-project type checking — `fireforge typecheck`.** `patchLint.checkJs` is patch-hygiene: scoped to patch-owned `.sys.mjs`, suppresses module-resolution noise, and runs every time `fireforge lint` runs. With `checkJsStrict`, that pass can match a strict jsconfig's `noImplicitAny` behaviour without replacing full-project resolution. `fireforge typecheck` remains the CI-grade complement: it runs whole projects you point at via `typecheck.projects` in `fireforge.json`, honours each jsconfig's strictness/include/exclude/`paths`, and is intended as a CI gate. The two are complementary; the recommended setup is `fireforge lint` on every patch export and `fireforge typecheck` on CI for the project-level baseline.
261
261
 
@@ -638,6 +638,12 @@ xpcshell has a chrome-URI boundary that is worth knowing before writing assertio
638
638
 
639
639
  The two flags can be combined — `--with-tests --xpcshell` writes both harnesses.
640
640
 
641
+ ### Mochitest stalls and `--marionette-port`
642
+
643
+ When you pass `--marionette-port <n>`, FireForge uses that port for the stale-listener probe and for `--doctor`, and it forwards `--setpref=marionette.port=<n>` to `mach test` so the harness binds the same port. The only exception is an explicit `--mach-arg --flavor=xpcshell` (or `--flavor=xpcshell-tests`): that harness ignores the pref, so FireForge skips auto-forward and logs a short notice instead. Toolkit widget mochitests under `toolkit/content/tests/` (for example `test_*.html` next to `browser_*.js` suites) therefore stay aligned with the probe without duplicating `--mach-arg=--setpref=marionette.port=…`.
644
+
645
+ Some forks see mochitests end with **`TEST_END: TIMEOUT`** after on the order of **370 seconds** with **no harness output** — including runs where mozinfo reports `headless: false`, so the failure is not explained by SWGL headless alone. When tests wait on custom chrome (for example a fork tile shell that never sets a `_readyForTesting` gate), the hang is **engine-side**; use your fork’s test docs and `browser.toml` defaults (for Hominis-style trees, see the fork’s `AGENT_RULES.md` for `hominis.testing.*` prefs). Operationally: ensure Marionette port **2828** is free, pass **`--marionette-port`** when you use a non-default port (FireForge keeps preflight and mach consistent as above), and narrow the failure with `--doctor` or by splitting a lighter smoke test that does not depend on full chrome init.
646
+
641
647
  ### Stale-build preflight on `fireforge test`
642
648
 
643
649
  `fireforge test <path>` (without `--build`) now runs a preflight that diffs engine HEAD and the workdir against the last successful `fireforge build` (recorded at `.fireforge/last-build.json`). When packageable engine files have changed since that baseline, the command prints a single up-front warning naming the paths and pointing at `fireforge test --build`. This catches the class of failure where a newly scaffolded chrome resource or pref file is registered correctly but `obj-*/dist/` still holds the pre-edit bundle, so the test reads stale packaged artifacts and errors out with a cryptic `NS_ERROR_FILE_NOT_FOUND` inside xpcshell / mach test. The preflight is warn-only — a fork that rebuilt out-of-band (direct `./mach build`, IDE plugin, separate CI stage) is not blocked. Passing `--build` skips the preflight because the rebuild just refreshed the bundle.
@@ -3,7 +3,7 @@ import { join } from 'node:path';
3
3
  import { prepareBuildEnvironment } from '../core/build-prepare.js';
4
4
  import { getProjectPaths, loadConfig } from '../core/config.js';
5
5
  import { buildArtifactMismatchMessage, buildUI, hasBuildArtifacts, hasRunnableBundle, testWithOutput, } from '../core/mach.js';
6
- import { assertMarionettePortAvailable, extractForwardedMarionettePort, isMarionetteFlavor, } from '../core/marionette-port.js';
6
+ import { assertMarionettePortAvailable, extractForwardedMarionettePort, shouldAutoForwardMarionettePortToMach, } from '../core/marionette-port.js';
7
7
  import { formatMarionettePreflightLine, reportMarionettePreflight, runMarionettePreflight, } from '../core/marionette-preflight.js';
8
8
  import { checkStaleBuildForTest, formatStaleBuildWarning } from '../core/test-stale-check.js';
9
9
  import { operatorAlreadySetAppPath, resolveXpcshellAppdirArg, } from '../core/xpcshell-appdir.js';
@@ -326,21 +326,22 @@ export async function testCommand(projectRoot, testPaths, options = {}) {
326
326
  //
327
327
  // Skip forwarding when the operator already supplied an equivalent arg
328
328
  // via `--mach-arg` — duplicates would be confusing without changing
329
- // semantics. Skip with a notice for clearly-non-marionette flavours
330
- // (xpcshell, or paths that don't look browser-chrome/mochitest) so the
331
- // operator knows the preflight took the override but mach was not
332
- // auto-configured. Same escape valve applies: any mach arg can still
333
- // be supplied via `--mach-arg`.
329
+ // semantics. Skip when mach args explicitly request `--flavor=xpcshell`
330
+ // (or `xpcshell-tests`): the preflight still honours `--marionette-port`,
331
+ // but mach does not use the marionette.port pref on that harness. Any
332
+ // other arg shape still forwards so toolkit widget paths and mixed suites
333
+ // stay aligned with the probe without duplicate `--mach-arg` flags.
334
334
  if (options.marionettePort !== undefined) {
335
335
  const operatorAlreadyForwarded = forwardedPort !== undefined;
336
+ const machArgs = options.machArg ?? [];
336
337
  if (operatorAlreadyForwarded) {
337
338
  info(`--marionette-port=${options.marionettePort} set, but the same port is already forwarded via --mach-arg; skipping auto-forward.`);
338
339
  }
339
- else if (isMarionetteFlavor(normalizedPaths, options.machArg ?? [])) {
340
+ else if (shouldAutoForwardMarionettePortToMach(machArgs)) {
340
341
  extraArgs.push(`--setpref=marionette.port=${options.marionettePort}`);
341
342
  }
342
343
  else {
343
- info(`--marionette-port=${options.marionettePort} applied to the preflight probe, but the test paths do not look browser-chrome/mochitest — mach is not auto-configured. Pass --mach-arg --setpref=marionette.port=${options.marionettePort} explicitly if mach should also use this port.`);
344
+ info(`--marionette-port=${options.marionettePort} applied to the preflight probe, but --flavor=xpcshell is set — mach is not auto-configured with --setpref=marionette.port (xpcshell ignores that pref). Pass --mach-arg --setpref=marionette.port=${options.marionettePort} explicitly if you still need mach to see the port.`);
344
345
  }
345
346
  }
346
347
  // xpcshell appdir auto-injection — see src/core/xpcshell-appdir.ts for the
@@ -408,7 +409,7 @@ export function registerTest(program, { getProjectRoot, withErrorHandling }) {
408
409
  acc.push(value);
409
410
  return acc;
410
411
  }, [])
411
- .option('--marionette-port <port>', 'Override the Marionette control port (default 2828) for the stale-browser probe, the --doctor preflight, and the auto-forwarded --setpref=marionette.port=<n> arg passed to mach. Use this when a stale process holds 2828 or a CI runner reserves a different port.', (raw) => {
412
+ .option('--marionette-port <port>', 'Override the Marionette control port (default 2828) for the stale-browser probe, the --doctor preflight, and (unless --mach-arg includes --flavor=xpcshell) the auto-forwarded --setpref=marionette.port=<n> passed to mach. Use this when a stale process holds 2828 or a CI runner reserves a different port.', (raw) => {
412
413
  const n = Number.parseInt(raw, 10);
413
414
  if (!Number.isFinite(n) || n < 1 || n > 65535) {
414
415
  throw new GeneralError(`--marionette-port must be an integer in 1..65535 (got "${raw}")`);
@@ -64,13 +64,31 @@ export declare function assertMarionettePortAvailable(port?: number, options?: {
64
64
  * `undefined`.
65
65
  */
66
66
  export declare function extractForwardedMarionettePort(machArgs: string[]): number | undefined;
67
+ /**
68
+ * True when forwarded mach args explicitly select the xpcshell harness.
69
+ * Used so `--marionette-port` auto-forward skips `--setpref=marionette.port`
70
+ * for runs where the pref is ignored anyway.
71
+ */
72
+ export declare function hasExplicitXpcshellFlavor(machArgs: string[]): boolean;
73
+ /**
74
+ * Whether `fireforge test` should append `--setpref=marionette.port=<n>` when
75
+ * the operator passed `--marionette-port`. Forwards for every harness except
76
+ * an explicit `--flavor=xpcshell` / `xpcshell-tests` (toolkit widget mochitests
77
+ * under `toolkit/content/tests/` do not match the older path-only heuristic
78
+ * but still launch a Marionette-driven browser).
79
+ */
80
+ export declare function shouldAutoForwardMarionettePortToMach(machArgs: string[]): boolean;
67
81
  /**
68
82
  * Heuristic: do the test paths or forwarded mach args indicate a flavour
69
83
  * that actually launches a Marionette-driven browser? Browser-chrome and
70
- * mochitest do; xpcshell does not. Used to decide whether to auto-forward
71
- * `--setpref=marionette.port=<n>` to mach when the operator passed
72
- * `--marionette-port`. A no-paths invocation (the default "run all tests"
73
- * shape) is treated as marionette-relevant since it includes browser-chrome.
84
+ * mochitest do; xpcshell does not. A no-paths invocation (the default "run
85
+ * all tests" shape) is treated as marionette-relevant since it includes
86
+ * browser-chrome.
87
+ *
88
+ * Note: `fireforge test` auto-forward of `--marionette-port` to mach uses
89
+ * {@link shouldAutoForwardMarionettePortToMach} (mach-arg flavor gate) rather
90
+ * than this function alone, so toolkit paths without `/mochitest/` still get
91
+ * the pref when appropriate.
74
92
  *
75
93
  * @param testPaths - Engine-relative paths after `stripEnginePrefix`.
76
94
  * @param machArgs - Forwarded mach args (post-`--mach-arg`).
@@ -260,23 +260,47 @@ export function extractForwardedMarionettePort(machArgs) {
260
260
  }
261
261
  return undefined;
262
262
  }
263
+ /**
264
+ * True when forwarded mach args explicitly select the xpcshell harness.
265
+ * Used so `--marionette-port` auto-forward skips `--setpref=marionette.port`
266
+ * for runs where the pref is ignored anyway.
267
+ */
268
+ export function hasExplicitXpcshellFlavor(machArgs) {
269
+ for (const arg of machArgs) {
270
+ if (/^--flavor=xpcshell\b/.test(arg) || arg === '--flavor=xpcshell-tests')
271
+ return true;
272
+ }
273
+ return false;
274
+ }
275
+ /**
276
+ * Whether `fireforge test` should append `--setpref=marionette.port=<n>` when
277
+ * the operator passed `--marionette-port`. Forwards for every harness except
278
+ * an explicit `--flavor=xpcshell` / `xpcshell-tests` (toolkit widget mochitests
279
+ * under `toolkit/content/tests/` do not match the older path-only heuristic
280
+ * but still launch a Marionette-driven browser).
281
+ */
282
+ export function shouldAutoForwardMarionettePortToMach(machArgs) {
283
+ return !hasExplicitXpcshellFlavor(machArgs);
284
+ }
263
285
  /**
264
286
  * Heuristic: do the test paths or forwarded mach args indicate a flavour
265
287
  * that actually launches a Marionette-driven browser? Browser-chrome and
266
- * mochitest do; xpcshell does not. Used to decide whether to auto-forward
267
- * `--setpref=marionette.port=<n>` to mach when the operator passed
268
- * `--marionette-port`. A no-paths invocation (the default "run all tests"
269
- * shape) is treated as marionette-relevant since it includes browser-chrome.
288
+ * mochitest do; xpcshell does not. A no-paths invocation (the default "run
289
+ * all tests" shape) is treated as marionette-relevant since it includes
290
+ * browser-chrome.
291
+ *
292
+ * Note: `fireforge test` auto-forward of `--marionette-port` to mach uses
293
+ * {@link shouldAutoForwardMarionettePortToMach} (mach-arg flavor gate) rather
294
+ * than this function alone, so toolkit paths without `/mochitest/` still get
295
+ * the pref when appropriate.
270
296
  *
271
297
  * @param testPaths - Engine-relative paths after `stripEnginePrefix`.
272
298
  * @param machArgs - Forwarded mach args (post-`--mach-arg`).
273
299
  * @returns `true` when the run is likely to bind a Marionette listener.
274
300
  */
275
301
  export function isMarionetteFlavor(testPaths, machArgs) {
276
- for (const arg of machArgs) {
277
- if (/^--flavor=xpcshell\b/.test(arg) || arg === '--flavor=xpcshell-tests')
278
- return false;
279
- }
302
+ if (hasExplicitXpcshellFlavor(machArgs))
303
+ return false;
280
304
  for (const arg of machArgs) {
281
305
  if (/^--flavor=(browser-chrome|mochitest|chrome|a11y)\b/.test(arg))
282
306
  return true;
@@ -291,6 +315,9 @@ export function isMarionetteFlavor(testPaths, machArgs) {
291
315
  return true;
292
316
  if (path.includes('/browser-chrome/') || path.startsWith('browser-chrome/'))
293
317
  return true;
318
+ if (path.includes('toolkit/content/tests/') && !path.includes('/tests/xpcshell/')) {
319
+ return true;
320
+ }
294
321
  }
295
322
  return false;
296
323
  }
@@ -26,8 +26,12 @@ export declare const SHIM_FILENAME = "__fireforge_firefox_globals.d.ts";
26
26
  * - `Ci`, `Cc`, `Cr`, `Cu` are XPCOM component shortcuts.
27
27
  * - Browser chrome globals like `gBrowser`, `gURLBar` are common in
28
28
  * content scripts wired via `browser.js`.
29
+ * - Dynamic `import("resource:-…")` / `import("chrome:-…")` under patch
30
+ * checkJs: the compiler sees empty stubs (`noResolve`); without URL
31
+ * ambient modules namespaces degrade to unusable typings. Wildcards
32
+ * keep Firefox URL imports pragmatically loose, same posture as globals.
29
33
  */
30
- export declare const FIREFOX_GLOBALS_SHIM = "\ndeclare var Services: any;\ndeclare var ChromeUtils: {\n defineESModuleGetters(target: any, modules: Record<string, string>): void;\n importESModule(specifier: string): any;\n import(specifier: string): any;\n defineModuleGetter(target: any, name: string, specifier: string): void;\n generateQI(interfaces: any[]): Function;\n isClassInfo(obj: any): boolean;\n};\ndeclare var Cu: any;\ndeclare var Ci: any;\ndeclare var Cc: any;\ndeclare var Cr: any;\ndeclare var Components: any;\ndeclare var XPCOMUtils: any;\ndeclare var lazy: Record<string, any>;\ndeclare var PathUtils: any;\ndeclare var IOUtils: any;\ndeclare var FileUtils: any;\ndeclare var gBrowser: any;\ndeclare var gURLBar: any;\ndeclare var gNavigatorBundle: any;\ndeclare var AppConstants: any;\n";
34
+ export declare const FIREFOX_GLOBALS_SHIM = "\ndeclare var Services: any;\ndeclare var ChromeUtils: {\n defineESModuleGetters(target: any, modules: Record<string, string>): void;\n importESModule(specifier: string): any;\n import(specifier: string): any;\n defineModuleGetter(target: any, name: string, specifier: string): void;\n generateQI(interfaces: any[]): Function;\n isClassInfo(obj: any): boolean;\n};\ndeclare var Cu: any;\ndeclare var Ci: any;\ndeclare var Cc: any;\ndeclare var Cr: any;\ndeclare var Components: any;\ndeclare var XPCOMUtils: any;\ndeclare var lazy: Record<string, any>;\ndeclare var PathUtils: any;\ndeclare var IOUtils: any;\ndeclare var FileUtils: any;\ndeclare var gBrowser: any;\ndeclare var gURLBar: any;\ndeclare var gNavigatorBundle: any;\ndeclare var AppConstants: any;\n\n// Shorthand ambient modules \u2014 exports from matching URL imports are loosely typed,\n// avoiding noResolve empty-graph namespaces. (Named member access broke when we tried\n// export= Record under moduleResolution Bundler.)\ndeclare module 'resource:*';\ndeclare module 'chrome:*';\n\n";
31
35
  /**
32
36
  * TS diagnostic codes suppressed by both the patch-lint checkJs pass
33
37
  * and the whole-project typecheck command. Each is a known false
@@ -29,6 +29,10 @@ export const SHIM_FILENAME = '__fireforge_firefox_globals.d.ts';
29
29
  * - `Ci`, `Cc`, `Cr`, `Cu` are XPCOM component shortcuts.
30
30
  * - Browser chrome globals like `gBrowser`, `gURLBar` are common in
31
31
  * content scripts wired via `browser.js`.
32
+ * - Dynamic `import("resource:-…")` / `import("chrome:-…")` under patch
33
+ * checkJs: the compiler sees empty stubs (`noResolve`); without URL
34
+ * ambient modules namespaces degrade to unusable typings. Wildcards
35
+ * keep Firefox URL imports pragmatically loose, same posture as globals.
32
36
  */
33
37
  export const FIREFOX_GLOBALS_SHIM = `
34
38
  declare var Services: any;
@@ -54,6 +58,13 @@ declare var gBrowser: any;
54
58
  declare var gURLBar: any;
55
59
  declare var gNavigatorBundle: any;
56
60
  declare var AppConstants: any;
61
+
62
+ // Shorthand ambient modules — exports from matching URL imports are loosely typed,
63
+ // avoiding noResolve empty-graph namespaces. (Named member access broke when we tried
64
+ // export= Record under moduleResolution Bundler.)
65
+ declare module 'resource:*';
66
+ declare module 'chrome:*';
67
+
57
68
  `;
58
69
  /**
59
70
  * TS diagnostic codes suppressed by both the patch-lint checkJs pass
@@ -319,9 +319,10 @@ export interface TestOptions {
319
319
  /**
320
320
  * Override the Marionette control port (default 2828) used by the
321
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.
322
+ * `--setpref=marionette.port=<n>` arg passed to mach (omitted when mach
323
+ * args explicitly set `--flavor=xpcshell` / `xpcshell-tests`). Set this
324
+ * when a stale process holds the default port and `kill` is not an option,
325
+ * or when a CI runner reserves a different port for parallel test runs.
325
326
  */
326
327
  marionettePort?: number;
327
328
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hominis/fireforge",
3
- "version": "0.19.1",
3
+ "version": "0.19.3",
4
4
  "description": "FireForge — a build tool for customizing Firefox",
5
5
  "type": "module",
6
6
  "main": "./dist/src/index.js",