extension-develop 3.17.0 → 3.18.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.
Files changed (43) hide show
  1. package/dist/0~dev-server.mjs +660 -59
  2. package/dist/0~rspack-config.mjs +867 -881
  3. package/dist/0~zip.mjs +39 -10
  4. package/dist/45.mjs +39 -0
  5. package/dist/946.mjs +142 -36
  6. package/dist/962.mjs +299 -250
  7. package/dist/bridge.mjs +228 -0
  8. package/dist/extension-js-devtools/chrome/content_scripts/content-0.js +2 -2
  9. package/dist/extension-js-devtools/chrome/pages/centralized-logger.js +1 -1
  10. package/dist/extension-js-devtools/chrome/pages/welcome.js +2 -2
  11. package/dist/extension-js-devtools/chrome/scripts/logger-client.js +1 -1
  12. package/dist/extension-js-devtools/chromium/content_scripts/content-0.js +2 -2
  13. package/dist/extension-js-devtools/chromium/pages/centralized-logger.js +1 -1
  14. package/dist/extension-js-devtools/chromium/pages/welcome.js +2 -2
  15. package/dist/extension-js-devtools/chromium/scripts/logger-client.js +1 -1
  16. package/dist/extension-js-devtools/edge/content_scripts/content-0.js +2 -2
  17. package/dist/extension-js-devtools/edge/pages/centralized-logger.js +1 -1
  18. package/dist/extension-js-devtools/edge/pages/welcome.js +2 -2
  19. package/dist/extension-js-devtools/edge/scripts/logger-client.js +1 -1
  20. package/dist/extension-js-devtools/extension-js/chrome/events.ndjson +2 -0
  21. package/dist/extension-js-devtools/extension-js/chrome/ready.json +16 -0
  22. package/dist/extension-js-devtools/extension-js/chromium/events.ndjson +2 -0
  23. package/dist/extension-js-devtools/extension-js/chromium/ready.json +16 -0
  24. package/dist/extension-js-devtools/extension-js/edge/events.ndjson +2 -0
  25. package/dist/extension-js-devtools/extension-js/edge/ready.json +16 -0
  26. package/dist/extension-js-devtools/extension-js/firefox/events.ndjson +2 -0
  27. package/dist/extension-js-devtools/extension-js/firefox/ready.json +16 -0
  28. package/dist/extension-js-devtools/firefox/content_scripts/content-0.js +2 -2
  29. package/dist/extension-js-devtools/firefox/pages/centralized-logger.js +1 -1
  30. package/dist/extension-js-devtools/firefox/pages/welcome.js +2 -2
  31. package/dist/extension-js-devtools/firefox/scripts/logger-client.js +1 -1
  32. package/dist/extension-js-theme/extension-js/chrome/events.ndjson +2 -0
  33. package/dist/extension-js-theme/extension-js/chrome/ready.json +16 -0
  34. package/dist/extension-js-theme/extension-js/chromium/events.ndjson +2 -0
  35. package/dist/extension-js-theme/extension-js/chromium/ready.json +16 -0
  36. package/dist/extension-js-theme/extension-js/edge/events.ndjson +2 -0
  37. package/dist/extension-js-theme/extension-js/edge/ready.json +16 -0
  38. package/dist/extension-js-theme/extension-js/firefox/events.ndjson +4 -0
  39. package/dist/extension-js-theme/extension-js/firefox/ready.json +16 -0
  40. package/dist/feature-scripts-content-script-wrapper.js +19 -2
  41. package/dist/feature-scripts-content-script-wrapper.mjs +19 -2
  42. package/package.json +14 -5
  43. package/runtime/process-shim.cjs +49 -0
@@ -1,7 +1,7 @@
1
1
  import { createRequire as __extjsCreateRequire } from "node:module"; const require = __extjsCreateRequire(import.meta.url);
2
2
  import { __webpack_require__ } from "./0~rslib-runtime.mjs";
3
3
  import { createRequire } from "module";
4
- import core, { Compilation as core_Compilation, DefinePlugin, WebpackError as core_WebpackError, rspack, sources as core_sources } from "@rspack/core";
4
+ import core, { Compilation as core_Compilation, DefinePlugin, ProvidePlugin, WebpackError as core_WebpackError, rspack, sources as core_sources } from "@rspack/core";
5
5
  import pintor from "pintor";
6
6
  import case_sensitive_paths_webpack_plugin from "case-sensitive-paths-webpack-plugin";
7
7
  import adm_zip from "adm-zip";
@@ -11,10 +11,10 @@ import { pathToFileURL } from "url";
11
11
  import { getManifestFieldsData } from "browser-extension-manifest-fields";
12
12
  import content_security_policy_parser from "content-security-policy-parser";
13
13
  import path_0 from "path";
14
- import fs_0 from "fs";
14
+ import fs from "fs";
15
15
  import { getCanonicalContentScriptEntryName, parseCanonicalContentScriptAsset, getCanonicalContentScriptJsAssetName, getCanonicalContentScriptCssAssetName, EXTENSIONJS_CONTENT_SCRIPT_LAYER } from "./526.mjs";
16
- import { isUsingTypeScript, jsFrameworksIntegrationsEnabled, ensureOptionalContractModuleLoaded, resolveDevelopInstallRoot, isUsingCustomLoader, resolveOptionalDependencySync, loadOptionalContractModuleWithoutInstall, isUsingIntegration as messages_isUsingIntegration, resolveOptionalContractPackageWithoutInstall, jsFrameworksHmrSummary, parseJsonSafe, getUserTypeScriptConfigFile, jsFrameworksConfigsDetected, hasDependency, resolveDevelopDistFile, optional_deps_resolver_ensureOptionalContractPackageResolved } from "./962.mjs";
17
- import { debugExtensionsToLoad, treeWithSourceFiles, getDirs, bundlerFatalError, bundlerRecompiling, asAbsolute, browserRunnerDisabled, packagingDistributionFiles, PlaywrightPlugin, debugContextPath, noEntrypointsDetected, packagingSourceFiles, debugBrowser, spacerLine, debugOutputPath, messages_ready, treeWithSourceAndDistFiles, treeWithDistFilesbrowser, getSpecialFoldersDataForCompiler, computeExtensionsToLoad, noCompanionExtensionsResolved } from "./946.mjs";
16
+ import { isUsingTypeScript, jsFrameworksIntegrationsEnabled, ensureTypeScriptConfig, ensureOptionalContractModuleLoaded, resolveDevelopInstallRoot, isUsingCustomLoader, resolveOptionalDependencySync, loadOptionalContractModuleWithoutInstall, isUsingIntegration as messages_isUsingIntegration, resolveOptionalContractPackageWithoutInstall, jsFrameworksHmrSummary, parseJsonSafe, getUserTypeScriptConfigFile, jsFrameworksConfigsDetected, hasDependency, resolveDevelopDistFile, optional_deps_resolver_ensureOptionalContractPackageResolved } from "./962.mjs";
17
+ import { debugExtensionsToLoad, treeWithSourceFiles, getDirs, bundlerFatalError, bundlerRecompiling, asAbsolute, browserRunnerDisabled, packagingDistributionFiles, PlaywrightPlugin, resolveCompanionExtensionDirs, debugContextPath, noEntrypointsDetected, packagingSourceFiles, debugBrowser, spacerLine, debugOutputPath, messages_ready, manifestInvalidJson, treeWithSourceAndDistFiles, treeWithDistFilesbrowser, getSpecialFoldersDataForCompiler, computeExtensionsToLoad, noCompanionExtensionsResolved } from "./946.mjs";
18
18
  import { scrubBrand, makeSanitizedConsole } from "./0~branding.mjs";
19
19
  import { findNearestPackageJsonSync, backgroundIsRequiredMessageOnly } from "./314.mjs";
20
20
  import { fileURLToPath as __rspack_fileURLToPath } from "node:url";
@@ -37,7 +37,7 @@ function filterKeysForThisBrowser(manifest, browser) {
37
37
  const GECKO_BASED_BROWSERS = [
38
38
  'firefox'
39
39
  ];
40
- const isChromiumTarget = CHROMIUM_BASED_BROWSERS.includes(browser) || String(browser).includes('chromium');
40
+ const isChromiumTarget = CHROMIUM_BASED_BROWSERS.includes(browser) || String(browser).includes('chromium') || 'safari' === browser || 'webkit-based' === browser || String(browser).includes('webkit');
41
41
  const isGeckoTarget = GECKO_BASED_BROWSERS.includes(browser) || String(browser).includes('gecko');
42
42
  const chromiumPrefixes = new Set([
43
43
  'chromium',
@@ -135,68 +135,6 @@ function isSubPath(resourcePath, directoryPath) {
135
135
  const dir = normalizePath(directoryPath).replace(/\/+$/, '');
136
136
  return resource === dir || resource.startsWith(`${dir}/`);
137
137
  }
138
- function isDir(p) {
139
- try {
140
- return __rspack_external_fs.existsSync(p) && __rspack_external_fs.statSync(p).isDirectory();
141
- } catch {
142
- return false;
143
- }
144
- }
145
- function isFile(p) {
146
- try {
147
- return __rspack_external_fs.existsSync(p) && __rspack_external_fs.statSync(p).isFile();
148
- } catch {
149
- return false;
150
- }
151
- }
152
- function toAbs(projectRoot, p) {
153
- return __rspack_external_path.isAbsolute(p) ? p : __rspack_external_path.resolve(projectRoot, p);
154
- }
155
- function isValidExtensionRoot(dir) {
156
- if (!isDir(dir)) return false;
157
- return isFile(__rspack_external_path.join(dir, 'manifest.json'));
158
- }
159
- function resolveCompanionExtensionDirs(opts) {
160
- const { projectRoot, config } = opts;
161
- const explicitPaths = [];
162
- let scanDir;
163
- if (Array.isArray(config)) explicitPaths.push(...config.filter((p)=>'string' == typeof p));
164
- else if (config && 'object' == typeof config) {
165
- if (Array.isArray(config.paths)) explicitPaths.push(...config.paths.filter((p)=>'string' == typeof p));
166
- if ('string' == typeof config.dir && config.dir.trim().length > 0) scanDir = config.dir.trim();
167
- }
168
- const found = [];
169
- for (const p of explicitPaths){
170
- const abs = toAbs(projectRoot, p);
171
- if (isValidExtensionRoot(abs)) found.push(abs);
172
- }
173
- if (scanDir) {
174
- const absScan = toAbs(projectRoot, scanDir);
175
- if (isDir(absScan)) {
176
- let entries = [];
177
- try {
178
- entries = __rspack_external_fs.readdirSync(absScan, {
179
- withFileTypes: true
180
- });
181
- } catch {
182
- entries = [];
183
- }
184
- for (const ent of entries){
185
- if (!ent.isDirectory()) continue;
186
- if (ent.name.startsWith('.')) continue;
187
- const candidate = __rspack_external_path.join(absScan, ent.name);
188
- if (isValidExtensionRoot(candidate)) found.push(candidate);
189
- }
190
- }
191
- }
192
- const unique = [];
193
- const seen = new Set();
194
- for (const p of found)if (!seen.has(p)) {
195
- seen.add(p);
196
- unique.push(p);
197
- }
198
- return unique;
199
- }
200
138
  function serverRestartRequiredFromSpecialFolderMessageOnly(addingOrRemoving, folder, typeOfAsset) {
201
139
  return `${pintor.red('ERROR')} in ${pintor.yellow('manifest.json')} entrypoint: ${addingOrRemoving} ${pintor.yellow(typeOfAsset)} in ${pintor.underline(folder + '/')} requires a dev server restart to apply changes.`;
202
140
  }
@@ -337,8 +275,7 @@ function checkManifestInPublic(compilation, publicDir) {
337
275
  try {
338
276
  const manifestInPublic = __rspack_external_path.join(publicDir, 'manifest.json');
339
277
  if (__rspack_external_fs.existsSync(manifestInPublic)) {
340
- const ErrCtor = compilation.compiler.webpack?.WebpackError;
341
- const err = new ErrCtor(`manifest.json must not be placed under public/: ${manifestInPublic}`);
278
+ const err = new core_WebpackError(`manifest.json must not be placed under public/: ${manifestInPublic}`);
342
279
  err.file = 'manifest.json';
343
280
  compilation.errors.push(err);
344
281
  }
@@ -363,6 +300,9 @@ class SpecialFoldersPlugin {
363
300
  checkManifestInPublic(compilation, publicDir);
364
301
  });
365
302
  });
303
+ const copyIgnore = [
304
+ 'manifest.json'
305
+ ];
366
306
  new rspack.CopyRspackPlugin({
367
307
  patterns: [
368
308
  {
@@ -370,14 +310,12 @@ class SpecialFoldersPlugin {
370
310
  to: '.',
371
311
  noErrorOnMissing: true,
372
312
  globOptions: {
373
- ignore: [
374
- 'manifest.json'
375
- ]
313
+ ignore: copyIgnore
376
314
  }
377
315
  }
378
316
  ]
379
317
  }).apply(compiler);
380
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(specialFoldersSetupSummary(true, true, 1));
318
+ if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(specialFoldersSetupSummary(true, true, copyIgnore.length));
381
319
  }
382
320
  if ('development' === compiler.options.mode) {
383
321
  if (compiler.options.watchOptions) new WarnUponFolderChanges().apply(compiler);
@@ -1038,6 +976,10 @@ function getManifestContent(compilation, manifestPath) {
1038
976
  const text = __rspack_external_fs.readFileSync(manifestPath, 'utf8');
1039
977
  return parseJsonSafe(text);
1040
978
  } catch {
979
+ try {
980
+ const resolved = cjsRequire.resolve(manifestPath);
981
+ delete cjsRequire.cache[resolved];
982
+ } catch {}
1041
983
  return cjsRequire(manifestPath);
1042
984
  }
1043
985
  }
@@ -1060,13 +1002,27 @@ function manifest_filterKeysForThisBrowser(manifest, browser) {
1060
1002
  'gecko',
1061
1003
  'firefox'
1062
1004
  ]);
1063
- const patchedManifest = JSON.parse(JSON.stringify(manifest), function(key, value) {
1064
- const indexOfColon = key.indexOf(':');
1065
- if (-1 === indexOfColon) return value;
1066
- const prefix = key.substring(0, indexOfColon);
1067
- if (prefix === browser || isChromiumTarget && chromiumPrefixes.has(prefix) || isGeckoTarget && geckoPrefixes.has(prefix)) this[key.substring(indexOfColon + 1)] = value;
1068
- });
1069
- return patchedManifest;
1005
+ const prefixMatchesTarget = (prefix)=>prefix === browser || isChromiumTarget && chromiumPrefixes.has(prefix) || isGeckoTarget && geckoPrefixes.has(prefix);
1006
+ const resolve = (node)=>{
1007
+ if (Array.isArray(node)) return node.map((item)=>resolve(item));
1008
+ if (node && 'object' == typeof node) {
1009
+ const result = {};
1010
+ const prefixedMatches = {};
1011
+ for (const [key, value] of Object.entries(node)){
1012
+ const indexOfColon = key.indexOf(':');
1013
+ if (-1 === indexOfColon) {
1014
+ result[key] = resolve(value);
1015
+ continue;
1016
+ }
1017
+ const prefix = key.substring(0, indexOfColon);
1018
+ if (prefixMatchesTarget(prefix)) prefixedMatches[key.substring(indexOfColon + 1)] = resolve(value);
1019
+ }
1020
+ for (const [strippedKey, value] of Object.entries(prefixedMatches))result[strippedKey] = value;
1021
+ return result;
1022
+ }
1023
+ return node;
1024
+ };
1025
+ return resolve(manifest);
1070
1026
  }
1071
1027
  function buildCanonicalManifest(manifestPath, manifest, browser) {
1072
1028
  const filteredManifest = manifest_filterKeysForThisBrowser(manifest, browser);
@@ -1075,6 +1031,15 @@ function buildCanonicalManifest(manifestPath, manifest, browser) {
1075
1031
  ...JSON.parse(getManifestOverrides(manifestPath, filteredManifest))
1076
1032
  };
1077
1033
  }
1034
+ var env_dirname = __rspack_dirname(__rspack_fileURLToPath(import.meta.url));
1035
+ function resolveProcessShim() {
1036
+ const candidate = __rspack_external_path.join(env_dirname, '..', 'runtime', 'process-shim.cjs');
1037
+ try {
1038
+ return __rspack_external_fs.existsSync(candidate) ? candidate : void 0;
1039
+ } catch {
1040
+ return;
1041
+ }
1042
+ }
1078
1043
  function findNearestWorkspaceRoot(startDir) {
1079
1044
  let current = __rspack_external_path.isAbsolute(startDir) ? __rspack_external_path.normalize(startDir) : __rspack_external_path.resolve(startDir);
1080
1045
  while(true){
@@ -1120,8 +1085,7 @@ class EnvPlugin {
1120
1085
  `.env.${this.browser}`,
1121
1086
  `.env.${mode}`,
1122
1087
  '.env.local',
1123
- '.env',
1124
- '.env.example'
1088
+ '.env'
1125
1089
  ];
1126
1090
  const { envPath, defaultsPath } = resolveEnvPaths(projectPath, envFiles);
1127
1091
  if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(envSelectedFile(envPath));
@@ -1143,8 +1107,6 @@ class EnvPlugin {
1143
1107
  obj[`import.meta.env.${key}`] = JSON.stringify(combinedVars[key]);
1144
1108
  return obj;
1145
1109
  }, {});
1146
- filteredEnvVars['process.env'] = JSON.stringify({});
1147
- filteredEnvVars['process'] = '({env: {}})';
1148
1110
  filteredEnvVars['process.env.EXTENSION_PUBLIC_BROWSER'] = JSON.stringify(this.browser);
1149
1111
  filteredEnvVars['import.meta.env.EXTENSION_PUBLIC_BROWSER'] = JSON.stringify(this.browser);
1150
1112
  filteredEnvVars['process.env.EXTENSION_PUBLIC_MODE'] = JSON.stringify(mode);
@@ -1159,7 +1121,15 @@ class EnvPlugin {
1159
1121
  filteredEnvVars['import.meta.env.MODE'] = JSON.stringify(mode);
1160
1122
  const injectedCount = Object.keys(filteredEnvVars).filter((k)=>k.startsWith('process.env.EXTENSION_PUBLIC_')).length;
1161
1123
  if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(envInjectedPublicVars(injectedCount));
1124
+ const processShim = resolveProcessShim();
1125
+ if (!processShim) {
1126
+ filteredEnvVars['process.env'] = '{}';
1127
+ filteredEnvVars['process'] = '({env:{},argv:[],platform:"browser",browser:true,versions:{},nextTick:function(cb){Promise.resolve().then(function(){cb()})}})';
1128
+ }
1162
1129
  new DefinePlugin(filteredEnvVars).apply(compiler);
1130
+ if (processShim) new ProvidePlugin({
1131
+ process: processShim
1132
+ }).apply(compiler);
1163
1133
  compiler.hooks.thisCompilation.tap('manifest:update-manifest', (compilation)=>{
1164
1134
  compilation.hooks.processAssets.tap({
1165
1135
  name: 'env:module',
@@ -1201,7 +1171,6 @@ class EnvPlugin {
1201
1171
  });
1202
1172
  }
1203
1173
  }
1204
- const rmdirSync = __rspack_external_fs.rmdirSync;
1205
1174
  class CleanDistFolderPlugin {
1206
1175
  options;
1207
1176
  constructor(options){
@@ -1214,25 +1183,21 @@ class CleanDistFolderPlugin {
1214
1183
  const removedCount = countFilesRecursively(distPath);
1215
1184
  if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(cleanDistStarting(distPath));
1216
1185
  try {
1217
- if (__rspack_external_fs.rmSync) __rspack_external_fs.rmSync(distPath, {
1186
+ __rspack_external_fs.rmSync(distPath, {
1218
1187
  recursive: true,
1219
1188
  force: true
1220
1189
  });
1221
- else rmdirSync(distPath, {
1222
- recursive: true
1223
- });
1224
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(cleanDistRemovedSummary(removedCount, distPath));
1225
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) logger.info('[CleanDistFolderPlugin] Removed old hot-update files before compilation.');
1190
+ if ('true' === process.env.EXTENSION_AUTHOR_MODE) {
1191
+ console.log(cleanDistRemovedSummary(removedCount, distPath));
1192
+ logger.info('[CleanDistFolderPlugin] Removed old hot-update files before compilation.');
1193
+ }
1226
1194
  } catch (error) {
1227
- if ('win32' === process.platform && /EBUSY|EPERM/i.test(String(error?.code || error?.message))) setTimeout(()=>{
1195
+ if ('win32' === process.platform && /EBUSY|EPERM/i.test(String(error?.code || error?.message))) return void setTimeout(()=>{
1228
1196
  try {
1229
- if (__rspack_external_fs.rmSync) __rspack_external_fs.rmSync(distPath, {
1197
+ __rspack_external_fs.rmSync(distPath, {
1230
1198
  recursive: true,
1231
1199
  force: true
1232
1200
  });
1233
- else rmdirSync(distPath, {
1234
- recursive: true
1235
- });
1236
1201
  } catch {}
1237
1202
  }, 100);
1238
1203
  logger.error(`[CleanDistFolderPlugin] Failed to remove hot-update files: ${error.message}`);
@@ -1516,15 +1481,18 @@ class CompilationPlugin {
1516
1481
  ] : existing ? [
1517
1482
  existing
1518
1483
  ] : [];
1484
+ const SUPPRESSED_THIRD_PARTY_WARNINGS = [
1485
+ 'Critical dependency: the request of a dependency is an expression',
1486
+ 'Critical dependency: require function is used in a way in which dependencies cannot be statically extracted',
1487
+ 'Accessing import.meta directly is unsupported'
1488
+ ];
1519
1489
  ignoreWarnings.push((warning)=>{
1520
1490
  try {
1521
1491
  const message = String(warning && (warning.message || warning) || '');
1522
- const modulePath = warning && warning.module && (warning.module.resource || warning.module.userRequest) || '';
1523
- if (message.includes('Critical dependency: the request of a dependency is an expression') && /[\\\/]@ffmpeg[\\\/]ffmpeg[\\\/]dist[\\\/]esm[\\\/](classes|worker)\.js$/.test(modulePath)) return true;
1524
- if (message.includes('Critical dependency: the request of a dependency is an expression') && /[\\\/]@techstark[\\\/]opencv-js[\\\/]dist[\\\/]opencv\.js$/.test(modulePath)) return true;
1525
- if (message.includes('Critical dependency: the request of a dependency is an expression') && /[\\\/]@sqlite\.org[\\\/]sqlite-wasm[\\\/]dist[\\\/]sqlite3-worker1\.mjs$/.test(modulePath)) return true;
1526
- if (message.includes('Critical dependency: require function is used in a way in which dependencies cannot be statically extracted') && /[\\\/]@vue[\\\/]compiler-sfc[\\\/]dist[\\\/]compiler-sfc\.esm-browser\.js$/.test(modulePath)) return true;
1527
- return message.includes('Accessing import.meta directly is unsupported') && /[\\\/]@huggingface[\\\/]transformers[\\\/].*transformers\.web\.js$/.test(modulePath);
1492
+ const modulePath = String(warning && warning.module && (warning.module.resource || warning.module.userRequest) || '');
1493
+ const isThirdParty = /[\\/]node_modules[\\/]/.test(modulePath);
1494
+ if (!isThirdParty) return false;
1495
+ return SUPPRESSED_THIRD_PARTY_WARNINGS.some((needle)=>message.includes(needle));
1528
1496
  } catch {
1529
1497
  return false;
1530
1498
  }
@@ -1571,9 +1539,9 @@ function cssIntegrationsEnabled(integrations) {
1571
1539
  const list = integrations.length > 0 ? integrations.map((n)=>pintor.yellow(n)).join(', ') : pintor.gray('none');
1572
1540
  return `${pintor.gray('⏵⏵⏵')} CSS: Integrations enabled (${pintor.gray(String(integrations.length))}) ${list}`;
1573
1541
  }
1574
- function cssConfigsDetected(postcssConfig, stylelintConfig, tailwindConfig, browserslistSource) {
1542
+ function cssConfigsDetected(postcssConfig, tailwindConfig, browserslistSource) {
1575
1543
  const fmt = (v)=>v ? pintor.underline(v) : pintor.gray('none');
1576
- return `${pintor.gray('⏵⏵⏵')} CSS: Configs\n${pintor.gray('POSTCSS')} ${fmt(postcssConfig)}\n${pintor.gray('STYLELINT')} ${fmt(stylelintConfig)}\n${pintor.gray('TAILWIND')} ${fmt(tailwindConfig)}\n${pintor.gray('BROWSERSLIST')} ${fmt(browserslistSource)}`;
1544
+ return `${pintor.gray('⏵⏵⏵')} CSS: Configs\n${pintor.gray('POSTCSS')} ${fmt(postcssConfig)}\n${pintor.gray('TAILWIND')} ${fmt(tailwindConfig)}\n${pintor.gray('BROWSERSLIST')} ${fmt(browserslistSource)}`;
1577
1545
  }
1578
1546
  function isUsingIntegration(name) {
1579
1547
  return `${pintor.gray('⏵⏵⏵')} Using ${pintor.brightBlue(name)}...`;
@@ -1642,48 +1610,12 @@ function createSassLoaderOptions(projectPath, mode) {
1642
1610
  return base;
1643
1611
  }
1644
1612
  async function maybeUseSass(projectPath) {
1645
- if (!isUsingSass(projectPath)) return [];
1646
- const sassLoaderPath = await optional_deps_resolver_ensureOptionalContractPackageResolved({
1613
+ if (!isUsingSass(projectPath)) return;
1614
+ await optional_deps_resolver_ensureOptionalContractPackageResolved({
1647
1615
  contractId: 'sass',
1648
1616
  projectPath,
1649
1617
  dependencyId: 'sass-loader'
1650
1618
  });
1651
- return [
1652
- {
1653
- test: /\.(sass|scss)$/,
1654
- exclude: /\.module\.(sass|scss)$/,
1655
- use: [
1656
- {
1657
- loader: sassLoaderPath,
1658
- options: createSassLoaderOptions(projectPath, 'development')
1659
- }
1660
- ]
1661
- },
1662
- {
1663
- test: /\.module\.(sass|scss)$/,
1664
- use: [
1665
- {
1666
- loader: sassLoaderPath,
1667
- options: createSassLoaderOptions(projectPath, 'development')
1668
- }
1669
- ]
1670
- }
1671
- ];
1672
- }
1673
- function isContentScriptEntry(absolutePath, manifestPath, projectPath) {
1674
- if (!absolutePath || !manifestPath || !projectPath) return false;
1675
- if (!__rspack_external_fs.existsSync(manifestPath)) return false;
1676
- const manifest = parseJsonSafe(__rspack_external_fs.readFileSync(manifestPath, 'utf8'));
1677
- const scriptsDir = __rspack_external_path.resolve(projectPath, "scripts");
1678
- const absPathNormalized = __rspack_external_path.resolve(absolutePath);
1679
- const relToScripts = __rspack_external_path.relative(scriptsDir, absPathNormalized);
1680
- const isScriptsFolderScript = relToScripts && !relToScripts.startsWith('..') && !__rspack_external_path.isAbsolute(relToScripts);
1681
- if (isScriptsFolderScript) return true;
1682
- for (const content of manifest.content_scripts || [])if (content.js?.length) for (const js of content.js){
1683
- const contentPath = __rspack_external_path.resolve(__rspack_external_path.dirname(manifestPath), js);
1684
- if (contentPath === absPathNormalized) return true;
1685
- }
1686
- return false;
1687
1619
  }
1688
1620
  let less_userMessageDelivered = false;
1689
1621
  function isUsingLess(projectPath) {
@@ -1696,88 +1628,44 @@ function isUsingLess(projectPath) {
1696
1628
  }
1697
1629
  return false;
1698
1630
  }
1699
- async function maybeUseLess(projectPath, manifestPath) {
1700
- const resolvedManifestPath = manifestPath || __rspack_external_path.join(projectPath, 'manifest.json');
1701
- if (!isUsingLess(projectPath)) return [];
1702
- const lessLoaderPath = await optional_deps_resolver_ensureOptionalContractPackageResolved({
1631
+ async function maybeUseLess(projectPath) {
1632
+ if (!isUsingLess(projectPath)) return;
1633
+ await optional_deps_resolver_ensureOptionalContractPackageResolved({
1703
1634
  contractId: 'less',
1704
1635
  projectPath,
1705
1636
  dependencyId: 'less-loader'
1706
1637
  });
1707
- return [
1708
- {
1709
- test: /\.less$/,
1710
- exclude: /\.module\.less$/,
1711
- use: [
1712
- {
1713
- loader: lessLoaderPath,
1714
- options: {
1715
- sourceMap: true
1716
- }
1717
- }
1718
- ]
1719
- },
1720
- {
1721
- test: /\.module\.less$/,
1722
- use: [
1723
- {
1724
- loader: lessLoaderPath,
1725
- options: {
1726
- sourceMap: true
1727
- }
1728
- }
1729
- ]
1730
- },
1731
- {
1732
- test: /\.less$/,
1733
- exclude: /\.module\.less$/,
1734
- type: 'asset/resource',
1735
- generator: {
1736
- filename: "content_scripts/[name].[contenthash:8].css"
1737
- },
1738
- issuer: (issuer)=>isContentScriptEntry(issuer, resolvedManifestPath, projectPath)
1739
- }
1740
- ];
1741
1638
  }
1742
- function getStylelintConfigFile(projectPath) {
1743
- const stylelintConfigJs = __rspack_external_path.join(projectPath, 'stylelint.config.js');
1744
- const stylelintConfigDotJs = __rspack_external_path.join(projectPath, '.stylelintrc.js');
1745
- const stylelintConfigMjs = __rspack_external_path.join(projectPath, 'stylelint.config.mjs');
1746
- const stylelintConfigDotMjs = __rspack_external_path.join(projectPath, '.stylelintrc.mjs');
1747
- const stylelintConfigCjs = __rspack_external_path.join(projectPath, 'stylelint.config.cjs');
1748
- const stylelintConfigDotCjs = __rspack_external_path.join(projectPath, '.stylelintrc.cjs');
1749
- const stylelintConfigJson = __rspack_external_path.join(projectPath, '.stylelintrc.json');
1750
- const stylelintConfigDotJson = __rspack_external_path.join(projectPath, '.stylelintrc');
1751
- const stylelintConfigYml = __rspack_external_path.join(projectPath, '.stylelintrc.yml');
1752
- const stylelintConfigDotYml = __rspack_external_path.join(projectPath, '.stylelintrc.yaml');
1753
- if (__rspack_external_fs.existsSync(stylelintConfigJs)) return stylelintConfigJs;
1754
- if (__rspack_external_fs.existsSync(stylelintConfigDotJs)) return stylelintConfigDotJs;
1755
- if (__rspack_external_fs.existsSync(stylelintConfigMjs)) return stylelintConfigMjs;
1756
- if (__rspack_external_fs.existsSync(stylelintConfigDotMjs)) return stylelintConfigDotMjs;
1757
- if (__rspack_external_fs.existsSync(stylelintConfigCjs)) return stylelintConfigCjs;
1758
- if (__rspack_external_fs.existsSync(stylelintConfigDotCjs)) return stylelintConfigDotCjs;
1759
- if (__rspack_external_fs.existsSync(stylelintConfigJson)) return stylelintConfigJson;
1760
- if (__rspack_external_fs.existsSync(stylelintConfigDotJson)) return stylelintConfigDotJson;
1761
- if (__rspack_external_fs.existsSync(stylelintConfigYml)) return stylelintConfigYml;
1762
- if (__rspack_external_fs.existsSync(stylelintConfigDotYml)) return stylelintConfigDotYml;
1763
- }
1764
- let stylelint_userMessageDelivered = false;
1765
- function stylelint_isUsingStylelint(projectPath) {
1766
- const packageJsonPath = __rspack_external_path.join(projectPath, 'package.json');
1767
- if (!__rspack_external_fs.existsSync(packageJsonPath)) return false;
1768
- const configFile = getStylelintConfigFile(projectPath);
1769
- const isUsingStylelint = !!configFile;
1770
- if (isUsingStylelint) {
1771
- if (!stylelint_userMessageDelivered) {
1772
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(`${pintor.brightMagenta('⏵⏵⏵ Author says')} ${isUsingIntegration('Stylelint')}`);
1773
- stylelint_userMessageDelivered = true;
1774
- }
1775
- }
1776
- return isUsingStylelint;
1639
+ const indexCache = new Map();
1640
+ function getContentScriptIndex(manifestPath, projectPath) {
1641
+ const cacheKey = `${manifestPath}::${projectPath}`;
1642
+ let mtimeMs = -1;
1643
+ try {
1644
+ mtimeMs = __rspack_external_fs.statSync(manifestPath).mtimeMs;
1645
+ } catch {}
1646
+ const cached = indexCache.get(cacheKey);
1647
+ if (cached && (mtimeMs < 0 || cached.mtimeMs === mtimeMs)) return cached;
1648
+ const manifest = parseJsonSafe(__rspack_external_fs.readFileSync(manifestPath, 'utf8'));
1649
+ const manifestDir = __rspack_external_path.dirname(manifestPath);
1650
+ const contentPaths = new Set();
1651
+ for (const content of manifest.content_scripts || [])if (content.js?.length) for (const js of content.js)contentPaths.add(__rspack_external_path.resolve(manifestDir, js));
1652
+ const index = {
1653
+ mtimeMs,
1654
+ scriptsDir: __rspack_external_path.resolve(projectPath, "scripts"),
1655
+ contentPaths
1656
+ };
1657
+ indexCache.set(cacheKey, index);
1658
+ return index;
1777
1659
  }
1778
- async function maybeUseStylelint(projectPath) {
1779
- stylelint_isUsingStylelint(projectPath);
1780
- return [];
1660
+ function isContentScriptEntry(absolutePath, manifestPath, projectPath) {
1661
+ if (!absolutePath || !manifestPath || !projectPath) return false;
1662
+ if (!__rspack_external_fs.existsSync(manifestPath)) return false;
1663
+ const { scriptsDir, contentPaths } = getContentScriptIndex(manifestPath, projectPath);
1664
+ const absPathNormalized = __rspack_external_path.resolve(absolutePath);
1665
+ const relToScripts = __rspack_external_path.relative(scriptsDir, absPathNormalized);
1666
+ const isScriptsFolderScript = relToScripts && !relToScripts.startsWith('..') && !__rspack_external_path.isAbsolute(relToScripts);
1667
+ if (isScriptsFolderScript) return true;
1668
+ return contentPaths.has(absPathNormalized);
1781
1669
  }
1782
1670
  let tailwind_userMessageDelivered = false;
1783
1671
  function tailwind_isUsingTailwind(projectPath) {
@@ -1791,12 +1679,16 @@ function tailwind_isUsingTailwind(projectPath) {
1791
1679
  return isUsingTailwind;
1792
1680
  }
1793
1681
  function getTailwindConfigFile(projectPath) {
1794
- const configFileMjs = __rspack_external_path.join(projectPath, 'tailwind.config.mjs');
1795
- const configFileCjs = __rspack_external_path.join(projectPath, 'tailwind.config.cjs');
1796
- const configFileJs = __rspack_external_path.join(projectPath, 'tailwind.config.js');
1797
- if (__rspack_external_fs.existsSync(configFileMjs)) return configFileMjs;
1798
- if (__rspack_external_fs.existsSync(configFileCjs)) return configFileCjs;
1799
- if (__rspack_external_fs.existsSync(configFileJs)) return configFileJs;
1682
+ const candidates = [
1683
+ 'tailwind.config.mjs',
1684
+ 'tailwind.config.cjs',
1685
+ 'tailwind.config.ts',
1686
+ 'tailwind.config.js'
1687
+ ];
1688
+ for (const candidate of candidates){
1689
+ const configPath = __rspack_external_path.join(projectPath, candidate);
1690
+ if (__rspack_external_fs.existsSync(configPath)) return configPath;
1691
+ }
1800
1692
  }
1801
1693
  let postcss_userMessageDelivered = false;
1802
1694
  const postCssConfigFiles = [
@@ -2127,9 +2019,9 @@ async function commonStyleLoaders(projectPath, opts) {
2127
2019
  function resolvePreprocessorLoader(loader, projectPath) {
2128
2020
  return resolveOptionalDependencySync(loader, projectPath);
2129
2021
  }
2130
- async function cssInContentScriptLoader(projectPath, manifestPath, mode, usage = {}) {
2022
+ async function buildCssRules(projectPath, mode, usage, opts) {
2131
2023
  const { useSass = true, useLess = true } = usage;
2132
- const isContentScript = (issuer)=>isContentScriptEntry(issuer, manifestPath, projectPath);
2024
+ const { nonModuleType, issuer } = opts;
2133
2025
  const fileTypes = [
2134
2026
  {
2135
2027
  test: /\.module\.css$/,
@@ -2139,14 +2031,14 @@ async function cssInContentScriptLoader(projectPath, manifestPath, mode, usage =
2139
2031
  {
2140
2032
  test: /\.css$/,
2141
2033
  exclude: /\.module\.css$/,
2142
- type: 'asset/inline',
2034
+ type: nonModuleType,
2143
2035
  loader: null
2144
2036
  },
2145
2037
  ...useSass ? [
2146
2038
  {
2147
2039
  test: /\.(sass|scss)$/,
2148
2040
  exclude: /\.module\.(sass|scss)$/,
2149
- type: 'asset/inline',
2041
+ type: nonModuleType,
2150
2042
  loader: 'sass-loader'
2151
2043
  },
2152
2044
  {
@@ -2159,7 +2051,7 @@ async function cssInContentScriptLoader(projectPath, manifestPath, mode, usage =
2159
2051
  {
2160
2052
  test: /\.less$/,
2161
2053
  exclude: /\.module\.less$/,
2162
- type: 'asset/inline',
2054
+ type: nonModuleType,
2163
2055
  loader: 'less-loader'
2164
2056
  },
2165
2057
  {
@@ -2169,7 +2061,7 @@ async function cssInContentScriptLoader(projectPath, manifestPath, mode, usage =
2169
2061
  }
2170
2062
  ] : []
2171
2063
  ];
2172
- const rules = await Promise.all(fileTypes.map(async ({ test, exclude, type, loader })=>{
2064
+ return Promise.all(fileTypes.map(async ({ test, exclude, type, loader })=>{
2173
2065
  const use = loader ? await commonStyleLoaders(projectPath, {
2174
2066
  mode: mode,
2175
2067
  loader: resolvePreprocessorLoader(loader, projectPath),
@@ -2183,76 +2075,22 @@ async function cssInContentScriptLoader(projectPath, manifestPath, mode, usage =
2183
2075
  test,
2184
2076
  exclude,
2185
2077
  type,
2186
- issuer: isContentScript,
2078
+ issuer,
2187
2079
  use
2188
2080
  };
2189
2081
  }));
2190
- return rules;
2191
2082
  }
2192
- function css_in_html_loader_resolvePreprocessorLoader(loader, projectPath) {
2193
- return resolveOptionalDependencySync(loader, projectPath);
2083
+ async function cssInContentScriptLoader(projectPath, manifestPath, mode, usage = {}) {
2084
+ return buildCssRules(projectPath, mode, usage, {
2085
+ nonModuleType: 'asset/inline',
2086
+ issuer: (issuer)=>isContentScriptEntry(issuer, manifestPath, projectPath)
2087
+ });
2194
2088
  }
2195
2089
  async function cssInHtmlLoader(projectPath, mode, manifestPath, usage = {}) {
2196
- const { useSass = true, useLess = true } = usage;
2197
- const isNotContentScript = (issuer)=>!isContentScriptEntry(issuer, manifestPath, projectPath);
2198
- const fileTypes = [
2199
- {
2200
- test: /\.module\.css$/,
2201
- type: 'css/module',
2202
- loader: null
2203
- },
2204
- {
2205
- test: /\.css$/,
2206
- exclude: /\.module\.css$/,
2207
- type: 'css',
2208
- loader: null
2209
- },
2210
- ...useSass ? [
2211
- {
2212
- test: /\.(sass|scss)$/,
2213
- exclude: /\.module\.(sass|scss)$/,
2214
- type: 'css',
2215
- loader: 'sass-loader'
2216
- },
2217
- {
2218
- test: /\.module\.(sass|scss)$/,
2219
- type: 'css/module',
2220
- loader: 'sass-loader'
2221
- }
2222
- ] : [],
2223
- ...useLess ? [
2224
- {
2225
- test: /\.less$/,
2226
- exclude: /\.module\.less$/,
2227
- type: 'css',
2228
- loader: 'less-loader'
2229
- },
2230
- {
2231
- test: /\.module\.less$/,
2232
- type: 'css/module',
2233
- loader: 'less-loader'
2234
- }
2235
- ] : []
2236
- ];
2237
- const rules = await Promise.all(fileTypes.map(async ({ test, exclude, type, loader })=>{
2238
- const use = loader ? await commonStyleLoaders(projectPath, {
2239
- mode: mode,
2240
- loader: css_in_html_loader_resolvePreprocessorLoader(loader, projectPath),
2241
- loaderOptions: 'sass-loader' === loader ? createSassLoaderOptions(projectPath, mode) : {
2242
- sourceMap: true
2243
- }
2244
- }) : await commonStyleLoaders(projectPath, {
2245
- mode: mode
2246
- });
2247
- return {
2248
- test,
2249
- exclude,
2250
- type,
2251
- issuer: isNotContentScript,
2252
- use
2253
- };
2254
- }));
2255
- return rules;
2090
+ return buildCssRules(projectPath, mode, usage, {
2091
+ nonModuleType: 'css',
2092
+ issuer: (issuer)=>!isContentScriptEntry(issuer, manifestPath, projectPath)
2093
+ });
2256
2094
  }
2257
2095
  function injectCssLink(headNode, feature, firstLinkAttrs, hrefOverride) {
2258
2096
  const linkTag = __rspack_external_parse5_utilities_78b19c6a.createNode('link');
@@ -2291,14 +2129,11 @@ class CssPlugin {
2291
2129
  async configureOptions(compiler) {
2292
2130
  const mode = compiler.options.mode || 'development';
2293
2131
  const projectPath = compiler.options.context || process.cwd();
2294
- const plugins = [];
2295
2132
  const manifestPath = this.manifestPath;
2296
2133
  const usingSass = hasDependency(projectPath, 'sass');
2297
2134
  const usingLess = hasDependency(projectPath, 'less');
2298
- const maybeInstallStylelint = await maybeUseStylelint(projectPath);
2299
- plugins.push(...maybeInstallStylelint);
2300
2135
  await maybeUseSass(projectPath);
2301
- await maybeUseLess(projectPath, manifestPath);
2136
+ await maybeUseLess(projectPath);
2302
2137
  const loaders = [
2303
2138
  ...await cssInContentScriptLoader(projectPath, manifestPath, mode, {
2304
2139
  useSass: usingSass,
@@ -2311,10 +2146,6 @@ class CssPlugin {
2311
2146
  ];
2312
2147
  compiler.options.output.cssFilename = '[name].css';
2313
2148
  compiler.options.output.cssChunkFilename = '[name].css';
2314
- compiler.options.plugins = [
2315
- ...compiler.options.plugins,
2316
- ...plugins
2317
- ].filter(Boolean);
2318
2149
  compiler.options.module.rules = [
2319
2150
  ...compiler.options.module.rules,
2320
2151
  ...loaders
@@ -2322,39 +2153,24 @@ class CssPlugin {
2322
2153
  if ('true' === process.env.EXTENSION_AUTHOR_MODE) {
2323
2154
  const integrations = [];
2324
2155
  const usingTailwind = hasDependency(projectPath, 'tailwindcss');
2325
- const usingPostcss = hasDependency(projectPath, 'postcss') || void 0 !== plugin_css_findPostCssConfig(projectPath) || usingSass || usingLess || usingTailwind;
2156
+ const usingPostcss = hasDependency(projectPath, 'postcss') || void 0 !== findPostCssConfig(projectPath) || usingSass || usingLess || usingTailwind;
2326
2157
  if (usingPostcss) integrations.push('PostCSS');
2327
2158
  if (usingSass) integrations.push('Sass');
2328
2159
  if (usingLess) integrations.push('Less');
2329
2160
  if (usingTailwind) integrations.push('Tailwind');
2330
2161
  console.log(cssIntegrationsEnabled(integrations));
2331
- const postcssConfig = plugin_css_findPostCssConfig(projectPath);
2332
- const stylelintConfig = getStylelintConfigFile(projectPath);
2162
+ const postcssConfig = findPostCssConfig(projectPath);
2333
2163
  const tailwindConfig = getTailwindConfigFile(projectPath);
2334
2164
  const browserslistSource = findBrowserslistSource(projectPath);
2335
- console.log(cssConfigsDetected(postcssConfig, stylelintConfig, tailwindConfig, browserslistSource));
2165
+ console.log(cssConfigsDetected(postcssConfig, tailwindConfig, browserslistSource));
2336
2166
  }
2337
2167
  }
2338
2168
  async apply(compiler) {
2339
2169
  const mode = compiler.options.mode || 'development';
2340
- if ('production' === mode) return void compiler.hooks.beforeRun.tapPromise(CssPlugin.name, async ()=>await this.configureOptions(compiler));
2341
- await this.configureOptions(compiler);
2342
- }
2343
- }
2344
- const plugin_css_postCssConfigFiles = [
2345
- '.postcssrc',
2346
- '.postcssrc.json',
2347
- '.postcssrc.yaml',
2348
- '.postcssrc.yml',
2349
- '.postcssrc.js',
2350
- '.postcssrc.cjs',
2351
- 'postcss.config.js',
2352
- 'postcss.config.cjs'
2353
- ];
2354
- function plugin_css_findPostCssConfig(projectPath) {
2355
- for (const configFile of plugin_css_postCssConfigFiles){
2356
- const configPath = __rspack_external_path.join(projectPath, configFile);
2357
- if (__rspack_external_fs.existsSync(configPath)) return configPath;
2170
+ if ('production' === mode) return void compiler.hooks.beforeRun.tapPromise(CssPlugin.name, ()=>this.configureOptions(compiler));
2171
+ const configuring = this.configureOptions(compiler);
2172
+ compiler.hooks.watchRun.tapPromise(CssPlugin.name, ()=>configuring);
2173
+ await configuring;
2358
2174
  }
2359
2175
  }
2360
2176
  function findBrowserslistSource(projectPath) {
@@ -2395,7 +2211,7 @@ class StaticAssetsPlugin {
2395
2211
  constructor(options){
2396
2212
  this.mode = options.mode;
2397
2213
  }
2398
- async apply(compiler) {
2214
+ apply(compiler) {
2399
2215
  compiler.options.module = compiler.options.module || {
2400
2216
  rules: []
2401
2217
  };
@@ -2743,16 +2559,6 @@ function svelte_resolveFromProject(id, projectPath) {
2743
2559
  const req = createRequire(__rspack_external_path.join(base, 'package.json'));
2744
2560
  return req.resolve(id);
2745
2561
  } catch {}
2746
- try {
2747
- return require.resolve(id, {
2748
- paths: [
2749
- projectPath,
2750
- process.cwd()
2751
- ]
2752
- });
2753
- } catch {
2754
- return;
2755
- }
2756
2562
  }
2757
2563
  function isUsingSvelte(projectPath) {
2758
2564
  const using = hasDependency(projectPath, 'svelte');
@@ -2936,6 +2742,7 @@ class JsFrameworksPlugin {
2936
2742
  const mode = compiler.options.mode || 'development';
2937
2743
  const projectPath = compiler.options.context;
2938
2744
  const manifestDir = __rspack_external_path.dirname(this.manifestPath);
2745
+ ensureTypeScriptConfig(projectPath);
2939
2746
  const swcIncludeDirs = Array.from(new Set([
2940
2747
  projectPath,
2941
2748
  manifestDir,
@@ -3159,8 +2966,10 @@ class JsFrameworksPlugin {
3159
2966
  }
3160
2967
  async apply(compiler) {
3161
2968
  const mode = compiler.options.mode || 'development';
3162
- if ('production' === mode) return void compiler.hooks.beforeRun.tapPromise(JsFrameworksPlugin.name, async ()=>await this.configureOptions(compiler));
3163
- await this.configureOptions(compiler);
2969
+ if ('production' === mode) return void compiler.hooks.beforeRun.tapPromise(JsFrameworksPlugin.name, ()=>this.configureOptions(compiler));
2970
+ const configuring = this.configureOptions(compiler);
2971
+ compiler.hooks.watchRun.tapPromise(JsFrameworksPlugin.name, ()=>configuring);
2972
+ await configuring;
3164
2973
  }
3165
2974
  }
3166
2975
  function serverRestartRequiredFromManifestError(fileAdded, fileRemoved) {
@@ -3598,6 +3407,33 @@ function isCoveredByExistingGlobs(existingPatterns, candidate) {
3598
3407
  } catch {}
3599
3408
  return false;
3600
3409
  }
3410
+ function mergeIntoV3Group(groups, normalizedMatches, resources, options) {
3411
+ if (0 === resources.length) return;
3412
+ const createGroupWhenMissing = options?.createGroupWhenMissing ?? true;
3413
+ const target = [
3414
+ ...normalizedMatches
3415
+ ].sort();
3416
+ const existing = groups.find((group)=>{
3417
+ const current = [
3418
+ ...group.matches
3419
+ ].sort();
3420
+ return current.length === target.length && current.every((value, index)=>value === target[index]);
3421
+ });
3422
+ if (existing) {
3423
+ const candidates = resources.filter((resource)=>!existing.resources.includes(resource) && !isCoveredByExistingGlobs(existing.resources, resource));
3424
+ existing.resources = Array.from(new Set([
3425
+ ...existing.resources,
3426
+ ...candidates
3427
+ ])).sort();
3428
+ return;
3429
+ }
3430
+ if (createGroupWhenMissing) groups.push({
3431
+ resources: Array.from(new Set(resources)).sort(),
3432
+ matches: [
3433
+ ...normalizedMatches
3434
+ ].sort()
3435
+ });
3436
+ }
3601
3437
  function isCanonicalContentScriptCss(resource) {
3602
3438
  return /^content_scripts\/content-\d+\.css$/.test(resource);
3603
3439
  }
@@ -3624,28 +3460,7 @@ function generateManifestPatches(compilation, manifestPath, entryImports, browse
3624
3460
  const re = /assets\/[A-Za-z0-9._-]+/g;
3625
3461
  const found = source.match(re) || [];
3626
3462
  const filtered = Array.from(new Set(found.filter((r)=>!r.endsWith('.js') && !r.endsWith('.map')))).sort();
3627
- if (0 === filtered.length) continue;
3628
- const existingResource = webAccessibleResourcesV3.find((entry)=>{
3629
- const a = [
3630
- ...entry.matches
3631
- ].sort();
3632
- const b = [
3633
- ...normalizedMatches
3634
- ].sort();
3635
- return a.length === b.length && a.every((v, i)=>v === b[i]);
3636
- });
3637
- if (existingResource) {
3638
- const candidates = filtered.filter((resource)=>!existingResource.resources.includes(resource) && !isCoveredByExistingGlobs(existingResource.resources, resource));
3639
- existingResource.resources = Array.from(new Set([
3640
- ...existingResource.resources || [],
3641
- ...candidates
3642
- ])).sort();
3643
- } else webAccessibleResourcesV3.push({
3644
- resources: filtered,
3645
- matches: [
3646
- ...normalizedMatches
3647
- ].sort()
3648
- });
3463
+ if (0 !== filtered.length) mergeIntoV3Group(webAccessibleResourcesV3, normalizedMatches, filtered);
3649
3464
  }
3650
3465
  }
3651
3466
  for (const [entryName, resources] of Object.entries(entryImports)){
@@ -3661,31 +3476,7 @@ function generateManifestPatches(compilation, manifestPath, entryImports, browse
3661
3476
  if (0 === filteredResources.length) continue;
3662
3477
  if (3 === canonicalManifest.manifest_version) {
3663
3478
  const normalizedMatches = cleanMatches(matches);
3664
- const existingResource = webAccessibleResourcesV3.find((resourceEntry)=>{
3665
- const a = [
3666
- ...resourceEntry.matches
3667
- ].sort();
3668
- const b = [
3669
- ...normalizedMatches
3670
- ].sort();
3671
- return a.length === b.length && a.every((v, i)=>v === b[i]);
3672
- });
3673
- if (existingResource) {
3674
- const candidates = filteredResources.filter((resource)=>!existingResource.resources.includes(resource) && !isCoveredByExistingGlobs(existingResource.resources, resource));
3675
- const merged = Array.from(new Set([
3676
- ...existingResource.resources,
3677
- ...candidates
3678
- ])).sort();
3679
- existingResource.resources = merged;
3680
- existingResource.matches = [
3681
- ...existingResource.matches
3682
- ].sort();
3683
- } else webAccessibleResourcesV3.push({
3684
- resources: Array.from(new Set(filteredResources)).sort(),
3685
- matches: [
3686
- ...normalizedMatches
3687
- ].sort()
3688
- });
3479
+ mergeIntoV3Group(webAccessibleResourcesV3, normalizedMatches, filteredResources);
3689
3480
  } else filteredResources.forEach((resource)=>{
3690
3481
  if (!webAccessibleResourcesV2.includes(resource)) webAccessibleResourcesV2.push(resource);
3691
3482
  });
@@ -3697,26 +3488,8 @@ function generateManifestPatches(compilation, manifestPath, entryImports, browse
3697
3488
  if (staticAssets.length > 0) {
3698
3489
  const allMatches = Array.from(new Set((canonicalManifest.content_scripts || []).flatMap((cs)=>cs.matches || [])));
3699
3490
  const normalizedMatches = cleanMatches(allMatches);
3700
- const existing = webAccessibleResourcesV3.find((entry)=>{
3701
- const a = [
3702
- ...entry.matches
3703
- ].sort();
3704
- const b = [
3705
- ...normalizedMatches
3706
- ].sort();
3707
- return a.length === b.length && a.every((v, i)=>v === b[i]);
3708
- });
3709
- if (existing) {
3710
- const candidates = staticAssets.filter((r)=>!existing.resources.includes(r) && !isCoveredByExistingGlobs(existing.resources, r));
3711
- existing.resources = Array.from(new Set([
3712
- ...existing.resources || [],
3713
- ...candidates
3714
- ])).sort();
3715
- } else if (normalizedMatches.length > 0) webAccessibleResourcesV3.push({
3716
- resources: staticAssets,
3717
- matches: [
3718
- ...normalizedMatches
3719
- ].sort()
3491
+ mergeIntoV3Group(webAccessibleResourcesV3, normalizedMatches, staticAssets, {
3492
+ createGroupWhenMissing: normalizedMatches.length > 0
3720
3493
  });
3721
3494
  }
3722
3495
  }
@@ -3727,29 +3500,7 @@ function generateManifestPatches(compilation, manifestPath, entryImports, browse
3727
3500
  if (fontAssets.length > 0) {
3728
3501
  const allMatches = Array.from(new Set((canonicalManifest.content_scripts || []).flatMap((cs)=>cs.matches || [])));
3729
3502
  const normalizedMatches = cleanMatches(allMatches);
3730
- if (normalizedMatches.length > 0) {
3731
- const existing = webAccessibleResourcesV3.find((entry)=>{
3732
- const a = [
3733
- ...entry.matches
3734
- ].sort();
3735
- const b = [
3736
- ...normalizedMatches
3737
- ].sort();
3738
- return a.length === b.length && a.every((v, i)=>v === b[i]);
3739
- });
3740
- if (existing) {
3741
- const candidates = fontAssets.filter((r)=>!existing.resources.includes(r) && !isCoveredByExistingGlobs(existing.resources, r));
3742
- existing.resources = Array.from(new Set([
3743
- ...existing.resources || [],
3744
- ...candidates
3745
- ])).sort();
3746
- } else webAccessibleResourcesV3.push({
3747
- resources: fontAssets,
3748
- matches: [
3749
- ...normalizedMatches
3750
- ].sort()
3751
- });
3752
- }
3503
+ if (normalizedMatches.length > 0) mergeIntoV3Group(webAccessibleResourcesV3, normalizedMatches, fontAssets);
3753
3504
  }
3754
3505
  } else if (2 === canonicalManifest.manifest_version) {
3755
3506
  const assetKeys = Object.keys(compilation.assets || {});
@@ -3784,29 +3535,7 @@ function generateManifestPatches(compilation, manifestPath, entryImports, browse
3784
3535
  if (cssUnderContentScripts.length > 0) {
3785
3536
  const allMatches = Array.from(new Set((canonicalManifest.content_scripts || []).flatMap((cs)=>cs.matches || [])));
3786
3537
  const normalizedMatches = cleanMatches(allMatches);
3787
- if (normalizedMatches.length > 0) {
3788
- const existing = webAccessibleResourcesV3.find((entry)=>{
3789
- const a = [
3790
- ...entry.matches
3791
- ].sort();
3792
- const b = [
3793
- ...normalizedMatches
3794
- ].sort();
3795
- return a.length === b.length && a.every((v, i)=>v === b[i]);
3796
- });
3797
- if (existing) {
3798
- const candidates = cssUnderContentScripts.filter((r)=>!existing.resources.includes(r) && !isCoveredByExistingGlobs(existing.resources, r));
3799
- existing.resources = Array.from(new Set([
3800
- ...existing.resources || [],
3801
- ...candidates
3802
- ])).sort();
3803
- } else webAccessibleResourcesV3.push({
3804
- resources: cssUnderContentScripts,
3805
- matches: [
3806
- ...normalizedMatches
3807
- ].sort()
3808
- });
3809
- }
3538
+ if (normalizedMatches.length > 0) mergeIntoV3Group(webAccessibleResourcesV3, normalizedMatches, cssUnderContentScripts);
3810
3539
  }
3811
3540
  } else if (2 === canonicalManifest.manifest_version) {
3812
3541
  for (const resource of cssUnderContentScripts)if (!webAccessibleResourcesV2.includes(resource)) webAccessibleResourcesV2.push(resource);
@@ -4138,8 +3867,14 @@ function writeFileAtomically(targetPath, content) {
4138
3867
  __rspack_external_fs.mkdirSync(directory, {
4139
3868
  recursive: true
4140
3869
  });
4141
- __rspack_external_fs.writeFileSync(tempPath, content, 'utf-8');
4142
- __rspack_external_fs.renameSync(tempPath, targetPath);
3870
+ try {
3871
+ __rspack_external_fs.writeFileSync(tempPath, content, 'utf-8');
3872
+ __rspack_external_fs.renameSync(tempPath, targetPath);
3873
+ } finally{
3874
+ try {
3875
+ if (__rspack_external_fs.existsSync(tempPath)) __rspack_external_fs.unlinkSync(tempPath);
3876
+ } catch {}
3877
+ }
4143
3878
  }
4144
3879
  class PersistManifestToDisk {
4145
3880
  apply(compiler) {
@@ -4211,10 +3946,7 @@ class AddDependencies {
4211
3946
  const deps = compilation.fileDependencies;
4212
3947
  if (this.dependencyList) this.dependencyList.forEach((dependency)=>{
4213
3948
  const alreadyPresent = 'function' == typeof deps?.has ? deps.has(dependency) : false;
4214
- if (!alreadyPresent) {
4215
- if ('function' == typeof deps?.add) deps.add(dependency);
4216
- if (deps !== compilation.fileDependencies && 'function' == typeof compilation.fileDependencies?.add) compilation.fileDependencies.add(dependency);
4217
- }
3949
+ if (!alreadyPresent && 'function' == typeof deps?.add) deps.add(dependency);
4218
3950
  });
4219
3951
  if ('true' === process.env.EXTENSION_AUTHOR_MODE) {
4220
3952
  const added = Array.isArray(this.dependencyList) ? this.dependencyList.length : 0;
@@ -4393,6 +4125,17 @@ function parseHtml(node, onResourceFound) {
4393
4125
  } else if ('link' === node.nodeName) {
4394
4126
  const href = node.attrs?.find((attr)=>'href' === attr.name)?.value;
4395
4127
  const rel = node.attrs?.find((attr)=>'rel' === attr.name)?.value;
4128
+ const imagesrcset = node.attrs?.find((attr)=>'imagesrcset' === attr.name)?.value;
4129
+ if (imagesrcset) for (const candidate of imagesrcset.split(',')){
4130
+ const url = candidate.trim().split(/\s+/)[0];
4131
+ if (!url) continue;
4132
+ const { cleanPath } = cleanAssetUrl(url);
4133
+ if (cleanPath && !parse_html_isUrl(cleanPath)) onResourceFound({
4134
+ filePath: cleanPath,
4135
+ childNode: node,
4136
+ assetType: 'staticHref'
4137
+ });
4138
+ }
4396
4139
  if (!href) return;
4397
4140
  if (parse_html_isUrl(href)) return;
4398
4141
  onResourceFound('dns-prefetch' === rel || 'icon' === rel || 'manifest' === rel || 'modulepreload' === rel || 'preconnect' === rel || 'prefetch' === rel || 'preload' === rel || 'prerender' === rel ? {
@@ -4439,22 +4182,6 @@ function parseHtml(node, onResourceFound) {
4439
4182
  });
4440
4183
  }
4441
4184
  }
4442
- } else if ('link' === node.nodeName) {
4443
- const imagesrcset = node.attrs?.find((attr)=>'imagesrcset' === attr.name)?.value;
4444
- if (imagesrcset) {
4445
- const candidates = imagesrcset.split(',');
4446
- for (const candidate of candidates){
4447
- const parts = candidate.trim().split(/\s+/);
4448
- const url = parts[0];
4449
- if (!url) continue;
4450
- const { cleanPath } = cleanAssetUrl(url);
4451
- if (cleanPath && !parse_html_isUrl(cleanPath)) onResourceFound({
4452
- filePath: cleanPath,
4453
- childNode: node,
4454
- assetType: 'staticHref'
4455
- });
4456
- }
4457
- }
4458
4185
  }
4459
4186
  const { childNodes = [] } = node;
4460
4187
  for (const childNode of childNodes)if ('#comment' !== childNode.nodeName && '#text' !== childNode.nodeName) parseHtml(childNode, onResourceFound);
@@ -4474,6 +4201,18 @@ function reportToCompilation(compilation, compiler, message, type = 'error', fil
4474
4201
  if (already) return;
4475
4202
  compilation[bucket].push(issue);
4476
4203
  }
4204
+ const cloneParsedHtmlAsset = (assets)=>({
4205
+ css: [
4206
+ ...assets.css || []
4207
+ ],
4208
+ js: [
4209
+ ...assets.js || []
4210
+ ],
4211
+ static: [
4212
+ ...assets.static || []
4213
+ ]
4214
+ });
4215
+ const assetsFromHtmlCache = new Map();
4477
4216
  function getAssetsFromHtml(htmlFilePath, htmlContent, publicPath = 'public') {
4478
4217
  const assets = {
4479
4218
  css: [],
@@ -4481,6 +4220,15 @@ function getAssetsFromHtml(htmlFilePath, htmlContent, publicPath = 'public') {
4481
4220
  static: []
4482
4221
  };
4483
4222
  if (!htmlFilePath) return assets;
4223
+ let cacheKey;
4224
+ if (void 0 === htmlContent) try {
4225
+ const stat = __rspack_external_fs.statSync(htmlFilePath);
4226
+ cacheKey = `${stat.mtimeMs}:${stat.size}:${publicPath}`;
4227
+ const cached = assetsFromHtmlCache.get(htmlFilePath);
4228
+ if (cached && cached.key === cacheKey) return cloneParsedHtmlAsset(cached.assets);
4229
+ } catch {
4230
+ cacheKey = void 0;
4231
+ }
4484
4232
  try {
4485
4233
  const htmlString = htmlContent || __rspack_external_fs.readFileSync(htmlFilePath, {
4486
4234
  encoding: 'utf8'
@@ -4514,13 +4262,21 @@ function getAssetsFromHtml(htmlFilePath, htmlContent, publicPath = 'public') {
4514
4262
  break;
4515
4263
  }
4516
4264
  });
4517
- } catch (error) {}
4265
+ } catch (error) {
4266
+ return assets;
4267
+ }
4268
+ if (cacheKey) assetsFromHtmlCache.set(htmlFilePath, {
4269
+ key: cacheKey,
4270
+ assets: cloneParsedHtmlAsset(assets)
4271
+ });
4518
4272
  return assets;
4519
4273
  }
4520
4274
  function getHtmlPageDeclaredAssetPath(filepathList, filePath, extension) {
4521
4275
  const entryname = Object.keys(filepathList).find((key)=>{
4522
4276
  const includePath = filepathList[key];
4523
- return filepathList[key] === filePath || getAssetsFromHtml(includePath)?.js?.includes(filePath) || getAssetsFromHtml(includePath)?.css?.includes(filePath);
4277
+ if (includePath === filePath) return true;
4278
+ const assets = getAssetsFromHtml(includePath);
4279
+ return Boolean(assets?.js?.includes(filePath) || assets?.css?.includes(filePath));
4524
4280
  }) || '';
4525
4281
  const extname = getExtname(filePath);
4526
4282
  if (!entryname) return `${filePath.replace(extname, '')}${extension}`;
@@ -4636,11 +4392,9 @@ class EmitHtmlFile {
4636
4392
  continue;
4637
4393
  }
4638
4394
  const rawHtml = __rspack_external_fs.readFileSync(resolved, 'utf8');
4639
- {
4640
- const rawSource = new core_sources.RawSource(rawHtml);
4641
- const filepath = getFilePath(featureName, '.html', false);
4642
- compilation.emitAsset(filepath, rawSource);
4643
- }
4395
+ const rawSource = new core_sources.RawSource(rawHtml);
4396
+ const filepath = getFilePath(featureName, '.html', false);
4397
+ compilation.emitAsset(filepath, rawSource);
4644
4398
  }
4645
4399
  }
4646
4400
  };
@@ -4714,6 +4468,17 @@ function resolveCssAsset(compilation, feature) {
4714
4468
  href: void 0
4715
4469
  };
4716
4470
  }
4471
+ function warnIfPublicRootAssetMissing(compilation, htmlEntry, cleanPath) {
4472
+ const projectDir = __rspack_external_path.dirname(__rspack_external_path.dirname(htmlEntry));
4473
+ const publicCandidate = __rspack_external_path.join(projectDir, 'public', cleanPath.slice(1));
4474
+ if (__rspack_external_fs.existsSync(publicCandidate)) return;
4475
+ const warn = new core_WebpackError(fileNotFound(htmlEntry, cleanPath));
4476
+ warn.name = 'HtmlPublicAssetMissing';
4477
+ warn.file = htmlEntry;
4478
+ const filtered = String(warn.message).split('\n').filter((line)=>!line.includes(String(cleanPath)));
4479
+ warn.message = filtered.join('\n').trim();
4480
+ compilation.warnings.push(warn);
4481
+ }
4717
4482
  function patchHtml(compilation, feature, htmlEntry, includeList) {
4718
4483
  const htmlFile = __rspack_external_fs.readFileSync(htmlEntry, {
4719
4484
  encoding: 'utf8'
@@ -4789,53 +4554,20 @@ function patchHtmlNested(compilation, htmlEntry) {
4789
4554
  switch(assetType){
4790
4555
  case "script":
4791
4556
  if (cleanPath.startsWith('/')) {
4792
- const projectDir = __rspack_external_path.dirname(__rspack_external_path.dirname(htmlEntry));
4793
- const publicCandidate = __rspack_external_path.join(projectDir, 'public', cleanPath.slice(1));
4794
- if (!__rspack_external_fs.existsSync(publicCandidate)) {
4795
- const errorMessage = fileNotFound(htmlEntry, cleanPath);
4796
- const warn = new core_WebpackError(errorMessage);
4797
- warn.name = 'HtmlPublicAssetMissing';
4798
- warn.file = htmlEntry;
4799
- const lines = String(warn.message).split('\n');
4800
- const filtered = lines.filter((line)=>!line.includes(String(cleanPath)));
4801
- warn.message = filtered.join('\n').trim();
4802
- compilation.warnings.push(warn);
4803
- }
4557
+ warnIfPublicRootAssetMissing(compilation, htmlEntry, cleanPath);
4804
4558
  thisChildNode = __rspack_external_parse5_utilities_78b19c6a.setAttribute(thisChildNode, 'src', cleanPath + (search || '') + (hash || ''));
4805
4559
  }
4806
4560
  break;
4807
4561
  case 'css':
4808
4562
  if (cleanPath.startsWith('/')) {
4809
- const projectDir = __rspack_external_path.dirname(__rspack_external_path.dirname(htmlEntry));
4810
- const publicCandidate = __rspack_external_path.join(projectDir, 'public', cleanPath.slice(1));
4811
- if (!__rspack_external_fs.existsSync(publicCandidate)) {
4812
- const errorMessage = fileNotFound(htmlEntry, cleanPath);
4813
- const warn = new core_WebpackError(errorMessage);
4814
- warn.name = 'HtmlPublicAssetMissing';
4815
- warn.file = htmlEntry;
4816
- const lines = String(warn.message).split('\n');
4817
- const filtered = lines.filter((line)=>!line.includes(String(cleanPath)));
4818
- warn.message = filtered.join('\n').trim();
4819
- compilation.warnings.push(warn);
4820
- }
4563
+ warnIfPublicRootAssetMissing(compilation, htmlEntry, cleanPath);
4821
4564
  thisChildNode = __rspack_external_parse5_utilities_78b19c6a.setAttribute(thisChildNode, 'href', cleanPath + (search || '') + (hash || ''));
4822
4565
  }
4823
4566
  break;
4824
4567
  case 'staticHref':
4825
4568
  case 'staticSrc':
4826
4569
  if (cleanPath.startsWith('/')) {
4827
- const projectDir = __rspack_external_path.dirname(__rspack_external_path.dirname(htmlEntry));
4828
- const publicCandidate = __rspack_external_path.join(projectDir, 'public', cleanPath.slice(1));
4829
- if (!__rspack_external_fs.existsSync(publicCandidate)) {
4830
- const errorMessage = fileNotFound(htmlEntry, cleanPath);
4831
- const warn = new core_WebpackError(errorMessage);
4832
- warn.name = 'HtmlPublicAssetMissing';
4833
- warn.file = htmlEntry;
4834
- const lines = String(warn.message).split('\n');
4835
- const filtered = lines.filter((line)=>!line.includes(String(cleanPath)));
4836
- warn.message = filtered.join('\n').trim();
4837
- compilation.warnings.push(warn);
4838
- }
4570
+ warnIfPublicRootAssetMissing(compilation, htmlEntry, cleanPath);
4839
4571
  thisChildNode = __rspack_external_parse5_utilities_78b19c6a.setAttribute(thisChildNode, 'staticSrc' === assetType ? 'src' : 'href', cleanPath + (search || '') + (hash || ''));
4840
4572
  } else if (__rspack_external_fs.existsSync(absolutePath)) {
4841
4573
  const relativeFromHtml = __rspack_external_path.relative(htmlDir, absolutePath);
@@ -5509,7 +5241,7 @@ var get_bridge_scripts_dirname = __rspack_dirname(__rspack_fileURLToPath(import.
5509
5241
  function findPackageRoot(startDir) {
5510
5242
  let current = startDir;
5511
5243
  for(let i = 0; i < 15; i++){
5512
- if (fs_0.existsSync(path_0.join(current, 'package.json'))) return current;
5244
+ if (fs.existsSync(path_0.join(current, 'package.json'))) return current;
5513
5245
  const parent = path_0.dirname(current);
5514
5246
  if (parent === current) break;
5515
5247
  current = parent;
@@ -5524,7 +5256,7 @@ function resolveExistingFile(candidates) {
5524
5256
  ];
5525
5257
  for (const candidate of candidates)if (candidate) for (const suffix of suffixes){
5526
5258
  const resolved = suffix ? `${candidate}${suffix}` : candidate;
5527
- if (fs_0.existsSync(resolved)) return resolved;
5259
+ if (fs.existsSync(resolved)) return resolved;
5528
5260
  }
5529
5261
  }
5530
5262
  function resolveMainWorldBridgeSourcePath(options) {
@@ -5539,7 +5271,7 @@ function resolveMainWorldBridgeSourcePath(options) {
5539
5271
  function getMainWorldBridgeScripts(manifestPath) {
5540
5272
  const bridgeScripts = {};
5541
5273
  try {
5542
- const raw = JSON.parse(fs_0.readFileSync(manifestPath, 'utf-8'));
5274
+ const raw = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
5543
5275
  const contentScripts = Array.isArray(raw?.content_scripts) ? raw.content_scripts : [];
5544
5276
  const originalCount = contentScripts.length;
5545
5277
  const bridgeSource = resolveMainWorldBridgeSourcePath();
@@ -6620,9 +6352,6 @@ class WebExtensionPlugin {
6620
6352
  }
6621
6353
  }
6622
6354
  const webpack_target_webextension_fork = WebExtensionPlugin;
6623
- function manifest_getManifestContent(compilation, manifestPath) {
6624
- return getManifestContent(compilation, manifestPath);
6625
- }
6626
6355
  function scripts_lib_manifest_filterKeysForThisBrowser(manifest, browser) {
6627
6356
  return manifest_filterKeysForThisBrowser(manifest, browser);
6628
6357
  }
@@ -6692,253 +6421,6 @@ class SetupBackgroundEntry {
6692
6421
  }
6693
6422
  }
6694
6423
  }
6695
- function patch_csp_resolveV2Policy(policy) {
6696
- if (!policy) return;
6697
- if ('string' == typeof policy) return policy;
6698
- if ('object' == typeof policy) {
6699
- const extensionPages = policy.extension_pages;
6700
- if ('string' == typeof extensionPages) return extensionPages;
6701
- }
6702
- }
6703
- function patch_csp_buildCSP(cspObject) {
6704
- const directives = Object.entries(cspObject).map(([directive, values])=>`${directive} ${values.join(' ')}`);
6705
- return directives.join('; ') + '; ';
6706
- }
6707
- function patch_csp_patchV2CSP(manifest) {
6708
- let policy = patch_csp_resolveV2Policy(manifest.content_security_policy);
6709
- if (!policy) return patch_csp_buildCSP({
6710
- "script-src": [
6711
- "'self'",
6712
- "'unsafe-eval'",
6713
- 'blob:',
6714
- 'filesystem:'
6715
- ],
6716
- 'object-src': [
6717
- "'self'",
6718
- 'blob:',
6719
- 'filesystem:'
6720
- ]
6721
- });
6722
- const csp = content_security_policy_parser(policy);
6723
- if (csp.get("script-src")) {
6724
- const scriptSrc = csp.get("script-src") || [];
6725
- if (!scriptSrc.includes("'unsafe-eval'")) scriptSrc.push("'unsafe-eval'");
6726
- if (!scriptSrc.includes('blob:')) scriptSrc.push('blob:');
6727
- if (!scriptSrc.includes('filesystem:')) scriptSrc.push('filesystem:');
6728
- csp.set("script-src", scriptSrc);
6729
- } else csp.set("script-src", [
6730
- "'self'",
6731
- "'unsafe-eval'",
6732
- 'blob:',
6733
- 'filesystem:'
6734
- ]);
6735
- if (csp.get('object-src')) {
6736
- const objectSrc = csp.get('object-src') || [];
6737
- if (!objectSrc.includes('blob:')) objectSrc.push('blob:');
6738
- if (!objectSrc.includes('filesystem:')) objectSrc.push('filesystem:');
6739
- csp.set('object-src', objectSrc);
6740
- } else csp.set('object-src', [
6741
- "'self'",
6742
- 'blob:',
6743
- 'filesystem:'
6744
- ]);
6745
- const cspObject = Object.fromEntries(csp.entries());
6746
- return patch_csp_buildCSP(cspObject);
6747
- }
6748
- function patch_csp_patchV3CSP(manifest) {
6749
- const policy = manifest.content_security_policy;
6750
- if (!policy) return {
6751
- extension_pages: patch_csp_buildCSP({
6752
- "script-src": [
6753
- "'self'"
6754
- ],
6755
- 'object-src': [
6756
- "'self'"
6757
- ]
6758
- })
6759
- };
6760
- const csp = content_security_policy_parser(policy.extension_pages || '');
6761
- const defaultDirectives = {
6762
- "script-src": [
6763
- "'self'"
6764
- ],
6765
- 'object-src': [
6766
- "'self'"
6767
- ]
6768
- };
6769
- for(const directive in defaultDirectives)if (!csp.get(directive)) csp.set(directive, defaultDirectives[directive]);
6770
- const cspObject = Object.fromEntries(csp.entries());
6771
- const extensionPagesPolicy = patch_csp_buildCSP(cspObject);
6772
- return {
6773
- extension_pages: extensionPagesPolicy
6774
- };
6775
- }
6776
- function patch_web_resources_patchWebResourcesV2(manifest) {
6777
- const defaultResources = [
6778
- '/*.json',
6779
- '/*.js',
6780
- '/*.css',
6781
- '/*.scss',
6782
- '/*.sass',
6783
- '/*.less',
6784
- '*.styl',
6785
- "/scripts/*.js",
6786
- "/scripts/*.css",
6787
- '/hot/*',
6788
- '/*.png',
6789
- '/*.jpg',
6790
- '/*.jpeg',
6791
- '/*.svg',
6792
- '/*.gif',
6793
- '/*.webp',
6794
- '/*.ico',
6795
- '/*.avif'
6796
- ];
6797
- const resources = manifest.web_accessible_resources;
6798
- if (!resources || 0 === resources.length) return defaultResources;
6799
- const webResources = new Set(resources);
6800
- for (const resource of defaultResources)if (!webResources.has(resource)) webResources.add(resource);
6801
- return Array.from(webResources);
6802
- }
6803
- function patch_web_resources_patchWebResourcesV3(manifest) {
6804
- const defaultResources = [
6805
- '/*.json',
6806
- '/*.js',
6807
- '/*.css',
6808
- '/*.scss',
6809
- '/*.sass',
6810
- '/*.less',
6811
- '*.styl',
6812
- "/scripts/*.js",
6813
- "/scripts/*.css",
6814
- '/hot/*',
6815
- '/*.png',
6816
- '/*.jpg',
6817
- '/*.jpeg',
6818
- '/*.svg',
6819
- '/*.gif',
6820
- '/*.webp',
6821
- '/*.ico',
6822
- '/*.avif'
6823
- ];
6824
- return [
6825
- ...manifest.web_accessible_resources || [],
6826
- {
6827
- resources: defaultResources,
6828
- matches: [
6829
- '<all_urls>'
6830
- ]
6831
- }
6832
- ];
6833
- }
6834
- function patch_background_patchBackground(manifest, browser) {
6835
- if (!manifest.background) {
6836
- if ('firefox' === browser || 'gecko-based' === browser) return {
6837
- background: {
6838
- ...manifest.background || {},
6839
- scripts: [
6840
- "background/script.js"
6841
- ]
6842
- }
6843
- };
6844
- if (2 === manifest.manifest_version) return {
6845
- background: {
6846
- ...manifest.background || {},
6847
- scripts: [
6848
- "background/script.js"
6849
- ]
6850
- }
6851
- };
6852
- return {
6853
- background: {
6854
- ...manifest.background || {},
6855
- service_worker: 'background/service_worker.js'
6856
- }
6857
- };
6858
- }
6859
- return {
6860
- background: {
6861
- ...manifest.background
6862
- }
6863
- };
6864
- }
6865
- function patch_externally_connectable_patchExternallyConnectable(manifest) {
6866
- if (manifest.externally_connectable && !manifest.externally_connectable.ids) return {
6867
- externally_connectable: {
6868
- ...manifest.externally_connectable,
6869
- ids: [
6870
- ...new Set(manifest.externally_connectable.ids || []),
6871
- '*'
6872
- ]
6873
- }
6874
- };
6875
- if (manifest.externally_connectable && !manifest.externally_connectable.ids) return {
6876
- externally_connectable: {
6877
- ...manifest.externally_connectable,
6878
- ids: [
6879
- '*'
6880
- ]
6881
- }
6882
- };
6883
- return {};
6884
- }
6885
- class ApplyManifestDevDefaults {
6886
- manifestPath;
6887
- browser;
6888
- constructor(options){
6889
- this.manifestPath = options.manifestPath;
6890
- this.browser = options.browser || 'chrome';
6891
- }
6892
- generateManifestPatches(compilation) {
6893
- const canonicalManifest = manifest_getManifestContent(compilation, this.manifestPath);
6894
- const patchedManifest = {
6895
- ...canonicalManifest,
6896
- content_security_policy: 3 === canonicalManifest.manifest_version ? patch_csp_patchV3CSP(canonicalManifest) : patch_csp_patchV2CSP(canonicalManifest),
6897
- ...3 === canonicalManifest.manifest_version ? canonicalManifest.permissions ? {
6898
- permissions: [
6899
- ...new Set([
6900
- "scripting",
6901
- 'tabs',
6902
- 'management',
6903
- ...canonicalManifest.permissions
6904
- ])
6905
- ]
6906
- } : {
6907
- permissions: [
6908
- "scripting",
6909
- 'tabs',
6910
- 'management'
6911
- ]
6912
- } : {},
6913
- ...patch_background_patchBackground(canonicalManifest, this.browser),
6914
- ...patch_externally_connectable_patchExternallyConnectable(canonicalManifest),
6915
- web_accessible_resources: 3 === canonicalManifest.manifest_version ? patch_web_resources_patchWebResourcesV3(canonicalManifest) : patch_web_resources_patchWebResourcesV2(canonicalManifest)
6916
- };
6917
- const source = JSON.stringify(patchedManifest, null, 2);
6918
- const rawSource = new core_sources.RawSource(source);
6919
- if (compilation.getAsset('manifest.json')) compilation.updateAsset('manifest.json', rawSource);
6920
- }
6921
- apply(compiler) {
6922
- if (!compiler?.hooks?.thisCompilation) return;
6923
- compiler.hooks.thisCompilation.tap('run-chromium:apply-manifest-dev-defaults', (compilation)=>{
6924
- if (!compilation?.hooks?.processAssets) return;
6925
- compilation.hooks.processAssets.tap({
6926
- name: 'run-chromium:apply-manifest-dev-defaults',
6927
- stage: core_Compilation.PROCESS_ASSETS_STAGE_REPORT + 100
6928
- }, (_assets)=>{
6929
- if (!this.manifestPath) {
6930
- const errorMessage = 'No manifest.json found in your extension bundle. Unable to patch manifest.json.';
6931
- try {
6932
- const WebpackErrorCtor = compiler?.rspack?.WebpackError;
6933
- compilation.errors.push(WebpackErrorCtor ? new WebpackErrorCtor(`run-chromium: ${errorMessage}`) : new Error(`run-chromium: ${errorMessage}`));
6934
- } catch {}
6935
- return;
6936
- }
6937
- this.generateManifestPatches(compilation);
6938
- });
6939
- });
6940
- }
6941
- }
6942
6424
  class SetupReloadStrategy {
6943
6425
  manifestPath;
6944
6426
  browser;
@@ -7005,10 +6487,6 @@ class SetupReloadStrategy {
7005
6487
  };
7006
6488
  }
7007
6489
  } catch {}
7008
- new ApplyManifestDevDefaults({
7009
- manifestPath: this.manifestPath,
7010
- browser: this.browser
7011
- }).apply(compiler);
7012
6490
  new SetupBackgroundEntry({
7013
6491
  manifestPath: this.manifestPath,
7014
6492
  browser: this.browser
@@ -7153,6 +6631,517 @@ class InjectScriptsReplayShim {
7153
6631
  });
7154
6632
  }
7155
6633
  }
6634
+ const BRIDGE_PRODUCER_SOURCE = `;(function () {
6635
+ try {
6636
+ var g = (typeof globalThis === "object" && globalThis) ? globalThis : this;
6637
+ if (!g || g.__extjsBridgeProducerInstalled) return;
6638
+
6639
+ var PORT = parseInt("__EXTJS_CONTROL_PORT__", 10);
6640
+ var INSTANCE_ID = "__EXTJS_INSTANCE_ID__";
6641
+ var CONTEXT = "__EXTJS_CONTEXT__";
6642
+ if (!PORT || PORT < 1) return;
6643
+
6644
+ var WS = g.WebSocket;
6645
+ if (typeof WS !== "function") return;
6646
+
6647
+ var consoleRef = g.console || {};
6648
+ g.__extjsBridgeProducerInstalled = true;
6649
+
6650
+ var LEVELS = ["log", "info", "warn", "error", "debug", "trace"];
6651
+ var socket = null;
6652
+ var open = false;
6653
+ var queue = [];
6654
+ var backoff = 250;
6655
+ var MAX_BACKOFF = 5000;
6656
+ var MAX_QUEUE = 1000;
6657
+ var MAX_RESULT_BYTES = 256 * 1024;
6658
+
6659
+ function nowId() {
6660
+ return Date.now().toString(36) + Math.random().toString(36).slice(2, 8);
6661
+ }
6662
+
6663
+ function engineName() {
6664
+ try {
6665
+ return (typeof navigator !== "undefined" && /firefox/i.test(navigator.userAgent)) ? "firefox" : "chromium";
6666
+ } catch (e) { return "chromium"; }
6667
+ }
6668
+
6669
+ // JSON-safe, byte-capped clone of a result value.
6670
+ function safeValue(v) {
6671
+ try {
6672
+ var s = JSON.stringify(v);
6673
+ if (s === undefined) return {value: undefined, truncated: false};
6674
+ if (s.length > MAX_RESULT_BYTES) {
6675
+ return {value: {__type: "truncated", preview: s.slice(0, 1024)}, truncated: true};
6676
+ }
6677
+ return {value: JSON.parse(s), truncated: false};
6678
+ } catch (e) {
6679
+ return {value: {__type: "unserializable", preview: String(v).slice(0, 512)}, truncated: false};
6680
+ }
6681
+ }
6682
+
6683
+ function replyOk(cmdId, value) {
6684
+ var s = safeValue(value);
6685
+ var frame = {type: "result", cmdId: cmdId, ok: true, value: s.value};
6686
+ if (s.truncated) frame.truncated = true;
6687
+ try { socket && socket.send(JSON.stringify(frame)); } catch (e) {}
6688
+ }
6689
+
6690
+ function replyErr(cmdId, name, message) {
6691
+ var frame = {type: "result", cmdId: cmdId, ok: false, error: {name: name, message: String(message), engine: engineName()}};
6692
+ try { socket && socket.send(JSON.stringify(frame)); } catch (e) {}
6693
+ }
6694
+
6695
+ // Execute one authorized command in the SW (or route to a tab). chrome.*
6696
+ // promise APIs are used; callback-only APIs are wrapped.
6697
+ function executeCommand(cmd) {
6698
+ var op = cmd.op, target = cmd.target || {}, args = cmd.args || {};
6699
+ var ctx = target.context || "background";
6700
+ var chrome = g.chrome;
6701
+ var cmdId = cmd.cmdId;
6702
+ try {
6703
+ if (!chrome) { replyErr(cmdId, "Unsupported", "chrome.* not available in this context"); return; }
6704
+ if (op === "eval") {
6705
+ if (ctx === "background") {
6706
+ Promise.resolve().then(function () { return (0, eval)(args.expression); })
6707
+ .then(function (r) { replyOk(cmdId, r); }, function (e) {
6708
+ var msg = (e && e.message) || String(e);
6709
+ // MV3 forbids eval of strings in the SW/extension pages; Chrome
6710
+ // rejects 'unsafe-eval' in MV3 extension_pages, so this can't be
6711
+ // relaxed. Surface it honestly with a usable alternative.
6712
+ if (/Content Security Policy|unsafe-eval/i.test(msg)) {
6713
+ replyErr(cmdId, "Unsupported", "eval is blocked in the MV3 service worker by CSP. Use --context page --tab <id> (eval runs in the page's MAIN world), or run on an MV2/Firefox build. Engine: " + engineName());
6714
+ } else {
6715
+ replyErr(cmdId, (e && e.name) || "EvalError", msg);
6716
+ }
6717
+ });
6718
+ } else if ((ctx === "content" || ctx === "page") && target.tabId && chrome.scripting) {
6719
+ chrome.scripting.executeScript({
6720
+ target: {tabId: target.tabId},
6721
+ world: ctx === "page" ? "MAIN" : "ISOLATED",
6722
+ func: function (src) { return eval(src); },
6723
+ args: [String(args.expression)]
6724
+ }).then(function (res) { replyOk(cmdId, res && res[0] ? res[0].result : undefined); },
6725
+ function (e) { replyErr(cmdId, "EvalError", e); });
6726
+ } else {
6727
+ replyErr(cmdId, "Unsupported", "eval in context " + ctx + " requires a tabId");
6728
+ }
6729
+ return;
6730
+ }
6731
+ if (op === "storage.get") {
6732
+ chrome.storage[args.area || "local"].get(args.key != null ? args.key : null)
6733
+ .then(function (r) { replyOk(cmdId, r); }, function (e) { replyErr(cmdId, "StorageError", e); });
6734
+ return;
6735
+ }
6736
+ if (op === "storage.set") {
6737
+ chrome.storage[args.area || "local"].set(args.items || {})
6738
+ .then(function () { replyOk(cmdId, {set: Object.keys(args.items || {})}); }, function (e) { replyErr(cmdId, "StorageError", e); });
6739
+ return;
6740
+ }
6741
+ if (op === "reload") {
6742
+ if (ctx === "background") {
6743
+ replyOk(cmdId, {reloading: true});
6744
+ setTimeout(function () { try { chrome.runtime.reload(); } catch (e) {} }, 50);
6745
+ } else if (target.tabId) {
6746
+ chrome.tabs.reload(target.tabId).then(function () { replyOk(cmdId, {reloaded: target.tabId}); }, function (e) { replyErr(cmdId, "ReloadError", e); });
6747
+ } else {
6748
+ replyErr(cmdId, "Unsupported", "reload needs background or a tabId");
6749
+ }
6750
+ return;
6751
+ }
6752
+ if (op === "open") {
6753
+ var surface = args.surface || ctx;
6754
+ if (surface === "popup") {
6755
+ if (chrome.action && chrome.action.openPopup) {
6756
+ chrome.action.openPopup().then(function () { replyOk(cmdId, {opened: "popup"}); }, function (e) { replyErr(cmdId, "Unsupported", "openPopup: " + e); });
6757
+ } else { replyErr(cmdId, "Unsupported", "action.openPopup not available"); }
6758
+ } else if (surface === "options") {
6759
+ try { chrome.runtime.openOptionsPage(function () { replyOk(cmdId, {opened: "options"}); }); }
6760
+ catch (e) { replyErr(cmdId, "Unsupported", "openOptionsPage: " + e); }
6761
+ } else if (surface === "sidebar") {
6762
+ if (chrome.sidePanel && chrome.sidePanel.open && chrome.windows) {
6763
+ chrome.windows.getCurrent(function (w) {
6764
+ chrome.sidePanel.open({windowId: w.id}).then(function () { replyOk(cmdId, {opened: "sidebar"}); }, function (e) { replyErr(cmdId, "Unsupported", "sidePanel.open: " + e); });
6765
+ });
6766
+ } else { replyErr(cmdId, "Unsupported", "sidePanel not available (engine: " + engineName() + ")"); }
6767
+ } else { replyErr(cmdId, "BadRequest", "unknown surface: " + surface); }
6768
+ return;
6769
+ }
6770
+ if (op === "tabs.query") {
6771
+ chrome.tabs.query(args || {}).then(function (tabs) {
6772
+ replyOk(cmdId, (tabs || []).map(function (t) { return {id: t.id, url: t.url, title: t.title, active: t.active, windowId: t.windowId}; }));
6773
+ }, function (e) { replyErr(cmdId, "TabsError", e); });
6774
+ return;
6775
+ }
6776
+ if (op === "inspect") {
6777
+ // Slice 3 sidecar/default path: extract a DOM snapshot from the target
6778
+ // page via chrome.scripting (CDP-free). Closed shadow roots need the
6779
+ // --deep-dom CDP escape hatch (separate tool); here we read open ones.
6780
+ if ((ctx === "content" || ctx === "page") && target.tabId && chrome.scripting) {
6781
+ var maxBytes = (args && args.maxBytes) || 262144;
6782
+ var includeHtml = !args || !args.include || args.include.indexOf("html") !== -1;
6783
+ chrome.scripting.executeScript({
6784
+ target: {tabId: target.tabId},
6785
+ world: ctx === "page" ? "MAIN" : "ISOLATED",
6786
+ func: function (wantHtml, cap) {
6787
+ function countShadow(root) {
6788
+ var n = 0, els = root.querySelectorAll("*");
6789
+ for (var i = 0; i < els.length; i++) { if (els[i].shadowRoot) { n++; n += countShadow(els[i].shadowRoot); } }
6790
+ return n;
6791
+ }
6792
+ var doc = document;
6793
+ var roots = doc.querySelectorAll('#extension-root,[data-extension-root]');
6794
+ var out = {
6795
+ url: location.href,
6796
+ title: doc.title,
6797
+ summary: {
6798
+ htmlLength: doc.documentElement.outerHTML.length,
6799
+ scriptCount: doc.querySelectorAll("script").length,
6800
+ styleCount: doc.querySelectorAll("style,link[rel=stylesheet]").length,
6801
+ extensionRootCount: roots.length,
6802
+ openShadowRoots: countShadow(doc),
6803
+ bodyChildCount: doc.body ? doc.body.children.length : 0
6804
+ }
6805
+ };
6806
+ if (wantHtml) {
6807
+ var html = doc.documentElement.outerHTML;
6808
+ if (cap > 0 && html.length > cap) { out.html = html.slice(0, cap); out.htmlTruncated = true; }
6809
+ else { out.html = html; }
6810
+ }
6811
+ return out;
6812
+ },
6813
+ args: [includeHtml, maxBytes]
6814
+ }).then(function (res) { replyOk(cmdId, res && res[0] ? res[0].result : undefined); },
6815
+ function (e) { replyErr(cmdId, "InspectError", e); });
6816
+ } else if (ctx === "popup" || ctx === "options" || ctx === "sidebar" || ctx === "devtools") {
6817
+ // The SW can't read a surface page's DOM; ask the surface's own
6818
+ // in-bundle relay (only the open, matching-context page responds).
6819
+ chrome.runtime.sendMessage(
6820
+ {__extjsInspectRequest: true, target: target, args: args},
6821
+ function (resp) {
6822
+ if (chrome.runtime.lastError || !resp) {
6823
+ replyErr(cmdId, "Unsupported", "surface '" + ctx + "' is not open (open it first: extension open " + ctx + ")");
6824
+ } else if (resp.ok) {
6825
+ replyOk(cmdId, resp.value);
6826
+ } else {
6827
+ replyErr(cmdId, (resp.error && resp.error.name) || "InspectError", (resp.error && resp.error.message) || "inspect failed");
6828
+ }
6829
+ }
6830
+ );
6831
+ } else if (ctx === "background") {
6832
+ replyErr(cmdId, "Unsupported", "the service worker has no DOM; inspect a content/page (with --tab) or an open surface");
6833
+ } else {
6834
+ replyErr(cmdId, "Unsupported", "inspect of " + ctx + " requires a tabId (content/page) or an open surface");
6835
+ }
6836
+ return;
6837
+ }
6838
+ replyErr(cmdId, "BadRequest", "unknown op: " + op);
6839
+ } catch (e) {
6840
+ replyErr(cmdId, "ExecutorError", e);
6841
+ }
6842
+ }
6843
+
6844
+ function sanitize(args) {
6845
+ var out = [];
6846
+ for (var i = 0; i < args.length; i++) {
6847
+ var p = args[i];
6848
+ try {
6849
+ if (typeof p === "string") out.push(p.length > 2048 ? p.slice(0, 2048) + "..." : p);
6850
+ else if (p instanceof Error) out.push(p.name + ": " + p.message);
6851
+ else out.push(JSON.stringify(p));
6852
+ } catch (e) {
6853
+ out.push(String(p));
6854
+ }
6855
+ if (out.join(" ").length > 8192) break;
6856
+ }
6857
+ return out;
6858
+ }
6859
+
6860
+ function flush() {
6861
+ while (queue.length && open && socket) {
6862
+ var f = queue.shift();
6863
+ try { socket.send(JSON.stringify(f)); } catch (e) { break; }
6864
+ }
6865
+ }
6866
+
6867
+ function send(frame) {
6868
+ if (open && socket) {
6869
+ try { socket.send(JSON.stringify(frame)); return; } catch (e) {}
6870
+ }
6871
+ if (queue.length < MAX_QUEUE) queue.push(frame);
6872
+ }
6873
+
6874
+ function schedule() {
6875
+ var delay = backoff;
6876
+ backoff = Math.min(backoff * 2, MAX_BACKOFF);
6877
+ try { setTimeout(connect, delay); } catch (e) {}
6878
+ }
6879
+
6880
+ function connect() {
6881
+ try {
6882
+ socket = new WS("ws://127.0.0.1:" + PORT + "/extjs-control");
6883
+ } catch (e) {
6884
+ schedule();
6885
+ return;
6886
+ }
6887
+ socket.onopen = function () {
6888
+ open = true;
6889
+ backoff = 250;
6890
+ try {
6891
+ socket.send(JSON.stringify({type: "hello", v: 1, role: "producer", instanceId: INSTANCE_ID}));
6892
+ } catch (e) {}
6893
+ flush();
6894
+ };
6895
+ socket.onmessage = function (ev) {
6896
+ // Slice 2: the broker routes authorized command frames to this SW.
6897
+ var frame;
6898
+ try { frame = JSON.parse(typeof ev.data === "string" ? ev.data : ""); } catch (e) { return; }
6899
+ if (frame && frame.type === "command") {
6900
+ try { executeCommand(frame); } catch (e) { replyErr(frame.cmdId, "ExecutorError", e); }
6901
+ }
6902
+ };
6903
+ socket.onclose = function () {
6904
+ open = false;
6905
+ socket = null;
6906
+ schedule();
6907
+ };
6908
+ socket.onerror = function () {
6909
+ try { socket && socket.close(); } catch (e) {}
6910
+ };
6911
+ }
6912
+
6913
+ LEVELS.forEach(function (level) {
6914
+ var orig = typeof consoleRef[level] === "function"
6915
+ ? consoleRef[level].bind(consoleRef)
6916
+ : function () {};
6917
+ consoleRef[level] = function () {
6918
+ try {
6919
+ send({
6920
+ type: "log",
6921
+ event: {
6922
+ v: 1,
6923
+ id: nowId(),
6924
+ timestamp: Date.now(),
6925
+ level: level,
6926
+ context: CONTEXT,
6927
+ messageParts: sanitize([].slice.call(arguments)),
6928
+ runId: INSTANCE_ID
6929
+ }
6930
+ });
6931
+ } catch (e) {}
6932
+ return orig.apply(consoleRef, arguments);
6933
+ };
6934
+ });
6935
+
6936
+ // Multi-context console forwarding: other contexts (content scripts, surface
6937
+ // pages) can't reliably open ws://127.0.0.1 (page CSP / connect-src), so they
6938
+ // relay console via chrome.runtime.sendMessage to this SW, which owns the WS.
6939
+ // We enrich with the real tabId/url from the message sender.
6940
+ try {
6941
+ var rt = g.chrome;
6942
+ if (rt && rt.runtime && rt.runtime.onMessage) {
6943
+ rt.runtime.onMessage.addListener(function (msg, sender) {
6944
+ if (!msg || !msg.__extjsBridgeLog) return;
6945
+ var ev = msg.__extjsBridgeLog;
6946
+ try {
6947
+ send({
6948
+ type: "log",
6949
+ event: {
6950
+ v: 1,
6951
+ id: nowId(),
6952
+ timestamp: Date.now(),
6953
+ level: ev.level || "log",
6954
+ context: ev.context || "content",
6955
+ messageParts: Array.isArray(ev.messageParts) ? ev.messageParts : [],
6956
+ url: ev.url || (sender ? sender.url : undefined),
6957
+ tabId: sender && sender.tab ? sender.tab.id : undefined,
6958
+ frameId: sender ? sender.frameId : undefined,
6959
+ runId: INSTANCE_ID
6960
+ }
6961
+ });
6962
+ } catch (e) {}
6963
+ // No async response.
6964
+ });
6965
+ }
6966
+ } catch (e) {}
6967
+
6968
+ connect();
6969
+ } catch (e) {}
6970
+ })();
6971
+ `;
6972
+ const BRIDGE_RELAY_SOURCE = `;(function () {
6973
+ try {
6974
+ var g = (typeof globalThis === "object" && globalThis) ? globalThis : this;
6975
+ if (!g || g.__extjsBridgeRelayInstalled) return;
6976
+
6977
+ var CONTEXT = "__EXTJS_CONTEXT__";
6978
+ var chrome = g.chrome;
6979
+ if (!chrome || !chrome.runtime || typeof chrome.runtime.sendMessage !== "function") return;
6980
+
6981
+ g.__extjsBridgeRelayInstalled = true;
6982
+ var consoleRef = g.console || {};
6983
+ var LEVELS = ["log", "info", "warn", "error", "debug", "trace"];
6984
+
6985
+ function sanitize(args) {
6986
+ var out = [];
6987
+ for (var i = 0; i < args.length; i++) {
6988
+ var p = args[i];
6989
+ try {
6990
+ if (typeof p === "string") out.push(p.length > 2048 ? p.slice(0, 2048) + "..." : p);
6991
+ else if (p instanceof Error) out.push(p.name + ": " + p.message);
6992
+ else out.push(JSON.stringify(p));
6993
+ } catch (e) { out.push(String(p)); }
6994
+ if (out.join(" ").length > 8192) break;
6995
+ }
6996
+ return out;
6997
+ }
6998
+
6999
+ function here() { try { return g.location ? g.location.href : undefined; } catch (e) { return undefined; } }
7000
+
7001
+ LEVELS.forEach(function (level) {
7002
+ var orig = typeof consoleRef[level] === "function" ? consoleRef[level].bind(consoleRef) : function () {};
7003
+ consoleRef[level] = function () {
7004
+ try {
7005
+ chrome.runtime.sendMessage(
7006
+ {__extjsBridgeLog: {level: level, context: CONTEXT, messageParts: sanitize([].slice.call(arguments)), url: here()}},
7007
+ function () { void chrome.runtime.lastError; } // swallow "no receiver" while the SW wakes
7008
+ );
7009
+ } catch (e) {}
7010
+ return orig.apply(consoleRef, arguments);
7011
+ };
7012
+ });
7013
+
7014
+ // Surface DOM inspection: the SW executor can't reach popup/options/sidebar
7015
+ // DOM (separate extension pages), and the sidecar can't either (cross-extension
7016
+ // isolation). So THIS page — the user extension's own surface — answers an
7017
+ // inspect request for its own context. The SW broadcasts the request; only the
7018
+ // matching-context surface responds with its DOM snapshot.
7019
+ try {
7020
+ if (chrome.runtime && chrome.runtime.onMessage) {
7021
+ chrome.runtime.onMessage.addListener(function (msg, _sender, sendResponse) {
7022
+ if (!msg || !msg.__extjsInspectRequest) return;
7023
+ if (!msg.target || msg.target.context !== CONTEXT) return; // not for me
7024
+ try {
7025
+ var args = msg.args || {};
7026
+ var wantHtml = !args.include || args.include.indexOf("html") !== -1;
7027
+ var cap = args.maxBytes || 262144;
7028
+ function countShadow(root) {
7029
+ var n = 0, els = root.querySelectorAll("*");
7030
+ for (var i = 0; i < els.length; i++) { if (els[i].shadowRoot) { n++; n += countShadow(els[i].shadowRoot); } }
7031
+ return n;
7032
+ }
7033
+ var doc = g.document;
7034
+ var roots = doc.querySelectorAll('#extension-root,[data-extension-root]');
7035
+ var snap = {
7036
+ context: CONTEXT,
7037
+ url: here(),
7038
+ title: doc.title,
7039
+ summary: {
7040
+ htmlLength: doc.documentElement.outerHTML.length,
7041
+ scriptCount: doc.querySelectorAll("script").length,
7042
+ styleCount: doc.querySelectorAll("style,link[rel=stylesheet]").length,
7043
+ extensionRootCount: roots.length,
7044
+ openShadowRoots: countShadow(doc),
7045
+ bodyChildCount: doc.body ? doc.body.children.length : 0
7046
+ }
7047
+ };
7048
+ if (wantHtml) {
7049
+ var html = doc.documentElement.outerHTML;
7050
+ if (cap > 0 && html.length > cap) { snap.html = html.slice(0, cap); snap.htmlTruncated = true; }
7051
+ else { snap.html = html; }
7052
+ }
7053
+ sendResponse({ok: true, value: snap});
7054
+ } catch (e) {
7055
+ sendResponse({ok: false, error: {name: "InspectError", message: String(e)}});
7056
+ }
7057
+ return true; // responded
7058
+ });
7059
+ }
7060
+ } catch (e) {}
7061
+ } catch (e) {}
7062
+ })();
7063
+ `;
7064
+ function buildBridgeRelaySource(opts) {
7065
+ return BRIDGE_RELAY_SOURCE.replace(/__EXTJS_CONTEXT__/g, String(opts.context || 'content'));
7066
+ }
7067
+ function buildBridgeProducerSource(opts) {
7068
+ if (!opts.controlPort || opts.controlPort < 1) return '';
7069
+ return BRIDGE_PRODUCER_SOURCE.replace(/__EXTJS_CONTROL_PORT__/g, String(opts.controlPort)).replace(/__EXTJS_INSTANCE_ID__/g, String(opts.instanceId)).replace(/__EXTJS_CONTEXT__/g, String(opts.context || 'background'));
7070
+ }
7071
+ const inject_bridge_producer_BACKGROUND_ASSET = /(^|\/)background\/(?:service_worker|script)\.js$/i;
7072
+ class InjectBridgeProducer {
7073
+ apply(compiler) {
7074
+ const controlPort = parseInt(String(process.env.EXTENSION_CONTROL_PORT || ''), 10);
7075
+ const instanceId = String(process.env.EXTENSION_INSTANCE_ID || '');
7076
+ const source = buildBridgeProducerSource({
7077
+ controlPort: Number.isFinite(controlPort) ? controlPort : null,
7078
+ instanceId,
7079
+ context: 'background'
7080
+ });
7081
+ if (!source) return;
7082
+ compiler.hooks.thisCompilation.tap(InjectBridgeProducer.name, (compilation)=>{
7083
+ compilation.hooks.processAssets.tap({
7084
+ name: InjectBridgeProducer.name,
7085
+ stage: core_Compilation.PROCESS_ASSETS_STAGE_REPORT + 101
7086
+ }, ()=>{
7087
+ for (const asset of compilation.getAssets()){
7088
+ if (!inject_bridge_producer_BACKGROUND_ASSET.test(asset.name)) continue;
7089
+ const original = asset.source.source().toString();
7090
+ if (-1 !== original.indexOf('__extjsBridgeProducerInstalled')) continue;
7091
+ const next = source + '\n' + original;
7092
+ compilation.updateAsset(asset.name, new core_sources.RawSource(next));
7093
+ }
7094
+ });
7095
+ });
7096
+ }
7097
+ }
7098
+ const RELAY_TARGETS = [
7099
+ {
7100
+ re: /(^|\/)content_scripts\/.+\.js$/i,
7101
+ context: 'content'
7102
+ },
7103
+ {
7104
+ re: /(^|\/)action\/index\.js$/i,
7105
+ context: 'popup'
7106
+ },
7107
+ {
7108
+ re: /(^|\/)options\/index\.js$/i,
7109
+ context: 'options'
7110
+ },
7111
+ {
7112
+ re: /(^|\/)sidebar\/index\.js$/i,
7113
+ context: 'sidebar'
7114
+ },
7115
+ {
7116
+ re: /(^|\/)devtools\/index\.js$/i,
7117
+ context: 'devtools'
7118
+ }
7119
+ ];
7120
+ class InjectBridgeRelay {
7121
+ apply(compiler) {
7122
+ const controlPort = parseInt(String(process.env.EXTENSION_CONTROL_PORT || ''), 10);
7123
+ if (!Number.isFinite(controlPort) || controlPort < 1) return;
7124
+ const sourceFor = new Map();
7125
+ for (const t of RELAY_TARGETS)if (!sourceFor.has(t.context)) sourceFor.set(t.context, buildBridgeRelaySource({
7126
+ context: t.context
7127
+ }));
7128
+ compiler.hooks.thisCompilation.tap(InjectBridgeRelay.name, (compilation)=>{
7129
+ compilation.hooks.processAssets.tap({
7130
+ name: InjectBridgeRelay.name,
7131
+ stage: core_Compilation.PROCESS_ASSETS_STAGE_REPORT + 101
7132
+ }, ()=>{
7133
+ for (const asset of compilation.getAssets()){
7134
+ const target = RELAY_TARGETS.find((t)=>t.re.test(asset.name));
7135
+ if (!target) continue;
7136
+ const original = asset.source.source().toString();
7137
+ if (-1 !== original.indexOf('__extjsBridgeRelayInstalled')) continue;
7138
+ const next = sourceFor.get(target.context) + '\n' + original;
7139
+ compilation.updateAsset(asset.name, new core_sources.RawSource(next));
7140
+ }
7141
+ });
7142
+ });
7143
+ }
7144
+ }
7156
7145
  const DEV_SERVER_CLIENT_MARKERS = [
7157
7146
  '@rspack/dev-server/client/index.js?',
7158
7147
  '@rspack/dev-server/client/utils/ansiHTML.js',
@@ -7164,6 +7153,9 @@ const DEV_SERVER_HOT_MARKERS = [
7164
7153
  '[HMR] Cannot find update. Need to do a full reload!',
7165
7154
  'module.hot.check()'
7166
7155
  ];
7156
+ function contentScriptRetainsDevServerRuntime(source) {
7157
+ return source.includes('@rspack/dev-server/client');
7158
+ }
7167
7159
  function stripDevServerStartupFromContentScript(source) {
7168
7160
  let nextSource = source;
7169
7161
  const startupModuleIds = getStartupModuleIds(source);
@@ -7213,7 +7205,7 @@ function stripStartupRequire(source, moduleId) {
7213
7205
  const startupRequirePattern = new RegExp(`^\\s*__webpack_require__\\(${moduleId}\\);\\n?`, 'm');
7214
7206
  return source.replace(startupRequirePattern, '');
7215
7207
  }
7216
- const strip_content_script_dev_server_runtime_CONTENT_SCRIPT_ASSET = /(^|\/)content_scripts\/content-\d+(?:\.[a-f0-9]+)?\.js$/i;
7208
+ const CONTENT_SCRIPT_ASSET = /(^|\/)content_scripts\/content-\d+(?:\.[a-f0-9]+)?\.js$/i;
7217
7209
  class StripContentScriptDevServerRuntime {
7218
7210
  apply(compiler) {
7219
7211
  compiler.hooks.thisCompilation.tap(StripContentScriptDevServerRuntime.name, (compilation)=>{
@@ -7222,10 +7214,17 @@ class StripContentScriptDevServerRuntime {
7222
7214
  stage: core_Compilation.PROCESS_ASSETS_STAGE_REPORT
7223
7215
  }, ()=>{
7224
7216
  for (const asset of compilation.getAssets()){
7225
- if (!strip_content_script_dev_server_runtime_CONTENT_SCRIPT_ASSET.test(asset.name)) continue;
7217
+ if (!CONTENT_SCRIPT_ASSET.test(asset.name)) continue;
7226
7218
  const originalSource = asset.source.source().toString();
7227
7219
  const strippedSource = stripDevServerStartupFromContentScript(originalSource);
7228
7220
  if (strippedSource !== originalSource) compilation.updateAsset(asset.name, new core_sources.RawSource(strippedSource));
7221
+ if (contentScriptRetainsDevServerRuntime(strippedSource)) {
7222
+ const warning = new core_WebpackError(`Could not strip the dev-server runtime from ${asset.name}. This usually means the bundler's output format changed and Extension.js needs an update. The content script may try to open a dev-server connection on the host page. Please report this at https://github.com/extension-js/extension.js/issues.`);
7223
+ warning.name = 'ContentScriptDevServerRuntimeWarning';
7224
+ warning.file = asset.name;
7225
+ compilation.warnings ||= [];
7226
+ compilation.warnings.push(warning);
7227
+ }
7229
7228
  }
7230
7229
  });
7231
7230
  });
@@ -7310,6 +7309,8 @@ class ScriptsPlugin {
7310
7309
  browser: this.browser
7311
7310
  }).apply(compiler);
7312
7311
  new InjectScriptsReplayShim().apply(compiler);
7312
+ new InjectBridgeProducer().apply(compiler);
7313
+ new InjectBridgeRelay().apply(compiler);
7313
7314
  }
7314
7315
  }
7315
7316
  }
@@ -7440,17 +7441,17 @@ function validateLocales(compiler, compilation, manifestPath) {
7440
7441
  pushCompilationError(compiler, compilation, 'LocalesValidationError', defaultLocaleMessagesMissing(defaultLocale), 'manifest.json');
7441
7442
  return false;
7442
7443
  }
7444
+ let defaultLocaleMessages;
7443
7445
  try {
7444
7446
  const content = __rspack_external_fs.readFileSync(messagesJsonPath, 'utf8');
7445
- JSON.parse(content);
7446
- } catch (e) {
7447
+ defaultLocaleMessages = JSON.parse(content);
7448
+ } catch {
7447
7449
  if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(localesValidationDetected(`invalid JSON in _locales/${defaultLocale}/messages.json`));
7448
7450
  pushCompilationError(compiler, compilation, 'LocalesValidationError', invalidMessagesJson(messagesJsonPath), 'manifest.json');
7449
7451
  return false;
7450
7452
  }
7451
7453
  try {
7452
- const content = __rspack_external_fs.readFileSync(messagesJsonPath, 'utf8');
7453
- const dict = JSON.parse(content);
7454
+ const dict = defaultLocaleMessages;
7454
7455
  const collectMsgKeys = (value, acc)=>{
7455
7456
  if ('string' == typeof value) {
7456
7457
  const regex = /__MSG_([a-zA-Z0-9_]+)__/g;
@@ -7501,8 +7502,8 @@ function validateLocales(compiler, compilation, manifestPath) {
7501
7502
  function processLocaleAssets(compiler, compilation, manifestPath) {
7502
7503
  if (compilation.errors.length > 0) return;
7503
7504
  const projectRoot = compiler.options.context || void 0;
7504
- const localesFields = getLocales(manifestPath, projectRoot);
7505
- const discoveredList = getLocales(manifestPath, projectRoot) || [];
7505
+ const localesFields = getLocales(manifestPath, projectRoot) || [];
7506
+ const discoveredList = localesFields;
7506
7507
  const resolvedLocalesRoot = resolveLocalesFolder(manifestPath, projectRoot);
7507
7508
  let emittedCount = 0;
7508
7509
  let missingCount = 0;
@@ -7751,13 +7752,9 @@ function trackJsonDependencies(compilation, manifestPath, includeList) {
7751
7752
  ];
7752
7753
  for (const thisResource of resourceArr)if (thisResource) {
7753
7754
  const abs = __rspack_external_path.isAbsolute(thisResource) ? thisResource : __rspack_external_path.join(manifestDir, thisResource);
7754
- const fileDependencies = new Set(compilation.fileDependencies);
7755
- if (__rspack_external_fs.existsSync(abs)) {
7756
- if (!fileDependencies.has(abs)) {
7757
- fileDependencies.add(abs);
7758
- compilation.fileDependencies.add(abs);
7759
- added++;
7760
- }
7755
+ if (__rspack_external_fs.existsSync(abs) && !compilation.fileDependencies.has(abs)) {
7756
+ compilation.fileDependencies.add(abs);
7757
+ added++;
7761
7758
  }
7762
7759
  }
7763
7760
  }
@@ -7779,13 +7776,6 @@ class JsonPlugin {
7779
7776
  stage: core_Compilation.PROCESS_ASSETS_STAGE_ADDITIONS
7780
7777
  }, ()=>{
7781
7778
  processJsonAssets(compilation, this.manifestPath, this.includeList || {});
7782
- });
7783
- });
7784
- compiler.hooks.thisCompilation.tap('json:module', (compilation)=>{
7785
- compilation.hooks.processAssets.tap({
7786
- name: 'json:module',
7787
- stage: core_Compilation.PROCESS_ASSETS_STAGE_ADDITIONS
7788
- }, ()=>{
7789
7779
  trackJsonDependencies(compilation, this.manifestPath, this.includeList || {});
7790
7780
  });
7791
7781
  });
@@ -7819,6 +7809,30 @@ function iconsDepsTracked(addedCount) {
7819
7809
  function iconsNormalizationSummary(beforeKeys, afterKeys, changedCount) {
7820
7810
  return `Icons include normalization — keys ${pintor.gray(String(beforeKeys.length))} → ${pintor.gray(String(afterKeys.length))}, normalized ${pintor.gray(String(changedCount))}`;
7821
7811
  }
7812
+ function iconValuesToStrings(response) {
7813
+ if (!response) return [];
7814
+ if ('string' == typeof response) return [
7815
+ response
7816
+ ];
7817
+ if (Array.isArray(response)) return response.flatMap((value)=>{
7818
+ if ('string' == typeof value) return [
7819
+ value
7820
+ ];
7821
+ if (value && 'object' == typeof value) return Object.values(value);
7822
+ return [];
7823
+ }).filter((value)=>'string' == typeof value);
7824
+ if ('object' == typeof response) return Object.values(response).filter((value)=>'string' == typeof value);
7825
+ return [];
7826
+ }
7827
+ function normalizeIconIncludeKeys(icons) {
7828
+ const out = {};
7829
+ for (const [key, value] of Object.entries(icons || {}))if ('action' === key) out['action/default_icon'] = value;
7830
+ else if ('browser_action' === key) out['browser_action/default_icon'] = value;
7831
+ else if ('page_action' === key) out['page_action/default_icon'] = value;
7832
+ else if ('sidebar_action' === key) out['sidebar_action/default_icon'] = value;
7833
+ else out[key] = value;
7834
+ return out;
7835
+ }
7822
7836
  function emit_file_reportToCompilation(compilation, message, compiler, opts) {
7823
7837
  const ErrorConstructor = compiler?.rspack?.WebpackError || Error;
7824
7838
  const errObj = new ErrorConstructor(message);
@@ -7848,25 +7862,7 @@ class EmitFile {
7848
7862
  for (const field of Object.entries(iconFields)){
7849
7863
  const [feature, resource] = field;
7850
7864
  if (void 0 === resource) continue;
7851
- const normalizeToStrings = (response)=>{
7852
- if (!response) return [];
7853
- if ('string' == typeof response) return [
7854
- response
7855
- ];
7856
- if (Array.isArray(response)) {
7857
- const flat = response.flatMap((v)=>{
7858
- if ('string' == typeof v) return [
7859
- v
7860
- ];
7861
- if (v && 'object' == typeof v) return Object.values(v);
7862
- return [];
7863
- });
7864
- return flat.filter((s)=>'string' == typeof s);
7865
- }
7866
- if ('object' == typeof response) return Object.values(response).filter((value)=>'string' == typeof value);
7867
- return [];
7868
- };
7869
- const stringEntries = normalizeToStrings(resource);
7865
+ const stringEntries = iconValuesToStrings(resource);
7870
7866
  let emittedCount = 0;
7871
7867
  let underPublicCount = 0;
7872
7868
  let missingCount = 0;
@@ -7975,34 +7971,10 @@ class add_to_file_dependencies_AddToFileDependencies {
7975
7971
  let added = 0;
7976
7972
  for (const field of Object.entries(iconFields)){
7977
7973
  const [, resource] = field;
7978
- const normalizeToStrings = (response)=>{
7979
- if (!response) return [];
7980
- if ('string' == typeof response) return [
7981
- response
7982
- ];
7983
- if (Array.isArray(response)) {
7984
- const flat = response.flatMap((value)=>{
7985
- if ('string' == typeof value) return [
7986
- value
7987
- ];
7988
- if (value && 'object' == typeof value) return Object.values(value);
7989
- return [];
7990
- });
7991
- return flat.filter((s)=>'string' == typeof s);
7992
- }
7993
- if ('object' == typeof response) return Object.values(response).filter((value)=>'string' == typeof value);
7994
- return [];
7995
- };
7996
- const stringEntries = normalizeToStrings(resource);
7997
- for (const entry of stringEntries)if (entry) {
7998
- const fileDependencies = new Set(compilation.fileDependencies);
7999
- if (__rspack_external_fs.existsSync(entry)) {
8000
- if (!fileDependencies.has(entry)) {
8001
- fileDependencies.add(entry);
8002
- compilation.fileDependencies.add(entry);
8003
- added++;
8004
- }
8005
- }
7974
+ const stringEntries = iconValuesToStrings(resource);
7975
+ for (const entry of stringEntries)if (entry && __rspack_external_fs.existsSync(entry) && !compilation.fileDependencies.has(entry)) {
7976
+ compilation.fileDependencies.add(entry);
7977
+ added++;
8006
7978
  }
8007
7979
  }
8008
7980
  if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(iconsDepsTracked(added));
@@ -8010,15 +7982,6 @@ class add_to_file_dependencies_AddToFileDependencies {
8010
7982
  });
8011
7983
  }
8012
7984
  }
8013
- function normalizeIconIncludeKeys(icons) {
8014
- const out = {};
8015
- for (const [key, value] of Object.entries(icons || {}))if ('action' === key) out['action/default_icon'] = value;
8016
- else if ('browser_action' === key) out['browser_action/default_icon'] = value;
8017
- else if ('page_action' === key) out['page_action/default_icon'] = value;
8018
- else if ('sidebar_action' === key) out['sidebar_action/default_icon'] = value;
8019
- else out[key] = value;
8020
- return out;
8021
- }
8022
7985
  class IconsPlugin {
8023
7986
  manifestPath;
8024
7987
  includeList;
@@ -8187,7 +8150,7 @@ function flattenValues(map) {
8187
8150
  return paths;
8188
8151
  }
8189
8152
  function diffArray(prev, next) {
8190
- if (prev.join(',') === next.join(',')) return null;
8153
+ if (prev.length === next.length && prev.every((value, i)=>value === next[i])) return null;
8191
8154
  const maxLen = Math.max(prev.length, next.length);
8192
8155
  let pathBefore;
8193
8156
  let pathAfter;
@@ -8466,16 +8429,18 @@ class CompatibilityPlugin {
8466
8429
  this.browser = options.browser || 'chrome';
8467
8430
  this.polyfill = options.polyfill || false;
8468
8431
  }
8469
- async apply(compiler) {
8470
- if (this.polyfill) {
8471
- if ('firefox' !== this.browser) {
8472
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(compatibilityPolyfillEnabled(this.browser, 'webextension-polyfill'));
8473
- new PolyfillPlugin({
8474
- manifestPath: this.manifestPath,
8475
- browser: this.browser || 'chrome'
8476
- }).apply(compiler);
8477
- } else if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(compatibilityPolyfillSkipped('Firefox bundles browser.* APIs', this.browser));
8478
- } else if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(compatibilityPolyfillDisabled(this.browser));
8432
+ apply(compiler) {
8433
+ const isGeckoFamily = 'firefox' === this.browser || 'gecko-based' === this.browser || 'firefox-based' === this.browser;
8434
+ if (this.polyfill) if (isGeckoFamily) {
8435
+ if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(compatibilityPolyfillSkipped('Firefox bundles browser.* APIs', this.browser));
8436
+ } else {
8437
+ if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(compatibilityPolyfillEnabled(this.browser, 'webextension-polyfill'));
8438
+ new PolyfillPlugin({
8439
+ manifestPath: this.manifestPath,
8440
+ browser: this.browser || 'chrome'
8441
+ }).apply(compiler);
8442
+ }
8443
+ else if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(compatibilityPolyfillDisabled(this.browser));
8479
8444
  }
8480
8445
  }
8481
8446
  class WasmPlugin {
@@ -8496,18 +8461,18 @@ class WasmPlugin {
8496
8461
  }
8497
8462
  buildAssetAliases(projectRoot) {
8498
8463
  const aliases = {};
8499
- const addAlias = (request, relativePath)=>{
8500
- const resolved = this.resolveAssetPath(projectRoot, relativePath);
8464
+ const addAlias = (request)=>{
8465
+ const resolved = this.resolveAssetPath(projectRoot, request);
8501
8466
  if (resolved) aliases[request] = resolved;
8502
8467
  };
8503
- addAlias('@ffmpeg/core/dist/esm/ffmpeg-core.js', '@ffmpeg/core/dist/esm/ffmpeg-core.js');
8504
- addAlias('@ffmpeg/core/dist/esm/ffmpeg-core.wasm', '@ffmpeg/core/dist/esm/ffmpeg-core.wasm');
8505
- addAlias('@ffmpeg/core-mt/dist/esm/ffmpeg-core.js', '@ffmpeg/core-mt/dist/esm/ffmpeg-core.js');
8506
- addAlias('@ffmpeg/core-mt/dist/esm/ffmpeg-core.wasm', '@ffmpeg/core-mt/dist/esm/ffmpeg-core.wasm');
8507
- addAlias('@ffmpeg/core-mt/dist/esm/ffmpeg-core.worker.js', '@ffmpeg/core-mt/dist/esm/ffmpeg-core.worker.js');
8508
- addAlias('@imagemagick/magick-wasm/magick.wasm', '@imagemagick/magick-wasm/magick.wasm');
8509
- addAlias('tesseract-wasm/dist/tesseract-worker.js', 'tesseract-wasm/dist/tesseract-worker.js');
8510
- addAlias('tesseract-wasm/dist/tesseract-core.wasm', 'tesseract-wasm/dist/tesseract-core.wasm');
8468
+ addAlias('@ffmpeg/core/dist/esm/ffmpeg-core.js');
8469
+ addAlias('@ffmpeg/core/dist/esm/ffmpeg-core.wasm');
8470
+ addAlias('@ffmpeg/core-mt/dist/esm/ffmpeg-core.js');
8471
+ addAlias('@ffmpeg/core-mt/dist/esm/ffmpeg-core.wasm');
8472
+ addAlias('@ffmpeg/core-mt/dist/esm/ffmpeg-core.worker.js');
8473
+ addAlias('@imagemagick/magick-wasm/magick.wasm');
8474
+ addAlias('tesseract-wasm/dist/tesseract-worker.js');
8475
+ addAlias('tesseract-wasm/dist/tesseract-core.wasm');
8511
8476
  return aliases;
8512
8477
  }
8513
8478
  ensureWasmResolution(compiler, projectRoot) {
@@ -8563,9 +8528,9 @@ function categorizeAsset(rawName) {
8563
8528
  return 'ignored';
8564
8529
  }
8565
8530
  const BUDGET_BYTES = {
8566
- "content-script": 262144,
8567
- 'service-worker': 204800,
8568
- page: 512000,
8531
+ "content-script": 524288,
8532
+ 'service-worker': 524288,
8533
+ page: 1048576,
8569
8534
  ignored: 1 / 0
8570
8535
  };
8571
8536
  function fmtKiB(bytes) {
@@ -8607,7 +8572,7 @@ class PerfBudgetsPlugin {
8607
8572
  ...BUDGET_BYTES,
8608
8573
  ...this.options.budgets || {}
8609
8574
  };
8610
- compiler.hooks.afterCompile.tap(PerfBudgetsPlugin.name, (compilation)=>{
8575
+ const report = (compilation)=>{
8611
8576
  if (compilation.errors?.length) return;
8612
8577
  const oversized = [];
8613
8578
  const assets = compilation.assets || {};
@@ -8617,7 +8582,7 @@ class PerfBudgetsPlugin {
8617
8582
  const category = categorizeAsset(name);
8618
8583
  if ('ignored' === category) continue;
8619
8584
  const budget = budgets[category];
8620
- if (isFinite(budget)) {
8585
+ if (Number.isFinite(budget)) {
8621
8586
  if (!(size <= budget)) oversized.push({
8622
8587
  name,
8623
8588
  size,
@@ -8633,6 +8598,13 @@ class PerfBudgetsPlugin {
8633
8598
  warning.name = 'PerfBudgetWarning';
8634
8599
  if (!compilation.warnings) compilation.warnings = [];
8635
8600
  compilation.warnings.push(warning);
8601
+ };
8602
+ const REPORT_STAGE = compiler?.rspack?.Compilation?.PROCESS_ASSETS_STAGE_REPORT ?? 5000;
8603
+ compiler.hooks.thisCompilation.tap(PerfBudgetsPlugin.name, (compilation)=>{
8604
+ compilation.hooks.processAssets.tap({
8605
+ name: PerfBudgetsPlugin.name,
8606
+ stage: REPORT_STAGE
8607
+ }, ()=>report(compilation));
8636
8608
  });
8637
8609
  }
8638
8610
  }
@@ -8640,7 +8612,13 @@ var rspack_config_dirname = __rspack_dirname(__rspack_fileURLToPath(import.meta.
8640
8612
  function webpackConfig(projectStructure, devOptions) {
8641
8613
  const { manifestPath } = projectStructure;
8642
8614
  const { packageJsonDir } = getDirs(projectStructure);
8643
- const manifest = filterKeysForThisBrowser(JSON.parse(__rspack_external_fs.readFileSync(manifestPath, 'utf-8')), devOptions.browser);
8615
+ let rawManifest;
8616
+ try {
8617
+ rawManifest = JSON.parse(__rspack_external_fs.readFileSync(manifestPath, 'utf-8'));
8618
+ } catch (error) {
8619
+ throw new Error(manifestInvalidJson(manifestPath, error));
8620
+ }
8621
+ const manifest = filterKeysForThisBrowser(rawManifest, devOptions.browser);
8644
8622
  const primaryExtensionOutputDir = asAbsolute(__rspack_external_path.isAbsolute(devOptions.output.path) ? devOptions.output.path : __rspack_external_path.resolve(packageJsonDir, devOptions.output.path));
8645
8623
  const companionUnpackedExtensionDirs = resolveCompanionExtensionDirs({
8646
8624
  projectRoot: packageJsonDir,
@@ -8694,15 +8672,21 @@ function webpackConfig(projectStructure, devOptions) {
8694
8672
  new SpecialFoldersPlugin({
8695
8673
  manifestPath
8696
8674
  }),
8697
- new PerfBudgetsPlugin()
8675
+ new PerfBudgetsPlugin({
8676
+ budgets: devOptions.perfBudgets
8677
+ })
8698
8678
  ];
8699
- if (devOptions.noBrowser) plugins.push(new PlaywrightPlugin({
8679
+ plugins.push(new PlaywrightPlugin({
8700
8680
  packageJsonDir,
8701
8681
  browser: devOptions.browser,
8702
8682
  mode: devOptions.mode,
8703
8683
  outputPath: primaryExtensionOutputDir,
8704
8684
  manifestPath,
8705
- port: devOptions.port
8685
+ port: devOptions.port,
8686
+ instanceId: devOptions.instanceId,
8687
+ controlPort: devOptions.controlPort,
8688
+ controlPath: devOptions.controlPath,
8689
+ logsPath: devOptions.logsPath
8706
8690
  }));
8707
8691
  if (devOptions.browsersPlugin) {
8708
8692
  const browsersPlugin = devOptions.browsersPlugin;
@@ -8734,7 +8718,9 @@ function webpackConfig(projectStructure, devOptions) {
8734
8718
  },
8735
8719
  watchOptions: {
8736
8720
  ignored: transpilePackageDirs.length > 0 ? /dist|extension-js\/profiles/ : /node_modules|dist|extension-js\/profiles/,
8737
- poll: 1000,
8721
+ ...'true' === process.env.EXTENSION_WATCH_POLL ? {
8722
+ poll: parseInt(String(process.env.EXTENSION_WATCH_POLL_INTERVAL || '1000'), 10)
8723
+ } : {},
8738
8724
  aggregateTimeout: 200
8739
8725
  },
8740
8726
  resolve: {