extension-develop 3.16.1 → 3.17.0-canary.312.672c4f2

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 (25) hide show
  1. package/dist/0~dev-server.mjs +21 -57
  2. package/dist/0~rspack-config.mjs +399 -909
  3. package/dist/0~zip.mjs +39 -10
  4. package/dist/946.mjs +117 -27
  5. package/dist/962.mjs +65 -18
  6. package/dist/extension-js-devtools/chrome/content_scripts/content-0.js +2 -2
  7. package/dist/extension-js-devtools/chrome/pages/centralized-logger.js +1 -1
  8. package/dist/extension-js-devtools/chrome/pages/welcome.js +2 -2
  9. package/dist/extension-js-devtools/chrome/scripts/logger-client.js +1 -1
  10. package/dist/extension-js-devtools/chromium/content_scripts/content-0.js +2 -2
  11. package/dist/extension-js-devtools/chromium/pages/centralized-logger.js +1 -1
  12. package/dist/extension-js-devtools/chromium/pages/welcome.js +2 -2
  13. package/dist/extension-js-devtools/chromium/scripts/logger-client.js +1 -1
  14. package/dist/extension-js-devtools/edge/content_scripts/content-0.js +2 -2
  15. package/dist/extension-js-devtools/edge/pages/centralized-logger.js +1 -1
  16. package/dist/extension-js-devtools/edge/pages/welcome.js +2 -2
  17. package/dist/extension-js-devtools/edge/scripts/logger-client.js +1 -1
  18. package/dist/extension-js-devtools/firefox/content_scripts/content-0.js +2 -2
  19. package/dist/extension-js-devtools/firefox/pages/centralized-logger.js +1 -1
  20. package/dist/extension-js-devtools/firefox/pages/welcome.js +2 -2
  21. package/dist/extension-js-devtools/firefox/scripts/logger-client.js +1 -1
  22. package/dist/feature-scripts-content-script-wrapper.js +19 -2
  23. package/dist/feature-scripts-content-script-wrapper.mjs +19 -2
  24. package/package.json +6 -4
  25. 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);
@@ -4109,12 +3838,6 @@ function normalizeManifestFile(filePath) {
4109
3838
  if (/[*?[\]{}]/.test(normalized)) return;
4110
3839
  return normalized;
4111
3840
  }
4112
- function compilationHasAsset(compilation, filename) {
4113
- if ('function' == typeof compilation.getAsset) {
4114
- if (compilation.getAsset(filename)) return true;
4115
- }
4116
- return Boolean(compilation.assets?.[filename]);
4117
- }
4118
3841
  function collectRequiredManifestFiles(manifest) {
4119
3842
  const required = new Set();
4120
3843
  const addFile = (filePath)=>{
@@ -4133,12 +3856,10 @@ function collectRequiredManifestFiles(manifest) {
4133
3856
  ...required
4134
3857
  ];
4135
3858
  }
4136
- function isFinalManifestReadyForDisk(compilation, manifestSource) {
4137
- const manifest = readJsonSafe(manifestSource);
4138
- if (!manifest) return false;
4139
- const requiredFiles = collectRequiredManifestFiles(manifest);
4140
- if (0 === requiredFiles.length) return true;
4141
- return requiredFiles.every((filename)=>compilationHasAsset(compilation, filename));
3859
+ function findMissingFilesOnDisk(outputPath, required) {
3860
+ const missing = [];
3861
+ for (const relativeFile of required)if (!__rspack_external_fs.existsSync(__rspack_external_path.join(outputPath, relativeFile))) missing.push(relativeFile);
3862
+ return missing;
4142
3863
  }
4143
3864
  function writeFileAtomically(targetPath, content) {
4144
3865
  const directory = __rspack_external_path.dirname(targetPath);
@@ -4146,37 +3867,72 @@ function writeFileAtomically(targetPath, content) {
4146
3867
  __rspack_external_fs.mkdirSync(directory, {
4147
3868
  recursive: true
4148
3869
  });
4149
- __rspack_external_fs.writeFileSync(tempPath, content, 'utf-8');
4150
- __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
+ }
4151
3878
  }
4152
3879
  class PersistManifestToDisk {
4153
3880
  apply(compiler) {
4154
- compiler.hooks.thisCompilation.tap('manifest:persist-manifest', (compilation)=>{
3881
+ let pendingManifestSource;
3882
+ let pendingOutputPath;
3883
+ let pendingHadErrors = false;
3884
+ compiler.hooks.thisCompilation.tap('manifest:persist-manifest:capture', (compilation)=>{
4155
3885
  compilation.hooks.processAssets.tap({
4156
- name: 'manifest:persist-manifest',
3886
+ name: 'manifest:persist-manifest:capture',
4157
3887
  stage: core_Compilation.PROCESS_ASSETS_STAGE_REPORT + 1000
4158
3888
  }, ()=>{
4159
- if (compilation.errors.length > 0) return;
4160
- const outputPath = compilation.outputOptions.path || compiler.options.output?.path;
4161
- if (!outputPath) return;
3889
+ pendingHadErrors = compilation.errors.length > 0;
3890
+ pendingOutputPath = compilation.outputOptions.path || compiler.options.output?.path;
4162
3891
  const manifestAsset = compilation.getAsset('manifest.json');
4163
3892
  const manifestSource = getCurrentManifestContent(compilation) || manifestAsset?.source?.source?.().toString();
4164
- if (!manifestSource) return;
4165
- if (!isFinalManifestReadyForDisk(compilation, manifestSource)) return;
4166
- const manifestOutputPath = __rspack_external_path.join(outputPath, 'manifest.json');
4167
- try {
4168
- try {
4169
- const currentOnDisk = __rspack_external_fs.readFileSync(manifestOutputPath, 'utf-8');
4170
- if (currentOnDisk === manifestSource) return;
4171
- } catch {}
4172
- writeFileAtomically(manifestOutputPath, manifestSource);
4173
- } catch (error) {
4174
- const err = new core.WebpackError(`Failed to persist manifest.json to disk: ${error.message}`);
4175
- err.file = 'manifest.json';
4176
- compilation.errors.push(err);
4177
- }
3893
+ pendingManifestSource = 'string' == typeof manifestSource ? manifestSource : void 0;
4178
3894
  });
4179
3895
  });
3896
+ compiler.hooks.afterEmit.tap('manifest:persist-manifest:flush', (compilation)=>{
3897
+ const outputPath = pendingOutputPath;
3898
+ const manifestSource = pendingManifestSource;
3899
+ const hadErrors = pendingHadErrors;
3900
+ pendingManifestSource = void 0;
3901
+ pendingOutputPath = void 0;
3902
+ pendingHadErrors = false;
3903
+ if (hadErrors || !outputPath || !manifestSource) return;
3904
+ const manifest = readJsonSafe(manifestSource);
3905
+ if (!manifest) return;
3906
+ const requiredFiles = collectRequiredManifestFiles(manifest);
3907
+ const missingFiles = findMissingFilesOnDisk(outputPath, requiredFiles);
3908
+ if (missingFiles.length > 0) {
3909
+ const sample = missingFiles.slice(0, 5).join('\n - ');
3910
+ const more = missingFiles.length > 5 ? `\n ... and ${missingFiles.length - 5} more` : '';
3911
+ const err = new core.WebpackError([
3912
+ 'manifest.json references files that were not emitted to disk for this build:',
3913
+ ` - ${sample}${more}`,
3914
+ '',
3915
+ 'The previous manifest.json was kept to avoid loading a broken extension.',
3916
+ 'This usually means the bundler skipped a chunk during an incremental rebuild.',
3917
+ 'Try saving any source file again, or restart `extension dev` if it persists.'
3918
+ ].join('\n'));
3919
+ err.file = 'manifest.json';
3920
+ compilation.errors.push(err);
3921
+ return;
3922
+ }
3923
+ const manifestOutputPath = __rspack_external_path.join(outputPath, 'manifest.json');
3924
+ try {
3925
+ try {
3926
+ const currentOnDisk = __rspack_external_fs.readFileSync(manifestOutputPath, 'utf-8');
3927
+ if (currentOnDisk === manifestSource) return;
3928
+ } catch {}
3929
+ writeFileAtomically(manifestOutputPath, manifestSource);
3930
+ } catch (error) {
3931
+ const err = new core.WebpackError(`Failed to persist manifest.json to disk: ${error.message}`);
3932
+ err.file = 'manifest.json';
3933
+ compilation.errors.push(err);
3934
+ }
3935
+ });
4180
3936
  }
4181
3937
  }
4182
3938
  class AddDependencies {
@@ -4190,10 +3946,7 @@ class AddDependencies {
4190
3946
  const deps = compilation.fileDependencies;
4191
3947
  if (this.dependencyList) this.dependencyList.forEach((dependency)=>{
4192
3948
  const alreadyPresent = 'function' == typeof deps?.has ? deps.has(dependency) : false;
4193
- if (!alreadyPresent) {
4194
- if ('function' == typeof deps?.add) deps.add(dependency);
4195
- if (deps !== compilation.fileDependencies && 'function' == typeof compilation.fileDependencies?.add) compilation.fileDependencies.add(dependency);
4196
- }
3949
+ if (!alreadyPresent && 'function' == typeof deps?.add) deps.add(dependency);
4197
3950
  });
4198
3951
  if ('true' === process.env.EXTENSION_AUTHOR_MODE) {
4199
3952
  const added = Array.isArray(this.dependencyList) ? this.dependencyList.length : 0;
@@ -4372,6 +4125,17 @@ function parseHtml(node, onResourceFound) {
4372
4125
  } else if ('link' === node.nodeName) {
4373
4126
  const href = node.attrs?.find((attr)=>'href' === attr.name)?.value;
4374
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
+ }
4375
4139
  if (!href) return;
4376
4140
  if (parse_html_isUrl(href)) return;
4377
4141
  onResourceFound('dns-prefetch' === rel || 'icon' === rel || 'manifest' === rel || 'modulepreload' === rel || 'preconnect' === rel || 'prefetch' === rel || 'preload' === rel || 'prerender' === rel ? {
@@ -4418,22 +4182,6 @@ function parseHtml(node, onResourceFound) {
4418
4182
  });
4419
4183
  }
4420
4184
  }
4421
- } else if ('link' === node.nodeName) {
4422
- const imagesrcset = node.attrs?.find((attr)=>'imagesrcset' === attr.name)?.value;
4423
- if (imagesrcset) {
4424
- const candidates = imagesrcset.split(',');
4425
- for (const candidate of candidates){
4426
- const parts = candidate.trim().split(/\s+/);
4427
- const url = parts[0];
4428
- if (!url) continue;
4429
- const { cleanPath } = cleanAssetUrl(url);
4430
- if (cleanPath && !parse_html_isUrl(cleanPath)) onResourceFound({
4431
- filePath: cleanPath,
4432
- childNode: node,
4433
- assetType: 'staticHref'
4434
- });
4435
- }
4436
- }
4437
4185
  }
4438
4186
  const { childNodes = [] } = node;
4439
4187
  for (const childNode of childNodes)if ('#comment' !== childNode.nodeName && '#text' !== childNode.nodeName) parseHtml(childNode, onResourceFound);
@@ -4453,6 +4201,18 @@ function reportToCompilation(compilation, compiler, message, type = 'error', fil
4453
4201
  if (already) return;
4454
4202
  compilation[bucket].push(issue);
4455
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();
4456
4216
  function getAssetsFromHtml(htmlFilePath, htmlContent, publicPath = 'public') {
4457
4217
  const assets = {
4458
4218
  css: [],
@@ -4460,6 +4220,15 @@ function getAssetsFromHtml(htmlFilePath, htmlContent, publicPath = 'public') {
4460
4220
  static: []
4461
4221
  };
4462
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
+ }
4463
4232
  try {
4464
4233
  const htmlString = htmlContent || __rspack_external_fs.readFileSync(htmlFilePath, {
4465
4234
  encoding: 'utf8'
@@ -4493,13 +4262,21 @@ function getAssetsFromHtml(htmlFilePath, htmlContent, publicPath = 'public') {
4493
4262
  break;
4494
4263
  }
4495
4264
  });
4496
- } catch (error) {}
4265
+ } catch (error) {
4266
+ return assets;
4267
+ }
4268
+ if (cacheKey) assetsFromHtmlCache.set(htmlFilePath, {
4269
+ key: cacheKey,
4270
+ assets: cloneParsedHtmlAsset(assets)
4271
+ });
4497
4272
  return assets;
4498
4273
  }
4499
4274
  function getHtmlPageDeclaredAssetPath(filepathList, filePath, extension) {
4500
4275
  const entryname = Object.keys(filepathList).find((key)=>{
4501
4276
  const includePath = filepathList[key];
4502
- 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));
4503
4280
  }) || '';
4504
4281
  const extname = getExtname(filePath);
4505
4282
  if (!entryname) return `${filePath.replace(extname, '')}${extension}`;
@@ -4615,11 +4392,9 @@ class EmitHtmlFile {
4615
4392
  continue;
4616
4393
  }
4617
4394
  const rawHtml = __rspack_external_fs.readFileSync(resolved, 'utf8');
4618
- {
4619
- const rawSource = new core_sources.RawSource(rawHtml);
4620
- const filepath = getFilePath(featureName, '.html', false);
4621
- compilation.emitAsset(filepath, rawSource);
4622
- }
4395
+ const rawSource = new core_sources.RawSource(rawHtml);
4396
+ const filepath = getFilePath(featureName, '.html', false);
4397
+ compilation.emitAsset(filepath, rawSource);
4623
4398
  }
4624
4399
  }
4625
4400
  };
@@ -4693,6 +4468,17 @@ function resolveCssAsset(compilation, feature) {
4693
4468
  href: void 0
4694
4469
  };
4695
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
+ }
4696
4482
  function patchHtml(compilation, feature, htmlEntry, includeList) {
4697
4483
  const htmlFile = __rspack_external_fs.readFileSync(htmlEntry, {
4698
4484
  encoding: 'utf8'
@@ -4768,53 +4554,20 @@ function patchHtmlNested(compilation, htmlEntry) {
4768
4554
  switch(assetType){
4769
4555
  case "script":
4770
4556
  if (cleanPath.startsWith('/')) {
4771
- const projectDir = __rspack_external_path.dirname(__rspack_external_path.dirname(htmlEntry));
4772
- const publicCandidate = __rspack_external_path.join(projectDir, 'public', cleanPath.slice(1));
4773
- if (!__rspack_external_fs.existsSync(publicCandidate)) {
4774
- const errorMessage = fileNotFound(htmlEntry, cleanPath);
4775
- const warn = new core_WebpackError(errorMessage);
4776
- warn.name = 'HtmlPublicAssetMissing';
4777
- warn.file = htmlEntry;
4778
- const lines = String(warn.message).split('\n');
4779
- const filtered = lines.filter((line)=>!line.includes(String(cleanPath)));
4780
- warn.message = filtered.join('\n').trim();
4781
- compilation.warnings.push(warn);
4782
- }
4557
+ warnIfPublicRootAssetMissing(compilation, htmlEntry, cleanPath);
4783
4558
  thisChildNode = __rspack_external_parse5_utilities_78b19c6a.setAttribute(thisChildNode, 'src', cleanPath + (search || '') + (hash || ''));
4784
4559
  }
4785
4560
  break;
4786
4561
  case 'css':
4787
4562
  if (cleanPath.startsWith('/')) {
4788
- const projectDir = __rspack_external_path.dirname(__rspack_external_path.dirname(htmlEntry));
4789
- const publicCandidate = __rspack_external_path.join(projectDir, 'public', cleanPath.slice(1));
4790
- if (!__rspack_external_fs.existsSync(publicCandidate)) {
4791
- const errorMessage = fileNotFound(htmlEntry, cleanPath);
4792
- const warn = new core_WebpackError(errorMessage);
4793
- warn.name = 'HtmlPublicAssetMissing';
4794
- warn.file = htmlEntry;
4795
- const lines = String(warn.message).split('\n');
4796
- const filtered = lines.filter((line)=>!line.includes(String(cleanPath)));
4797
- warn.message = filtered.join('\n').trim();
4798
- compilation.warnings.push(warn);
4799
- }
4563
+ warnIfPublicRootAssetMissing(compilation, htmlEntry, cleanPath);
4800
4564
  thisChildNode = __rspack_external_parse5_utilities_78b19c6a.setAttribute(thisChildNode, 'href', cleanPath + (search || '') + (hash || ''));
4801
4565
  }
4802
4566
  break;
4803
4567
  case 'staticHref':
4804
4568
  case 'staticSrc':
4805
4569
  if (cleanPath.startsWith('/')) {
4806
- const projectDir = __rspack_external_path.dirname(__rspack_external_path.dirname(htmlEntry));
4807
- const publicCandidate = __rspack_external_path.join(projectDir, 'public', cleanPath.slice(1));
4808
- if (!__rspack_external_fs.existsSync(publicCandidate)) {
4809
- const errorMessage = fileNotFound(htmlEntry, cleanPath);
4810
- const warn = new core_WebpackError(errorMessage);
4811
- warn.name = 'HtmlPublicAssetMissing';
4812
- warn.file = htmlEntry;
4813
- const lines = String(warn.message).split('\n');
4814
- const filtered = lines.filter((line)=>!line.includes(String(cleanPath)));
4815
- warn.message = filtered.join('\n').trim();
4816
- compilation.warnings.push(warn);
4817
- }
4570
+ warnIfPublicRootAssetMissing(compilation, htmlEntry, cleanPath);
4818
4571
  thisChildNode = __rspack_external_parse5_utilities_78b19c6a.setAttribute(thisChildNode, 'staticSrc' === assetType ? 'src' : 'href', cleanPath + (search || '') + (hash || ''));
4819
4572
  } else if (__rspack_external_fs.existsSync(absolutePath)) {
4820
4573
  const relativeFromHtml = __rspack_external_path.relative(htmlDir, absolutePath);
@@ -5488,7 +5241,7 @@ var get_bridge_scripts_dirname = __rspack_dirname(__rspack_fileURLToPath(import.
5488
5241
  function findPackageRoot(startDir) {
5489
5242
  let current = startDir;
5490
5243
  for(let i = 0; i < 15; i++){
5491
- if (fs_0.existsSync(path_0.join(current, 'package.json'))) return current;
5244
+ if (fs.existsSync(path_0.join(current, 'package.json'))) return current;
5492
5245
  const parent = path_0.dirname(current);
5493
5246
  if (parent === current) break;
5494
5247
  current = parent;
@@ -5503,7 +5256,7 @@ function resolveExistingFile(candidates) {
5503
5256
  ];
5504
5257
  for (const candidate of candidates)if (candidate) for (const suffix of suffixes){
5505
5258
  const resolved = suffix ? `${candidate}${suffix}` : candidate;
5506
- if (fs_0.existsSync(resolved)) return resolved;
5259
+ if (fs.existsSync(resolved)) return resolved;
5507
5260
  }
5508
5261
  }
5509
5262
  function resolveMainWorldBridgeSourcePath(options) {
@@ -5518,7 +5271,7 @@ function resolveMainWorldBridgeSourcePath(options) {
5518
5271
  function getMainWorldBridgeScripts(manifestPath) {
5519
5272
  const bridgeScripts = {};
5520
5273
  try {
5521
- const raw = JSON.parse(fs_0.readFileSync(manifestPath, 'utf-8'));
5274
+ const raw = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
5522
5275
  const contentScripts = Array.isArray(raw?.content_scripts) ? raw.content_scripts : [];
5523
5276
  const originalCount = contentScripts.length;
5524
5277
  const bridgeSource = resolveMainWorldBridgeSourcePath();
@@ -6599,9 +6352,6 @@ class WebExtensionPlugin {
6599
6352
  }
6600
6353
  }
6601
6354
  const webpack_target_webextension_fork = WebExtensionPlugin;
6602
- function manifest_getManifestContent(compilation, manifestPath) {
6603
- return getManifestContent(compilation, manifestPath);
6604
- }
6605
6355
  function scripts_lib_manifest_filterKeysForThisBrowser(manifest, browser) {
6606
6356
  return manifest_filterKeysForThisBrowser(manifest, browser);
6607
6357
  }
@@ -6671,253 +6421,6 @@ class SetupBackgroundEntry {
6671
6421
  }
6672
6422
  }
6673
6423
  }
6674
- function patch_csp_resolveV2Policy(policy) {
6675
- if (!policy) return;
6676
- if ('string' == typeof policy) return policy;
6677
- if ('object' == typeof policy) {
6678
- const extensionPages = policy.extension_pages;
6679
- if ('string' == typeof extensionPages) return extensionPages;
6680
- }
6681
- }
6682
- function patch_csp_buildCSP(cspObject) {
6683
- const directives = Object.entries(cspObject).map(([directive, values])=>`${directive} ${values.join(' ')}`);
6684
- return directives.join('; ') + '; ';
6685
- }
6686
- function patch_csp_patchV2CSP(manifest) {
6687
- let policy = patch_csp_resolveV2Policy(manifest.content_security_policy);
6688
- if (!policy) return patch_csp_buildCSP({
6689
- "script-src": [
6690
- "'self'",
6691
- "'unsafe-eval'",
6692
- 'blob:',
6693
- 'filesystem:'
6694
- ],
6695
- 'object-src': [
6696
- "'self'",
6697
- 'blob:',
6698
- 'filesystem:'
6699
- ]
6700
- });
6701
- const csp = content_security_policy_parser(policy);
6702
- if (csp.get("script-src")) {
6703
- const scriptSrc = csp.get("script-src") || [];
6704
- if (!scriptSrc.includes("'unsafe-eval'")) scriptSrc.push("'unsafe-eval'");
6705
- if (!scriptSrc.includes('blob:')) scriptSrc.push('blob:');
6706
- if (!scriptSrc.includes('filesystem:')) scriptSrc.push('filesystem:');
6707
- csp.set("script-src", scriptSrc);
6708
- } else csp.set("script-src", [
6709
- "'self'",
6710
- "'unsafe-eval'",
6711
- 'blob:',
6712
- 'filesystem:'
6713
- ]);
6714
- if (csp.get('object-src')) {
6715
- const objectSrc = csp.get('object-src') || [];
6716
- if (!objectSrc.includes('blob:')) objectSrc.push('blob:');
6717
- if (!objectSrc.includes('filesystem:')) objectSrc.push('filesystem:');
6718
- csp.set('object-src', objectSrc);
6719
- } else csp.set('object-src', [
6720
- "'self'",
6721
- 'blob:',
6722
- 'filesystem:'
6723
- ]);
6724
- const cspObject = Object.fromEntries(csp.entries());
6725
- return patch_csp_buildCSP(cspObject);
6726
- }
6727
- function patch_csp_patchV3CSP(manifest) {
6728
- const policy = manifest.content_security_policy;
6729
- if (!policy) return {
6730
- extension_pages: patch_csp_buildCSP({
6731
- "script-src": [
6732
- "'self'"
6733
- ],
6734
- 'object-src': [
6735
- "'self'"
6736
- ]
6737
- })
6738
- };
6739
- const csp = content_security_policy_parser(policy.extension_pages || '');
6740
- const defaultDirectives = {
6741
- "script-src": [
6742
- "'self'"
6743
- ],
6744
- 'object-src': [
6745
- "'self'"
6746
- ]
6747
- };
6748
- for(const directive in defaultDirectives)if (!csp.get(directive)) csp.set(directive, defaultDirectives[directive]);
6749
- const cspObject = Object.fromEntries(csp.entries());
6750
- const extensionPagesPolicy = patch_csp_buildCSP(cspObject);
6751
- return {
6752
- extension_pages: extensionPagesPolicy
6753
- };
6754
- }
6755
- function patch_web_resources_patchWebResourcesV2(manifest) {
6756
- const defaultResources = [
6757
- '/*.json',
6758
- '/*.js',
6759
- '/*.css',
6760
- '/*.scss',
6761
- '/*.sass',
6762
- '/*.less',
6763
- '*.styl',
6764
- "/scripts/*.js",
6765
- "/scripts/*.css",
6766
- '/hot/*',
6767
- '/*.png',
6768
- '/*.jpg',
6769
- '/*.jpeg',
6770
- '/*.svg',
6771
- '/*.gif',
6772
- '/*.webp',
6773
- '/*.ico',
6774
- '/*.avif'
6775
- ];
6776
- const resources = manifest.web_accessible_resources;
6777
- if (!resources || 0 === resources.length) return defaultResources;
6778
- const webResources = new Set(resources);
6779
- for (const resource of defaultResources)if (!webResources.has(resource)) webResources.add(resource);
6780
- return Array.from(webResources);
6781
- }
6782
- function patch_web_resources_patchWebResourcesV3(manifest) {
6783
- const defaultResources = [
6784
- '/*.json',
6785
- '/*.js',
6786
- '/*.css',
6787
- '/*.scss',
6788
- '/*.sass',
6789
- '/*.less',
6790
- '*.styl',
6791
- "/scripts/*.js",
6792
- "/scripts/*.css",
6793
- '/hot/*',
6794
- '/*.png',
6795
- '/*.jpg',
6796
- '/*.jpeg',
6797
- '/*.svg',
6798
- '/*.gif',
6799
- '/*.webp',
6800
- '/*.ico',
6801
- '/*.avif'
6802
- ];
6803
- return [
6804
- ...manifest.web_accessible_resources || [],
6805
- {
6806
- resources: defaultResources,
6807
- matches: [
6808
- '<all_urls>'
6809
- ]
6810
- }
6811
- ];
6812
- }
6813
- function patch_background_patchBackground(manifest, browser) {
6814
- if (!manifest.background) {
6815
- if ('firefox' === browser || 'gecko-based' === browser) return {
6816
- background: {
6817
- ...manifest.background || {},
6818
- scripts: [
6819
- "background/script.js"
6820
- ]
6821
- }
6822
- };
6823
- if (2 === manifest.manifest_version) return {
6824
- background: {
6825
- ...manifest.background || {},
6826
- scripts: [
6827
- "background/script.js"
6828
- ]
6829
- }
6830
- };
6831
- return {
6832
- background: {
6833
- ...manifest.background || {},
6834
- service_worker: 'background/service_worker.js'
6835
- }
6836
- };
6837
- }
6838
- return {
6839
- background: {
6840
- ...manifest.background
6841
- }
6842
- };
6843
- }
6844
- function patch_externally_connectable_patchExternallyConnectable(manifest) {
6845
- if (manifest.externally_connectable && !manifest.externally_connectable.ids) return {
6846
- externally_connectable: {
6847
- ...manifest.externally_connectable,
6848
- ids: [
6849
- ...new Set(manifest.externally_connectable.ids || []),
6850
- '*'
6851
- ]
6852
- }
6853
- };
6854
- if (manifest.externally_connectable && !manifest.externally_connectable.ids) return {
6855
- externally_connectable: {
6856
- ...manifest.externally_connectable,
6857
- ids: [
6858
- '*'
6859
- ]
6860
- }
6861
- };
6862
- return {};
6863
- }
6864
- class ApplyManifestDevDefaults {
6865
- manifestPath;
6866
- browser;
6867
- constructor(options){
6868
- this.manifestPath = options.manifestPath;
6869
- this.browser = options.browser || 'chrome';
6870
- }
6871
- generateManifestPatches(compilation) {
6872
- const canonicalManifest = manifest_getManifestContent(compilation, this.manifestPath);
6873
- const patchedManifest = {
6874
- ...canonicalManifest,
6875
- content_security_policy: 3 === canonicalManifest.manifest_version ? patch_csp_patchV3CSP(canonicalManifest) : patch_csp_patchV2CSP(canonicalManifest),
6876
- ...3 === canonicalManifest.manifest_version ? canonicalManifest.permissions ? {
6877
- permissions: [
6878
- ...new Set([
6879
- "scripting",
6880
- 'tabs',
6881
- 'management',
6882
- ...canonicalManifest.permissions
6883
- ])
6884
- ]
6885
- } : {
6886
- permissions: [
6887
- "scripting",
6888
- 'tabs',
6889
- 'management'
6890
- ]
6891
- } : {},
6892
- ...patch_background_patchBackground(canonicalManifest, this.browser),
6893
- ...patch_externally_connectable_patchExternallyConnectable(canonicalManifest),
6894
- web_accessible_resources: 3 === canonicalManifest.manifest_version ? patch_web_resources_patchWebResourcesV3(canonicalManifest) : patch_web_resources_patchWebResourcesV2(canonicalManifest)
6895
- };
6896
- const source = JSON.stringify(patchedManifest, null, 2);
6897
- const rawSource = new core_sources.RawSource(source);
6898
- if (compilation.getAsset('manifest.json')) compilation.updateAsset('manifest.json', rawSource);
6899
- }
6900
- apply(compiler) {
6901
- if (!compiler?.hooks?.thisCompilation) return;
6902
- compiler.hooks.thisCompilation.tap('run-chromium:apply-manifest-dev-defaults', (compilation)=>{
6903
- if (!compilation?.hooks?.processAssets) return;
6904
- compilation.hooks.processAssets.tap({
6905
- name: 'run-chromium:apply-manifest-dev-defaults',
6906
- stage: core_Compilation.PROCESS_ASSETS_STAGE_REPORT + 100
6907
- }, (_assets)=>{
6908
- if (!this.manifestPath) {
6909
- const errorMessage = 'No manifest.json found in your extension bundle. Unable to patch manifest.json.';
6910
- try {
6911
- const WebpackErrorCtor = compiler?.rspack?.WebpackError;
6912
- compilation.errors.push(WebpackErrorCtor ? new WebpackErrorCtor(`run-chromium: ${errorMessage}`) : new Error(`run-chromium: ${errorMessage}`));
6913
- } catch {}
6914
- return;
6915
- }
6916
- this.generateManifestPatches(compilation);
6917
- });
6918
- });
6919
- }
6920
- }
6921
6424
  class SetupReloadStrategy {
6922
6425
  manifestPath;
6923
6426
  browser;
@@ -6984,10 +6487,6 @@ class SetupReloadStrategy {
6984
6487
  };
6985
6488
  }
6986
6489
  } catch {}
6987
- new ApplyManifestDevDefaults({
6988
- manifestPath: this.manifestPath,
6989
- browser: this.browser
6990
- }).apply(compiler);
6991
6490
  new SetupBackgroundEntry({
6992
6491
  manifestPath: this.manifestPath,
6993
6492
  browser: this.browser
@@ -7143,6 +6642,9 @@ const DEV_SERVER_HOT_MARKERS = [
7143
6642
  '[HMR] Cannot find update. Need to do a full reload!',
7144
6643
  'module.hot.check()'
7145
6644
  ];
6645
+ function contentScriptRetainsDevServerRuntime(source) {
6646
+ return source.includes('@rspack/dev-server/client');
6647
+ }
7146
6648
  function stripDevServerStartupFromContentScript(source) {
7147
6649
  let nextSource = source;
7148
6650
  const startupModuleIds = getStartupModuleIds(source);
@@ -7192,7 +6694,7 @@ function stripStartupRequire(source, moduleId) {
7192
6694
  const startupRequirePattern = new RegExp(`^\\s*__webpack_require__\\(${moduleId}\\);\\n?`, 'm');
7193
6695
  return source.replace(startupRequirePattern, '');
7194
6696
  }
7195
- const strip_content_script_dev_server_runtime_CONTENT_SCRIPT_ASSET = /(^|\/)content_scripts\/content-\d+(?:\.[a-f0-9]+)?\.js$/i;
6697
+ const CONTENT_SCRIPT_ASSET = /(^|\/)content_scripts\/content-\d+(?:\.[a-f0-9]+)?\.js$/i;
7196
6698
  class StripContentScriptDevServerRuntime {
7197
6699
  apply(compiler) {
7198
6700
  compiler.hooks.thisCompilation.tap(StripContentScriptDevServerRuntime.name, (compilation)=>{
@@ -7201,10 +6703,17 @@ class StripContentScriptDevServerRuntime {
7201
6703
  stage: core_Compilation.PROCESS_ASSETS_STAGE_REPORT
7202
6704
  }, ()=>{
7203
6705
  for (const asset of compilation.getAssets()){
7204
- if (!strip_content_script_dev_server_runtime_CONTENT_SCRIPT_ASSET.test(asset.name)) continue;
6706
+ if (!CONTENT_SCRIPT_ASSET.test(asset.name)) continue;
7205
6707
  const originalSource = asset.source.source().toString();
7206
6708
  const strippedSource = stripDevServerStartupFromContentScript(originalSource);
7207
6709
  if (strippedSource !== originalSource) compilation.updateAsset(asset.name, new core_sources.RawSource(strippedSource));
6710
+ if (contentScriptRetainsDevServerRuntime(strippedSource)) {
6711
+ 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.`);
6712
+ warning.name = 'ContentScriptDevServerRuntimeWarning';
6713
+ warning.file = asset.name;
6714
+ compilation.warnings ||= [];
6715
+ compilation.warnings.push(warning);
6716
+ }
7208
6717
  }
7209
6718
  });
7210
6719
  });
@@ -7419,17 +6928,17 @@ function validateLocales(compiler, compilation, manifestPath) {
7419
6928
  pushCompilationError(compiler, compilation, 'LocalesValidationError', defaultLocaleMessagesMissing(defaultLocale), 'manifest.json');
7420
6929
  return false;
7421
6930
  }
6931
+ let defaultLocaleMessages;
7422
6932
  try {
7423
6933
  const content = __rspack_external_fs.readFileSync(messagesJsonPath, 'utf8');
7424
- JSON.parse(content);
7425
- } catch (e) {
6934
+ defaultLocaleMessages = JSON.parse(content);
6935
+ } catch {
7426
6936
  if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(localesValidationDetected(`invalid JSON in _locales/${defaultLocale}/messages.json`));
7427
6937
  pushCompilationError(compiler, compilation, 'LocalesValidationError', invalidMessagesJson(messagesJsonPath), 'manifest.json');
7428
6938
  return false;
7429
6939
  }
7430
6940
  try {
7431
- const content = __rspack_external_fs.readFileSync(messagesJsonPath, 'utf8');
7432
- const dict = JSON.parse(content);
6941
+ const dict = defaultLocaleMessages;
7433
6942
  const collectMsgKeys = (value, acc)=>{
7434
6943
  if ('string' == typeof value) {
7435
6944
  const regex = /__MSG_([a-zA-Z0-9_]+)__/g;
@@ -7480,8 +6989,8 @@ function validateLocales(compiler, compilation, manifestPath) {
7480
6989
  function processLocaleAssets(compiler, compilation, manifestPath) {
7481
6990
  if (compilation.errors.length > 0) return;
7482
6991
  const projectRoot = compiler.options.context || void 0;
7483
- const localesFields = getLocales(manifestPath, projectRoot);
7484
- const discoveredList = getLocales(manifestPath, projectRoot) || [];
6992
+ const localesFields = getLocales(manifestPath, projectRoot) || [];
6993
+ const discoveredList = localesFields;
7485
6994
  const resolvedLocalesRoot = resolveLocalesFolder(manifestPath, projectRoot);
7486
6995
  let emittedCount = 0;
7487
6996
  let missingCount = 0;
@@ -7730,13 +7239,9 @@ function trackJsonDependencies(compilation, manifestPath, includeList) {
7730
7239
  ];
7731
7240
  for (const thisResource of resourceArr)if (thisResource) {
7732
7241
  const abs = __rspack_external_path.isAbsolute(thisResource) ? thisResource : __rspack_external_path.join(manifestDir, thisResource);
7733
- const fileDependencies = new Set(compilation.fileDependencies);
7734
- if (__rspack_external_fs.existsSync(abs)) {
7735
- if (!fileDependencies.has(abs)) {
7736
- fileDependencies.add(abs);
7737
- compilation.fileDependencies.add(abs);
7738
- added++;
7739
- }
7242
+ if (__rspack_external_fs.existsSync(abs) && !compilation.fileDependencies.has(abs)) {
7243
+ compilation.fileDependencies.add(abs);
7244
+ added++;
7740
7245
  }
7741
7246
  }
7742
7247
  }
@@ -7758,13 +7263,6 @@ class JsonPlugin {
7758
7263
  stage: core_Compilation.PROCESS_ASSETS_STAGE_ADDITIONS
7759
7264
  }, ()=>{
7760
7265
  processJsonAssets(compilation, this.manifestPath, this.includeList || {});
7761
- });
7762
- });
7763
- compiler.hooks.thisCompilation.tap('json:module', (compilation)=>{
7764
- compilation.hooks.processAssets.tap({
7765
- name: 'json:module',
7766
- stage: core_Compilation.PROCESS_ASSETS_STAGE_ADDITIONS
7767
- }, ()=>{
7768
7266
  trackJsonDependencies(compilation, this.manifestPath, this.includeList || {});
7769
7267
  });
7770
7268
  });
@@ -7798,6 +7296,30 @@ function iconsDepsTracked(addedCount) {
7798
7296
  function iconsNormalizationSummary(beforeKeys, afterKeys, changedCount) {
7799
7297
  return `Icons include normalization — keys ${pintor.gray(String(beforeKeys.length))} → ${pintor.gray(String(afterKeys.length))}, normalized ${pintor.gray(String(changedCount))}`;
7800
7298
  }
7299
+ function iconValuesToStrings(response) {
7300
+ if (!response) return [];
7301
+ if ('string' == typeof response) return [
7302
+ response
7303
+ ];
7304
+ if (Array.isArray(response)) return response.flatMap((value)=>{
7305
+ if ('string' == typeof value) return [
7306
+ value
7307
+ ];
7308
+ if (value && 'object' == typeof value) return Object.values(value);
7309
+ return [];
7310
+ }).filter((value)=>'string' == typeof value);
7311
+ if ('object' == typeof response) return Object.values(response).filter((value)=>'string' == typeof value);
7312
+ return [];
7313
+ }
7314
+ function normalizeIconIncludeKeys(icons) {
7315
+ const out = {};
7316
+ for (const [key, value] of Object.entries(icons || {}))if ('action' === key) out['action/default_icon'] = value;
7317
+ else if ('browser_action' === key) out['browser_action/default_icon'] = value;
7318
+ else if ('page_action' === key) out['page_action/default_icon'] = value;
7319
+ else if ('sidebar_action' === key) out['sidebar_action/default_icon'] = value;
7320
+ else out[key] = value;
7321
+ return out;
7322
+ }
7801
7323
  function emit_file_reportToCompilation(compilation, message, compiler, opts) {
7802
7324
  const ErrorConstructor = compiler?.rspack?.WebpackError || Error;
7803
7325
  const errObj = new ErrorConstructor(message);
@@ -7827,25 +7349,7 @@ class EmitFile {
7827
7349
  for (const field of Object.entries(iconFields)){
7828
7350
  const [feature, resource] = field;
7829
7351
  if (void 0 === resource) continue;
7830
- const normalizeToStrings = (response)=>{
7831
- if (!response) return [];
7832
- if ('string' == typeof response) return [
7833
- response
7834
- ];
7835
- if (Array.isArray(response)) {
7836
- const flat = response.flatMap((v)=>{
7837
- if ('string' == typeof v) return [
7838
- v
7839
- ];
7840
- if (v && 'object' == typeof v) return Object.values(v);
7841
- return [];
7842
- });
7843
- return flat.filter((s)=>'string' == typeof s);
7844
- }
7845
- if ('object' == typeof response) return Object.values(response).filter((value)=>'string' == typeof value);
7846
- return [];
7847
- };
7848
- const stringEntries = normalizeToStrings(resource);
7352
+ const stringEntries = iconValuesToStrings(resource);
7849
7353
  let emittedCount = 0;
7850
7354
  let underPublicCount = 0;
7851
7355
  let missingCount = 0;
@@ -7954,34 +7458,10 @@ class add_to_file_dependencies_AddToFileDependencies {
7954
7458
  let added = 0;
7955
7459
  for (const field of Object.entries(iconFields)){
7956
7460
  const [, resource] = field;
7957
- const normalizeToStrings = (response)=>{
7958
- if (!response) return [];
7959
- if ('string' == typeof response) return [
7960
- response
7961
- ];
7962
- if (Array.isArray(response)) {
7963
- const flat = response.flatMap((value)=>{
7964
- if ('string' == typeof value) return [
7965
- value
7966
- ];
7967
- if (value && 'object' == typeof value) return Object.values(value);
7968
- return [];
7969
- });
7970
- return flat.filter((s)=>'string' == typeof s);
7971
- }
7972
- if ('object' == typeof response) return Object.values(response).filter((value)=>'string' == typeof value);
7973
- return [];
7974
- };
7975
- const stringEntries = normalizeToStrings(resource);
7976
- for (const entry of stringEntries)if (entry) {
7977
- const fileDependencies = new Set(compilation.fileDependencies);
7978
- if (__rspack_external_fs.existsSync(entry)) {
7979
- if (!fileDependencies.has(entry)) {
7980
- fileDependencies.add(entry);
7981
- compilation.fileDependencies.add(entry);
7982
- added++;
7983
- }
7984
- }
7461
+ const stringEntries = iconValuesToStrings(resource);
7462
+ for (const entry of stringEntries)if (entry && __rspack_external_fs.existsSync(entry) && !compilation.fileDependencies.has(entry)) {
7463
+ compilation.fileDependencies.add(entry);
7464
+ added++;
7985
7465
  }
7986
7466
  }
7987
7467
  if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(iconsDepsTracked(added));
@@ -7989,15 +7469,6 @@ class add_to_file_dependencies_AddToFileDependencies {
7989
7469
  });
7990
7470
  }
7991
7471
  }
7992
- function normalizeIconIncludeKeys(icons) {
7993
- const out = {};
7994
- for (const [key, value] of Object.entries(icons || {}))if ('action' === key) out['action/default_icon'] = value;
7995
- else if ('browser_action' === key) out['browser_action/default_icon'] = value;
7996
- else if ('page_action' === key) out['page_action/default_icon'] = value;
7997
- else if ('sidebar_action' === key) out['sidebar_action/default_icon'] = value;
7998
- else out[key] = value;
7999
- return out;
8000
- }
8001
7472
  class IconsPlugin {
8002
7473
  manifestPath;
8003
7474
  includeList;
@@ -8166,7 +7637,7 @@ function flattenValues(map) {
8166
7637
  return paths;
8167
7638
  }
8168
7639
  function diffArray(prev, next) {
8169
- if (prev.join(',') === next.join(',')) return null;
7640
+ if (prev.length === next.length && prev.every((value, i)=>value === next[i])) return null;
8170
7641
  const maxLen = Math.max(prev.length, next.length);
8171
7642
  let pathBefore;
8172
7643
  let pathAfter;
@@ -8445,16 +7916,18 @@ class CompatibilityPlugin {
8445
7916
  this.browser = options.browser || 'chrome';
8446
7917
  this.polyfill = options.polyfill || false;
8447
7918
  }
8448
- async apply(compiler) {
8449
- if (this.polyfill) {
8450
- if ('firefox' !== this.browser) {
8451
- if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(compatibilityPolyfillEnabled(this.browser, 'webextension-polyfill'));
8452
- new PolyfillPlugin({
8453
- manifestPath: this.manifestPath,
8454
- browser: this.browser || 'chrome'
8455
- }).apply(compiler);
8456
- } else if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(compatibilityPolyfillSkipped('Firefox bundles browser.* APIs', this.browser));
8457
- } else if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(compatibilityPolyfillDisabled(this.browser));
7919
+ apply(compiler) {
7920
+ const isGeckoFamily = 'firefox' === this.browser || 'gecko-based' === this.browser || 'firefox-based' === this.browser;
7921
+ if (this.polyfill) if (isGeckoFamily) {
7922
+ if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(compatibilityPolyfillSkipped('Firefox bundles browser.* APIs', this.browser));
7923
+ } else {
7924
+ if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(compatibilityPolyfillEnabled(this.browser, 'webextension-polyfill'));
7925
+ new PolyfillPlugin({
7926
+ manifestPath: this.manifestPath,
7927
+ browser: this.browser || 'chrome'
7928
+ }).apply(compiler);
7929
+ }
7930
+ else if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(compatibilityPolyfillDisabled(this.browser));
8458
7931
  }
8459
7932
  }
8460
7933
  class WasmPlugin {
@@ -8475,18 +7948,18 @@ class WasmPlugin {
8475
7948
  }
8476
7949
  buildAssetAliases(projectRoot) {
8477
7950
  const aliases = {};
8478
- const addAlias = (request, relativePath)=>{
8479
- const resolved = this.resolveAssetPath(projectRoot, relativePath);
7951
+ const addAlias = (request)=>{
7952
+ const resolved = this.resolveAssetPath(projectRoot, request);
8480
7953
  if (resolved) aliases[request] = resolved;
8481
7954
  };
8482
- addAlias('@ffmpeg/core/dist/esm/ffmpeg-core.js', '@ffmpeg/core/dist/esm/ffmpeg-core.js');
8483
- addAlias('@ffmpeg/core/dist/esm/ffmpeg-core.wasm', '@ffmpeg/core/dist/esm/ffmpeg-core.wasm');
8484
- addAlias('@ffmpeg/core-mt/dist/esm/ffmpeg-core.js', '@ffmpeg/core-mt/dist/esm/ffmpeg-core.js');
8485
- addAlias('@ffmpeg/core-mt/dist/esm/ffmpeg-core.wasm', '@ffmpeg/core-mt/dist/esm/ffmpeg-core.wasm');
8486
- addAlias('@ffmpeg/core-mt/dist/esm/ffmpeg-core.worker.js', '@ffmpeg/core-mt/dist/esm/ffmpeg-core.worker.js');
8487
- addAlias('@imagemagick/magick-wasm/magick.wasm', '@imagemagick/magick-wasm/magick.wasm');
8488
- addAlias('tesseract-wasm/dist/tesseract-worker.js', 'tesseract-wasm/dist/tesseract-worker.js');
8489
- addAlias('tesseract-wasm/dist/tesseract-core.wasm', 'tesseract-wasm/dist/tesseract-core.wasm');
7955
+ addAlias('@ffmpeg/core/dist/esm/ffmpeg-core.js');
7956
+ addAlias('@ffmpeg/core/dist/esm/ffmpeg-core.wasm');
7957
+ addAlias('@ffmpeg/core-mt/dist/esm/ffmpeg-core.js');
7958
+ addAlias('@ffmpeg/core-mt/dist/esm/ffmpeg-core.wasm');
7959
+ addAlias('@ffmpeg/core-mt/dist/esm/ffmpeg-core.worker.js');
7960
+ addAlias('@imagemagick/magick-wasm/magick.wasm');
7961
+ addAlias('tesseract-wasm/dist/tesseract-worker.js');
7962
+ addAlias('tesseract-wasm/dist/tesseract-core.wasm');
8490
7963
  return aliases;
8491
7964
  }
8492
7965
  ensureWasmResolution(compiler, projectRoot) {
@@ -8586,7 +8059,7 @@ class PerfBudgetsPlugin {
8586
8059
  ...BUDGET_BYTES,
8587
8060
  ...this.options.budgets || {}
8588
8061
  };
8589
- compiler.hooks.afterCompile.tap(PerfBudgetsPlugin.name, (compilation)=>{
8062
+ const report = (compilation)=>{
8590
8063
  if (compilation.errors?.length) return;
8591
8064
  const oversized = [];
8592
8065
  const assets = compilation.assets || {};
@@ -8596,7 +8069,7 @@ class PerfBudgetsPlugin {
8596
8069
  const category = categorizeAsset(name);
8597
8070
  if ('ignored' === category) continue;
8598
8071
  const budget = budgets[category];
8599
- if (isFinite(budget)) {
8072
+ if (Number.isFinite(budget)) {
8600
8073
  if (!(size <= budget)) oversized.push({
8601
8074
  name,
8602
8075
  size,
@@ -8612,6 +8085,13 @@ class PerfBudgetsPlugin {
8612
8085
  warning.name = 'PerfBudgetWarning';
8613
8086
  if (!compilation.warnings) compilation.warnings = [];
8614
8087
  compilation.warnings.push(warning);
8088
+ };
8089
+ const REPORT_STAGE = compiler?.rspack?.Compilation?.PROCESS_ASSETS_STAGE_REPORT ?? 5000;
8090
+ compiler.hooks.thisCompilation.tap(PerfBudgetsPlugin.name, (compilation)=>{
8091
+ compilation.hooks.processAssets.tap({
8092
+ name: PerfBudgetsPlugin.name,
8093
+ stage: REPORT_STAGE
8094
+ }, ()=>report(compilation));
8615
8095
  });
8616
8096
  }
8617
8097
  }
@@ -8619,7 +8099,13 @@ var rspack_config_dirname = __rspack_dirname(__rspack_fileURLToPath(import.meta.
8619
8099
  function webpackConfig(projectStructure, devOptions) {
8620
8100
  const { manifestPath } = projectStructure;
8621
8101
  const { packageJsonDir } = getDirs(projectStructure);
8622
- const manifest = filterKeysForThisBrowser(JSON.parse(__rspack_external_fs.readFileSync(manifestPath, 'utf-8')), devOptions.browser);
8102
+ let rawManifest;
8103
+ try {
8104
+ rawManifest = JSON.parse(__rspack_external_fs.readFileSync(manifestPath, 'utf-8'));
8105
+ } catch (error) {
8106
+ throw new Error(manifestInvalidJson(manifestPath, error));
8107
+ }
8108
+ const manifest = filterKeysForThisBrowser(rawManifest, devOptions.browser);
8623
8109
  const primaryExtensionOutputDir = asAbsolute(__rspack_external_path.isAbsolute(devOptions.output.path) ? devOptions.output.path : __rspack_external_path.resolve(packageJsonDir, devOptions.output.path));
8624
8110
  const companionUnpackedExtensionDirs = resolveCompanionExtensionDirs({
8625
8111
  projectRoot: packageJsonDir,
@@ -8673,7 +8159,9 @@ function webpackConfig(projectStructure, devOptions) {
8673
8159
  new SpecialFoldersPlugin({
8674
8160
  manifestPath
8675
8161
  }),
8676
- new PerfBudgetsPlugin()
8162
+ new PerfBudgetsPlugin({
8163
+ budgets: devOptions.perfBudgets
8164
+ })
8677
8165
  ];
8678
8166
  if (devOptions.noBrowser) plugins.push(new PlaywrightPlugin({
8679
8167
  packageJsonDir,
@@ -8699,9 +8187,9 @@ function webpackConfig(projectStructure, devOptions) {
8699
8187
  clean: devOptions.output.clean,
8700
8188
  path: primaryExtensionOutputDir,
8701
8189
  publicPath: '/',
8702
- filename: 'development' === (devOptions.mode || 'development') ? (pathData)=>{
8190
+ filename: 'development' === (devOptions.mode || 'development') && false !== devOptions.hashContentScripts ? (pathData)=>{
8703
8191
  const chunkName = pathData.chunk?.name;
8704
- if ('string' == typeof chunkName && /^content_scripts\/content-\d+$/.test(chunkName)) return `${chunkName}.[fullhash:8].js`;
8192
+ if ('string' == typeof chunkName && /^content_scripts\/content-\d+$/.test(chunkName)) return `${chunkName}.[contenthash:8].js`;
8705
8193
  return '[name].js';
8706
8194
  } : '[name].js',
8707
8195
  hotUpdateChunkFilename: 'hot/[id].[fullhash].hot-update.js',
@@ -8713,7 +8201,9 @@ function webpackConfig(projectStructure, devOptions) {
8713
8201
  },
8714
8202
  watchOptions: {
8715
8203
  ignored: transpilePackageDirs.length > 0 ? /dist|extension-js\/profiles/ : /node_modules|dist|extension-js\/profiles/,
8716
- poll: 1000,
8204
+ ...'true' === process.env.EXTENSION_WATCH_POLL ? {
8205
+ poll: parseInt(String(process.env.EXTENSION_WATCH_POLL_INTERVAL || '1000'), 10)
8206
+ } : {},
8717
8207
  aggregateTimeout: 200
8718
8208
  },
8719
8209
  resolve: {