extension 4.0.7 → 4.0.8

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/876.cjs CHANGED
@@ -177,7 +177,7 @@ exports.modules = {
177
177
  if ('pipe' === this.transport) {
178
178
  try {
179
179
  this.pipeIn?.removeAllListeners();
180
- this.pipeOut?.end();
180
+ this.pipeIn?.resume();
181
181
  } catch {}
182
182
  this.pipeIn = null;
183
183
  this.pipeOut = null;
@@ -195,7 +195,15 @@ exports.modules = {
195
195
  if (!this.isConnected()) return void this.stopHeartbeat();
196
196
  try {
197
197
  await this.getBrowserVersion();
198
+ this.heartbeatStallWarned = false;
198
199
  } catch {
200
+ if ('pipe' === this.transport) {
201
+ if (!this.heartbeatStallWarned) {
202
+ this.heartbeatStallWarned = true;
203
+ console.warn('[CDP] Browser is not answering CDP commands (heartbeat timed out). Keeping the session — it resumes automatically if the browser recovers.');
204
+ }
205
+ return;
206
+ }
199
207
  if (this.isDev()) console.warn('[CDP] Heartbeat failed, connection appears dead');
200
208
  this.disconnect();
201
209
  }
@@ -331,6 +339,7 @@ exports.modules = {
331
339
  _define_property(this, "messageId", 0);
332
340
  _define_property(this, "pendingRequests", new Map());
333
341
  _define_property(this, "heartbeatTimer", null);
342
+ _define_property(this, "heartbeatStallWarned", false);
334
343
  this.port = port;
335
344
  this.host = host;
336
345
  }
package/dist/browsers.cjs CHANGED
@@ -466,7 +466,7 @@ var __webpack_modules__ = {
466
466
  function chromiumInvalidMatchPatterns(extensionPath, patterns) {
467
467
  const shown = patterns.slice(0, 6);
468
468
  const more = patterns.length - shown.length;
469
- return `${getLoggingPrefix('warn')} ${pintor__rspack_import_4_default().brightYellow('This extension declares match patterns Chrome refuses — the whole extension will not load.')}\n${pintor__rspack_import_4_default().gray('PATH')} ${pintor__rspack_import_4_default().underline(extensionPath)}\n` + shown.map((pattern)=>`${pintor__rspack_import_4_default().gray('PATTERN')} ${pintor__rspack_import_4_default().red(pattern)}\n`).join('') + (more > 0 ? `${pintor__rspack_import_4_default().gray(`…and ${more} more`)}\n` : '') + "Match patterns cannot contain a query string, fragment, or port, and a host wildcard " + `must be ${pintor__rspack_import_4_default().blue('*')} or ${pintor__rspack_import_4_default().blue('*.domain.tld')}. ` + `Replace the invalid part with ${pintor__rspack_import_4_default().blue('*')} (e.g. ${pintor__rspack_import_4_default().blue('/page*')} instead of ${pintor__rspack_import_4_default().blue('/page?id=*')}) in the source manifest.`;
469
+ return `${getLoggingPrefix('warn')} ${pintor__rspack_import_4_default().brightYellow('This extension declares match patterns Chrome refuses — the whole extension will not load.')}\n${pintor__rspack_import_4_default().gray('PATH')} ${pintor__rspack_import_4_default().underline(extensionPath)}\n` + shown.map((pattern)=>`${pintor__rspack_import_4_default().gray('PATTERN')} ${pintor__rspack_import_4_default().red(pattern)}\n`).join('') + (more > 0 ? `${pintor__rspack_import_4_default().gray(`…and ${more} more`)}\n` : '') + `A match pattern's host wildcard must be ${pintor__rspack_import_4_default().blue('*')} or ${pintor__rspack_import_4_default().blue('*.domain.tld')} ` + "a wildcard anywhere else in the host is invalid. " + `Replace the host with ${pintor__rspack_import_4_default().blue('*')} or ${pintor__rspack_import_4_default().blue('*.domain.tld')} in the source manifest.`;
470
470
  }
471
471
  function chromiumManifestLoadBlockers(extensionPath, blockers) {
472
472
  return `${getLoggingPrefix('warn')} ${pintor__rspack_import_4_default().brightYellow('This manifest declares shapes Chrome refuses — the whole extension will not load.')}\n${pintor__rspack_import_4_default().gray('PATH')} ${pintor__rspack_import_4_default().underline(extensionPath)}\n` + blockers.map((blocker)=>`${pintor__rspack_import_4_default().gray('REASON')} ${pintor__rspack_import_4_default().red(blocker)}\n`).join('') + "Chrome rejects the extension at load, so no service worker or content script ever runs. Fix these in the source manifest.";
@@ -1003,6 +1003,10 @@ var __webpack_modules__ = {
1003
1003
  var child_process__rspack_import_0 = __webpack_require__("child_process");
1004
1004
  var _messages__rspack_import_1 = __webpack_require__("./browsers/browsers-lib/messages.ts");
1005
1005
  const FORCE_KILL_GRACE_MS = 5000;
1006
+ const terminatedByUs = new WeakSet();
1007
+ function wasTerminatedByUs(child) {
1008
+ return !!child && terminatedByUs.has(child);
1009
+ }
1006
1010
  function authorLog(line) {
1007
1011
  if (line && 'true' === process.env.EXTENSION_AUTHOR_MODE) console.log(line);
1008
1012
  }
@@ -1027,6 +1031,7 @@ var __webpack_modules__ = {
1027
1031
  }
1028
1032
  function gracefulTerminateChild(child, browser) {
1029
1033
  if (!child || child.killed) return;
1034
+ terminatedByUs.add(child);
1030
1035
  killWindowsTree(child, false);
1031
1036
  authorLog(_messages__rspack_import_1.XH(browser));
1032
1037
  child.kill('SIGTERM');
@@ -1040,6 +1045,7 @@ var __webpack_modules__ = {
1040
1045
  }
1041
1046
  function forceKillChildOnExit(child, browser) {
1042
1047
  if (!child) return;
1048
+ terminatedByUs.add(child);
1043
1049
  killWindowsTree(child, true);
1044
1050
  try {
1045
1051
  authorLog(_messages__rspack_import_1.AG(browser));
@@ -1060,7 +1066,8 @@ var __webpack_modules__ = {
1060
1066
  __webpack_require__.d(__webpack_exports__, {
1061
1067
  $Y: ()=>forceKillChildOnExit,
1062
1068
  Df: ()=>gracefulTerminateChild,
1063
- FA: ()=>isBenignSocketTeardown
1069
+ FA: ()=>isBenignSocketTeardown,
1070
+ Op: ()=>wasTerminatedByUs
1064
1071
  });
1065
1072
  },
1066
1073
  "./browsers/browsers-lib/ready-message.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
@@ -1775,15 +1782,24 @@ var __webpack_modules__ = {
1775
1782
  contentScript?.exclude_matches
1776
1783
  ])if (Array.isArray(list)) patterns.push(...list);
1777
1784
  for (const resource of Array.isArray(m?.web_accessible_resources) ? m.web_accessible_resources : [])if (Array.isArray(resource?.matches)) patterns.push(...resource.matches);
1778
- const invalid = patterns.filter((pattern)=>'string' == typeof pattern && '<all_urls>' !== pattern && (pattern.includes('?') || pattern.includes('#') || hasInvalidHostWildcard(pattern)));
1785
+ const invalid = patterns.filter((pattern)=>'string' == typeof pattern && '<all_urls>' !== pattern && hasInvalidHostWildcard(pattern));
1779
1786
  return [
1780
1787
  ...new Set(invalid)
1781
1788
  ];
1782
1789
  }
1783
1790
  function hasInvalidHostWildcard(pattern) {
1784
1791
  const match = /^[a-zA-Z*]+:\/\/([^/]*)/.exec(pattern);
1785
- const host = match?.[1];
1786
- if (!host || !host.includes('*')) return false;
1792
+ const authority = match?.[1];
1793
+ if (!authority) return false;
1794
+ let host = authority;
1795
+ if (authority.startsWith('[')) {
1796
+ const end = authority.indexOf(']');
1797
+ if (-1 !== end) host = authority.slice(0, end + 1);
1798
+ } else {
1799
+ const colon = authority.indexOf(':');
1800
+ if (-1 !== colon) host = authority.slice(0, colon);
1801
+ }
1802
+ if (!host.includes('*')) return false;
1787
1803
  return '*' !== host && !/^\*\.[^*]+$/.test(host);
1788
1804
  }
1789
1805
  function findChromiumLoadBlockers(manifest) {
@@ -1848,6 +1864,7 @@ var __webpack_modules__ = {
1848
1864
  var ready_message = __webpack_require__("./browsers/browsers-lib/ready-message.ts");
1849
1865
  var runtime_options = __webpack_require__("./browsers/browsers-lib/runtime-options.ts");
1850
1866
  var shared_utils = __webpack_require__("./browsers/browsers-lib/shared-utils.ts");
1867
+ var process_teardown = __webpack_require__("./browsers/browsers-lib/process-teardown.ts");
1851
1868
  var discovery = __webpack_require__("./browsers/run-chromium/cdp/discovery.ts");
1852
1869
  var manifest_readiness = __webpack_require__("./browsers/run-chromium/manifest-readiness.ts");
1853
1870
  var resolve_profile = __webpack_require__("./browsers/browsers-lib/resolve-profile.ts");
@@ -2087,7 +2104,6 @@ var __webpack_modules__ = {
2087
2104
  console.log(messages.E8(chromiumConfig.join(' ')));
2088
2105
  }
2089
2106
  var extension_output_path = __webpack_require__("./browsers/run-chromium/chromium-launch/extension-output-path.ts");
2090
- var process_teardown = __webpack_require__("./browsers/browsers-lib/process-teardown.ts");
2091
2107
  const activeInstances = new Set();
2092
2108
  let globalHandlersInstalled = false;
2093
2109
  function cleanupOne(instance) {
@@ -2288,6 +2304,17 @@ var __webpack_modules__ = {
2288
2304
  browserVersionLine: args.browserVersionLine
2289
2305
  });
2290
2306
  }
2307
+ function stampReadyBrowserExited(extensionOutputPath, code) {
2308
+ try {
2309
+ if (!extensionOutputPath) return;
2310
+ const readyPath = external_path_.join(external_path_.dirname(extensionOutputPath), 'extension-js', external_path_.basename(extensionOutputPath), 'ready.json');
2311
+ if (!external_fs_.existsSync(readyPath)) return;
2312
+ const ready = JSON.parse(external_fs_.readFileSync(readyPath, 'utf-8'));
2313
+ ready.browserExitedAt = new Date().toISOString();
2314
+ ready.browserExitCode = code;
2315
+ external_fs_.writeFileSync(readyPath, JSON.stringify(ready, null, 2));
2316
+ } catch {}
2317
+ }
2291
2318
  class ChromiumLaunchPlugin {
2292
2319
  async runOnce(compilation, opts) {
2293
2320
  if (!this.logger) this.logger = {
@@ -2658,6 +2685,10 @@ var __webpack_modules__ = {
2658
2685
  });
2659
2686
  if (this.options.dryRun) return void logChromiumDryRun(browserBinaryLocation, chromiumConfig);
2660
2687
  const usePipe = chromiumConfig.includes('--remote-debugging-pipe');
2688
+ this.closeHandlerContext = {
2689
+ isDevMode: 'development' === compilation.options.mode,
2690
+ extensionOutputPath: (0, extension_output_path.W)(compilation, chromiumConfig.find((flag)=>flag.startsWith('--load-extension='))) || void 0
2691
+ };
2661
2692
  const child = await this.launchWithDirectSpawn(browserBinaryLocation, chromiumConfig, usePipe);
2662
2693
  const pipeStreams = usePipe && child?.stdio?.[3] && child?.stdio?.[4] ? {
2663
2694
  input: child.stdio[4],
@@ -2760,6 +2791,10 @@ var __webpack_modules__ = {
2760
2791
  let disposeSignalHandlers;
2761
2792
  child.on('close', (code)=>{
2762
2793
  if ('true' === process.env.EXTENSION_AUTHOR_MODE) this.logger.info(messages.nn(code || 0));
2794
+ if (!(0, process_teardown.Op)(child) && this.closeHandlerContext?.isDevMode) {
2795
+ this.logger.error(`[browser] ${this.options.browser} exited mid-session (code ${code ?? 'unknown'}). The dev server is still running but reloads cannot be delivered — restart "extension dev" to relaunch the browser.`);
2796
+ stampReadyBrowserExited(this.closeHandlerContext.extensionOutputPath, code);
2797
+ }
2763
2798
  disposeSignalHandlers?.();
2764
2799
  const userDataDir = launchArgs.find((arg)=>arg.startsWith('--user-data-dir='))?.slice('--user-data-dir='.length).replace(/^"|"$/g, '');
2765
2800
  shared_utils.sW(userDataDir);
@@ -2794,10 +2829,12 @@ var __webpack_modules__ = {
2794
2829
  _define_property(this, "didLaunch", void 0);
2795
2830
  _define_property(this, "didReportReady", void 0);
2796
2831
  _define_property(this, "logger", void 0);
2832
+ _define_property(this, "closeHandlerContext", void 0);
2797
2833
  this.options = options;
2798
2834
  this.ctx = ctx;
2799
2835
  this.didLaunch = false;
2800
2836
  this.didReportReady = false;
2837
+ this.closeHandlerContext = null;
2801
2838
  }
2802
2839
  }
2803
2840
  },
package/dist/cli.cjs CHANGED
@@ -467,7 +467,7 @@ var __webpack_modules__ = {
467
467
  function chromiumInvalidMatchPatterns(extensionPath, patterns) {
468
468
  const shown = patterns.slice(0, 6);
469
469
  const more = patterns.length - shown.length;
470
- return `${getLoggingPrefix('warn')} ${pintor__rspack_import_4_default().brightYellow('This extension declares match patterns Chrome refuses — the whole extension will not load.')}\n${pintor__rspack_import_4_default().gray('PATH')} ${pintor__rspack_import_4_default().underline(extensionPath)}\n` + shown.map((pattern)=>`${pintor__rspack_import_4_default().gray('PATTERN')} ${pintor__rspack_import_4_default().red(pattern)}\n`).join('') + (more > 0 ? `${pintor__rspack_import_4_default().gray(`…and ${more} more`)}\n` : '') + "Match patterns cannot contain a query string, fragment, or port, and a host wildcard " + `must be ${pintor__rspack_import_4_default().blue('*')} or ${pintor__rspack_import_4_default().blue('*.domain.tld')}. ` + `Replace the invalid part with ${pintor__rspack_import_4_default().blue('*')} (e.g. ${pintor__rspack_import_4_default().blue('/page*')} instead of ${pintor__rspack_import_4_default().blue('/page?id=*')}) in the source manifest.`;
470
+ return `${getLoggingPrefix('warn')} ${pintor__rspack_import_4_default().brightYellow('This extension declares match patterns Chrome refuses — the whole extension will not load.')}\n${pintor__rspack_import_4_default().gray('PATH')} ${pintor__rspack_import_4_default().underline(extensionPath)}\n` + shown.map((pattern)=>`${pintor__rspack_import_4_default().gray('PATTERN')} ${pintor__rspack_import_4_default().red(pattern)}\n`).join('') + (more > 0 ? `${pintor__rspack_import_4_default().gray(`…and ${more} more`)}\n` : '') + `A match pattern's host wildcard must be ${pintor__rspack_import_4_default().blue('*')} or ${pintor__rspack_import_4_default().blue('*.domain.tld')} ` + "a wildcard anywhere else in the host is invalid. " + `Replace the host with ${pintor__rspack_import_4_default().blue('*')} or ${pintor__rspack_import_4_default().blue('*.domain.tld')} in the source manifest.`;
471
471
  }
472
472
  function chromiumManifestLoadBlockers(extensionPath, blockers) {
473
473
  return `${getLoggingPrefix('warn')} ${pintor__rspack_import_4_default().brightYellow('This manifest declares shapes Chrome refuses — the whole extension will not load.')}\n${pintor__rspack_import_4_default().gray('PATH')} ${pintor__rspack_import_4_default().underline(extensionPath)}\n` + blockers.map((blocker)=>`${pintor__rspack_import_4_default().gray('REASON')} ${pintor__rspack_import_4_default().red(blocker)}\n`).join('') + "Chrome rejects the extension at load, so no service worker or content script ever runs. Fix these in the source manifest.";
@@ -1090,6 +1090,10 @@ var __webpack_modules__ = {
1090
1090
  var child_process__rspack_import_0 = __webpack_require__("child_process");
1091
1091
  var _messages__rspack_import_1 = __webpack_require__("./browsers/browsers-lib/messages.ts");
1092
1092
  const FORCE_KILL_GRACE_MS = 5000;
1093
+ const terminatedByUs = new WeakSet();
1094
+ function wasTerminatedByUs(child) {
1095
+ return !!child && terminatedByUs.has(child);
1096
+ }
1093
1097
  function authorLog(line) {
1094
1098
  if (line && 'true' === process.env.EXTENSION_AUTHOR_MODE) console.log(line);
1095
1099
  }
@@ -1114,6 +1118,7 @@ var __webpack_modules__ = {
1114
1118
  }
1115
1119
  function gracefulTerminateChild(child, browser) {
1116
1120
  if (!child || child.killed) return;
1121
+ terminatedByUs.add(child);
1117
1122
  killWindowsTree(child, false);
1118
1123
  authorLog(_messages__rspack_import_1.XH(browser));
1119
1124
  child.kill('SIGTERM');
@@ -1127,6 +1132,7 @@ var __webpack_modules__ = {
1127
1132
  }
1128
1133
  function forceKillChildOnExit(child, browser) {
1129
1134
  if (!child) return;
1135
+ terminatedByUs.add(child);
1130
1136
  killWindowsTree(child, true);
1131
1137
  try {
1132
1138
  authorLog(_messages__rspack_import_1.AG(browser));
@@ -1147,7 +1153,8 @@ var __webpack_modules__ = {
1147
1153
  __webpack_require__.d(__webpack_exports__, {
1148
1154
  $Y: ()=>forceKillChildOnExit,
1149
1155
  Df: ()=>gracefulTerminateChild,
1150
- FA: ()=>isBenignSocketTeardown
1156
+ FA: ()=>isBenignSocketTeardown,
1157
+ Op: ()=>wasTerminatedByUs
1151
1158
  });
1152
1159
  },
1153
1160
  "./browsers/browsers-lib/ready-message.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
@@ -1860,15 +1867,24 @@ var __webpack_modules__ = {
1860
1867
  contentScript?.exclude_matches
1861
1868
  ])if (Array.isArray(list)) patterns.push(...list);
1862
1869
  for (const resource of Array.isArray(m?.web_accessible_resources) ? m.web_accessible_resources : [])if (Array.isArray(resource?.matches)) patterns.push(...resource.matches);
1863
- const invalid = patterns.filter((pattern)=>'string' == typeof pattern && '<all_urls>' !== pattern && (pattern.includes('?') || pattern.includes('#') || hasInvalidHostWildcard(pattern)));
1870
+ const invalid = patterns.filter((pattern)=>'string' == typeof pattern && '<all_urls>' !== pattern && hasInvalidHostWildcard(pattern));
1864
1871
  return [
1865
1872
  ...new Set(invalid)
1866
1873
  ];
1867
1874
  }
1868
1875
  function hasInvalidHostWildcard(pattern) {
1869
1876
  const match = /^[a-zA-Z*]+:\/\/([^/]*)/.exec(pattern);
1870
- const host = match?.[1];
1871
- if (!host || !host.includes('*')) return false;
1877
+ const authority = match?.[1];
1878
+ if (!authority) return false;
1879
+ let host = authority;
1880
+ if (authority.startsWith('[')) {
1881
+ const end = authority.indexOf(']');
1882
+ if (-1 !== end) host = authority.slice(0, end + 1);
1883
+ } else {
1884
+ const colon = authority.indexOf(':');
1885
+ if (-1 !== colon) host = authority.slice(0, colon);
1886
+ }
1887
+ if (!host.includes('*')) return false;
1872
1888
  return '*' !== host && !/^\*\.[^*]+$/.test(host);
1873
1889
  }
1874
1890
  function findChromiumLoadBlockers(manifest) {
@@ -1933,6 +1949,7 @@ var __webpack_modules__ = {
1933
1949
  var ready_message = __webpack_require__("./browsers/browsers-lib/ready-message.ts");
1934
1950
  var runtime_options = __webpack_require__("./browsers/browsers-lib/runtime-options.ts");
1935
1951
  var shared_utils = __webpack_require__("./browsers/browsers-lib/shared-utils.ts");
1952
+ var process_teardown = __webpack_require__("./browsers/browsers-lib/process-teardown.ts");
1936
1953
  var discovery = __webpack_require__("./browsers/run-chromium/cdp/discovery.ts");
1937
1954
  var manifest_readiness = __webpack_require__("./browsers/run-chromium/manifest-readiness.ts");
1938
1955
  var resolve_profile = __webpack_require__("./browsers/browsers-lib/resolve-profile.ts");
@@ -2172,7 +2189,6 @@ var __webpack_modules__ = {
2172
2189
  console.log(messages.E8(chromiumConfig.join(' ')));
2173
2190
  }
2174
2191
  var extension_output_path = __webpack_require__("./browsers/run-chromium/chromium-launch/extension-output-path.ts");
2175
- var process_teardown = __webpack_require__("./browsers/browsers-lib/process-teardown.ts");
2176
2192
  const activeInstances = new Set();
2177
2193
  let globalHandlersInstalled = false;
2178
2194
  function cleanupOne(instance) {
@@ -2373,6 +2389,17 @@ var __webpack_modules__ = {
2373
2389
  browserVersionLine: args.browserVersionLine
2374
2390
  });
2375
2391
  }
2392
+ function stampReadyBrowserExited(extensionOutputPath, code) {
2393
+ try {
2394
+ if (!extensionOutputPath) return;
2395
+ const readyPath = external_path_.join(external_path_.dirname(extensionOutputPath), 'extension-js', external_path_.basename(extensionOutputPath), 'ready.json');
2396
+ if (!external_fs_.existsSync(readyPath)) return;
2397
+ const ready = JSON.parse(external_fs_.readFileSync(readyPath, 'utf-8'));
2398
+ ready.browserExitedAt = new Date().toISOString();
2399
+ ready.browserExitCode = code;
2400
+ external_fs_.writeFileSync(readyPath, JSON.stringify(ready, null, 2));
2401
+ } catch {}
2402
+ }
2376
2403
  class ChromiumLaunchPlugin {
2377
2404
  async runOnce(compilation, opts) {
2378
2405
  if (!this.logger) this.logger = {
@@ -2743,6 +2770,10 @@ var __webpack_modules__ = {
2743
2770
  });
2744
2771
  if (this.options.dryRun) return void logChromiumDryRun(browserBinaryLocation, chromiumConfig);
2745
2772
  const usePipe = chromiumConfig.includes('--remote-debugging-pipe');
2773
+ this.closeHandlerContext = {
2774
+ isDevMode: 'development' === compilation.options.mode,
2775
+ extensionOutputPath: (0, extension_output_path.W)(compilation, chromiumConfig.find((flag)=>flag.startsWith('--load-extension='))) || void 0
2776
+ };
2746
2777
  const child = await this.launchWithDirectSpawn(browserBinaryLocation, chromiumConfig, usePipe);
2747
2778
  const pipeStreams = usePipe && child?.stdio?.[3] && child?.stdio?.[4] ? {
2748
2779
  input: child.stdio[4],
@@ -2845,6 +2876,10 @@ var __webpack_modules__ = {
2845
2876
  let disposeSignalHandlers;
2846
2877
  child.on('close', (code)=>{
2847
2878
  if ('true' === process.env.EXTENSION_AUTHOR_MODE) this.logger.info(messages.nn(code || 0));
2879
+ if (!(0, process_teardown.Op)(child) && this.closeHandlerContext?.isDevMode) {
2880
+ this.logger.error(`[browser] ${this.options.browser} exited mid-session (code ${code ?? 'unknown'}). The dev server is still running but reloads cannot be delivered — restart "extension dev" to relaunch the browser.`);
2881
+ stampReadyBrowserExited(this.closeHandlerContext.extensionOutputPath, code);
2882
+ }
2848
2883
  disposeSignalHandlers?.();
2849
2884
  const userDataDir = launchArgs.find((arg)=>arg.startsWith('--user-data-dir='))?.slice('--user-data-dir='.length).replace(/^"|"$/g, '');
2850
2885
  shared_utils.sW(userDataDir);
@@ -2879,10 +2914,12 @@ var __webpack_modules__ = {
2879
2914
  _define_property(this, "didLaunch", void 0);
2880
2915
  _define_property(this, "didReportReady", void 0);
2881
2916
  _define_property(this, "logger", void 0);
2917
+ _define_property(this, "closeHandlerContext", void 0);
2882
2918
  this.options = options;
2883
2919
  this.ctx = ctx;
2884
2920
  this.didLaunch = false;
2885
2921
  this.didReportReady = false;
2922
+ this.closeHandlerContext = null;
2886
2923
  }
2887
2924
  }
2888
2925
  },
@@ -7,18 +7,23 @@
7
7
  export type ChromiumManifestRefusal = 'mv2' | 'mv3-background-scripts' | null;
8
8
  export declare function diagnoseChromiumManifestRefusal(manifest: unknown): ChromiumManifestRefusal;
9
9
  /**
10
- * Match patterns Chrome's grammar refuses a query string / fragment
11
- * (`?`, `#`) in the pattern. ONE invalid pattern in content_scripts
12
- * matches, host_permissions, or web_accessible_resources makes Chrome
13
- * refuse the WHOLE extension at load (wild: Ban-Checker's
14
- * `.../gcpd/730?tab=majors`). Loading the source unpacked fails
15
- * identically, so this is extension-own — but dev must say so instead of
16
- * printing an ID for an extension that never loads.
10
+ * Match patterns Chrome's grammar refuses. ONE invalid pattern in
11
+ * content_scripts matches, host_permissions, or web_accessible_resources
12
+ * makes Chrome refuse the WHOLE extension at load. The only shape verified
13
+ * to actually refuse is an invalid HOST WILDCARD (wild: CarbonWise's
14
+ * `*carbonwise*` CDP loadUnpacked reports "Invalid host wildcard").
17
15
  *
18
- * Explicit ports are NOT flagged: Chromium's URLPattern accepts them
19
- * (verified live 2026-07-11 `http://localhost:3000/*` and
20
- * `https://example.com:8888/*` install ENABLED; the wild memux subject
21
- * loads fine), so warning on them cried wolf on working extensions.
16
+ * NOT flagged, all verified live on Chrome 150 (2026-07-11, both CDP
17
+ * loadUnpacked and --load-extension, install ENABLED):
18
+ * - explicit ports (`http://localhost:3000/*`; wild memux loads fine)
19
+ * - WILDCARD ports (`ws://localhost:<star>` with a wildcard port; wild
20
+ * BinaryBeastMaster/chat-relay installs ENABLED with a live service
21
+ * worker) — the port is not part of the host
22
+ * - query strings / fragments in the path (`?`, `#` are literal path
23
+ * characters: `.../gcpd/730?tab=majors` and `/page#section` both load;
24
+ * wild SN-Utils ships a query-string exclude_matches on the store) —
25
+ * flagging them warned "the whole extension will not load" on extensions
26
+ * that load fine.
22
27
  */
23
28
  export declare function findInvalidMatchPatterns(manifest: unknown): string[];
24
29
  /**
@@ -1,6 +1,7 @@
1
1
  import { ChildProcess } from 'child_process';
2
2
  import type { BrowserType } from '../browsers-types';
3
3
  export declare const FORCE_KILL_GRACE_MS = 5000;
4
+ export declare function wasTerminatedByUs(child: ChildProcess | null): boolean;
4
5
  export declare function gracefulTerminateChild(child: ChildProcess | null, browser: BrowserType): void;
5
6
  export declare function forceKillChildOnExit(child: ChildProcess | null, browser: BrowserType): void;
6
7
  export declare function isBenignSocketTeardown(value: unknown): boolean;
@@ -17,6 +17,7 @@ export declare class CDPClient {
17
17
  private messageId;
18
18
  private pendingRequests;
19
19
  private heartbeatTimer;
20
+ private heartbeatStallWarned;
20
21
  constructor(port?: number, host?: string);
21
22
  private isDev;
22
23
  connect(): Promise<void>;
@@ -1,6 +1,7 @@
1
1
  import type { CompilationLike } from '../../browsers-types';
2
2
  import type { ChromiumContext } from '../chromium-context';
3
3
  import type { ChromiumLaunchOptions } from '../chromium-types';
4
+ export declare function stampReadyBrowserExited(extensionOutputPath: string | undefined, code: number | null): void;
4
5
  /**
5
6
  * ChromiumLaunchPlugin
6
7
  *
@@ -16,6 +17,7 @@ export declare class ChromiumLaunchPlugin {
16
17
  private didLaunch;
17
18
  private didReportReady;
18
19
  private logger;
20
+ private closeHandlerContext;
19
21
  constructor(options: ChromiumLaunchOptions, ctx: ChromiumContext);
20
22
  /**
21
23
  * Run the Chromium launch flow without requiring a bundler compiler instance.
package/package.json CHANGED
@@ -38,7 +38,7 @@
38
38
  "extension": "./bin/extension.cjs"
39
39
  },
40
40
  "name": "extension",
41
- "version": "4.0.7",
41
+ "version": "4.0.8",
42
42
  "description": "The cross-browser extension framework. Build Chrome, Edge, Firefox, and Safari extensions with no build configuration.",
43
43
  "homepage": "https://extension.js.org/",
44
44
  "bugs": {
@@ -109,9 +109,9 @@
109
109
  "vivaldi-location2": "2.1.0",
110
110
  "waterfox-location": "2.1.0",
111
111
  "yandex-location": "2.1.0",
112
- "extension-create": "4.0.7",
113
- "extension-develop": "4.0.7",
114
- "extension-install": "4.0.7",
112
+ "extension-create": "4.0.8",
113
+ "extension-develop": "4.0.8",
114
+ "extension-install": "4.0.8",
115
115
  "commander": "^15.0.0",
116
116
  "pintor": "0.3.0",
117
117
  "semver": "^7.7.3",