extension-develop 4.0.30 → 4.0.33

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.
@@ -4,7 +4,7 @@ import { createRequire } from "node:module";
4
4
  import pintor from "pintor";
5
5
  import core, { Compilation as core_Compilation, DefinePlugin, ProvidePlugin, WebpackError as core_WebpackError, rspack, sources as core_sources } from "@rspack/core";
6
6
  import case_sensitive_paths_webpack_plugin from "case-sensitive-paths-webpack-plugin";
7
- import adm_zip from "adm-zip";
7
+ import { zipSync } from "fflate";
8
8
  import ignore from "ignore";
9
9
  import tiny_glob from "tiny-glob";
10
10
  import { pathToFileURL } from "node:url";
@@ -12,7 +12,7 @@ import { filterKeysForThisBrowser as external_browser_extension_manifest_fields_
12
12
  import content_security_policy_parser from "content-security-policy-parser";
13
13
  import node_fs from "node:fs";
14
14
  import node_path from "node:path";
15
- import { debugExtensionsToLoad, package_namespaceObject, getDirs, asAbsolute, browserRunnerDisabled, treeWithDistFilesBrowser, packagingDistributionFiles, toPosixPath, resolveCompanionExtensionDirs, debugContextPath, PlaywrightPlugin, isWebkitBasedBrowser, spacerLine, isGeckoBasedBrowser, messages_ready, CHROMIUM_FAMILY_ALIASES, treeWithSourceAndDistFiles, computeExtensionsToLoad, noCompanionExtensionsResolved, treeWithSourceFiles, bundlerFatalError, bundlerRecompiling, noEntrypointsDetected, GECKO_FAMILY_ALIASES, packagingSourceFiles, debugBrowser, debugOutputPath, manifestInvalidJson, isChromiumBasedBrowser, getSpecialFoldersDataForCompiler } from "./101.mjs";
15
+ import { debugExtensionsToLoad, package_namespaceObject, getDirs, asAbsolute, browserRunnerDisabled, treeWithDistFilesBrowser, packagingDistributionFiles, toPosixPath, resolveCompanionExtensionDirs, debugContextPath, PlaywrightPlugin, isGeckoBasedBrowser, spacerLine, isWebkitBasedBrowser, messages_ready, CHROMIUM_FAMILY_ALIASES, treeWithSourceAndDistFiles, computeExtensionsToLoad, noCompanionExtensionsResolved, treeWithSourceFiles, bundlerFatalError, bundlerRecompiling, noEntrypointsDetected, GECKO_FAMILY_ALIASES, packagingSourceFiles, debugBrowser, debugOutputPath, manifestInvalidJson, isChromiumBasedBrowser, getSpecialFoldersDataForCompiler } from "./101.mjs";
16
16
  import { stripBom, parseJsonSafe } from "./23.mjs";
17
17
  import { isResourceUnderDirs, canonicalizeDir, toResourceKey } from "./93.mjs";
18
18
  import { prefix as messaging_prefix, isDebug } from "./349.mjs";
@@ -246,6 +246,11 @@ class PolyfillPlugin {
246
246
  }
247
247
  }
248
248
  }
249
+ function polyfillSkipReason(browser) {
250
+ if (isGeckoBasedBrowser(String(browser))) return 'Firefox bundles browser.* APIs';
251
+ if (isWebkitBasedBrowser(String(browser))) return 'Safari ships a native promise-based browser.* namespace';
252
+ return null;
253
+ }
249
254
  class CompatibilityPlugin {
250
255
  static name = 'plugin-compatibility';
251
256
  manifestPath;
@@ -257,9 +262,9 @@ class CompatibilityPlugin {
257
262
  this.polyfill = options.polyfill || false;
258
263
  }
259
264
  apply(compiler) {
260
- const isGeckoFamily = isGeckoBasedBrowser(String(this.browser));
261
- if (this.polyfill) if (isGeckoFamily) {
262
- if (isDebug()) console.log(compatibilityPolyfillSkipped('Firefox bundles browser.* APIs', this.browser));
265
+ const skipReason = polyfillSkipReason(this.browser);
266
+ if (this.polyfill) if (skipReason) {
267
+ if (isDebug()) console.log(compatibilityPolyfillSkipped(skipReason, this.browser));
263
268
  } else {
264
269
  if (isDebug()) console.log(compatibilityPolyfillEnabled(this.browser, 'webextension-polyfill'));
265
270
  new PolyfillPlugin({
@@ -671,7 +676,7 @@ function contentSecurityPolicy(manifest) {
671
676
  content_security_policy: manifest.content_security_policy
672
677
  };
673
678
  }
674
- function devtoolsPage(manifest, manifestPath) {
679
+ function devtools_page_devtoolsPage(manifest, manifestPath) {
675
680
  return manifest.devtools_page && {
676
681
  devtools_page: (()=>{
677
682
  const raw = String(manifest.devtools_page);
@@ -805,7 +810,7 @@ function manifestCommon(manifest, manifestPath) {
805
810
  ...backgroundPage(manifest),
806
811
  ...chromeUrlOverrides(manifest, manifestPath),
807
812
  ...content_scripts_contentScripts(manifest, manifestPath),
808
- ...devtoolsPage(manifest, manifestPath),
813
+ ...devtools_page_devtoolsPage(manifest, manifestPath),
809
814
  ...icons_icons(manifest),
810
815
  ...commands_commands(manifest),
811
816
  ...permissions(manifest),
@@ -1001,10 +1006,12 @@ function declarativeNetRequest(manifest) {
1001
1006
  return manifest.declarative_net_request && {
1002
1007
  declarative_net_request: {
1003
1008
  ...manifest.declarative_net_request,
1004
- rule_resources: manifest.declarative_net_request.rule_resources.map((resourceObj)=>({
1005
- ...resourceObj,
1006
- path: resourceObj.path && getFilename(`declarative_net_request/${resourceObj.id}.json`, resourceObj.path)
1007
- }))
1009
+ ...Array.isArray(manifest.declarative_net_request.rule_resources) && {
1010
+ rule_resources: manifest.declarative_net_request.rule_resources.map((resourceObj)=>({
1011
+ ...resourceObj,
1012
+ path: resourceObj.path && getFilename(`declarative_net_request/${resourceObj.id}.json`, resourceObj.path)
1013
+ }))
1014
+ }
1008
1015
  }
1009
1016
  };
1010
1017
  }
@@ -1254,6 +1261,7 @@ class EnvPlugin {
1254
1261
  if (processShim) new ProvidePlugin({
1255
1262
  process: processShim
1256
1263
  }).apply(compiler);
1264
+ const templateVars = buildTemplateVars(combinedVars, this.browser, mode);
1257
1265
  compiler.hooks.thisCompilation.tap('manifest:update-manifest', (compilation)=>{
1258
1266
  compilation.hooks.processAssets.tap({
1259
1267
  name: 'env:module',
@@ -1264,29 +1272,11 @@ class EnvPlugin {
1264
1272
  if (filename.endsWith('.json') || filename.endsWith('.html')) {
1265
1273
  let fileContent = String(compilation.assets[filename]?.source() ?? '');
1266
1274
  const resolveVar = (name)=>{
1267
- if (Object.prototype.hasOwnProperty.call(process.env, name)) {
1268
- const systemValue = process.env[name];
1269
- if ('string' == typeof systemValue) return systemValue;
1270
- }
1271
- if (Object.prototype.hasOwnProperty.call(envVars, name)) {
1272
- const explicitEnvValue = envVars[name];
1273
- if ('string' == typeof explicitEnvValue) return explicitEnvValue;
1274
- }
1275
- if (Object.prototype.hasOwnProperty.call(defaultsVars, name)) {
1276
- const defaultsValue = defaultsVars[name];
1277
- if ('string' == typeof defaultsValue) return defaultsValue;
1278
- }
1279
- const combinedValue = combinedVars[name];
1280
- return 'string' == typeof combinedValue ? combinedValue : `$${name}`;
1275
+ if (Object.prototype.hasOwnProperty.call(templateVars, name)) return templateVars[name];
1276
+ return `$${name}`;
1281
1277
  };
1282
- fileContent = fileContent.replace(/\$EXTENSION_PUBLIC_[A-Z_]+/g, (match)=>{
1283
- const envVarName = match.slice(1);
1284
- return resolveVar(envVarName);
1285
- });
1286
- fileContent = fileContent.replace(/\$EXTENSION_[A-Z_]+/g, (match)=>{
1287
- const envVarName = match.slice(1);
1288
- return resolveVar(envVarName);
1289
- });
1278
+ fileContent = fileContent.replace(/\$EXTENSION_PUBLIC_[A-Z0-9_]+/g, (match)=>resolveVar(match.slice(1)));
1279
+ fileContent = fileContent.replace(/\$EXTENSION_[A-Z0-9_]+/g, (match)=>resolveVar(match.slice(1)));
1290
1280
  compilation.updateAsset(filename, new core_sources.RawSource(fileContent));
1291
1281
  if ('manifest.json' === filename) setCurrentManifestContent(compilation, fileContent);
1292
1282
  }
@@ -1295,6 +1285,17 @@ class EnvPlugin {
1295
1285
  });
1296
1286
  }
1297
1287
  }
1288
+ function buildTemplateVars(combinedVars, browser, mode) {
1289
+ const vars = {};
1290
+ for (const [key, value] of Object.entries(combinedVars))if ('string' == typeof value && key.startsWith('EXTENSION_')) vars[key] = value;
1291
+ const browserValue = String(browser);
1292
+ const modeValue = String(mode);
1293
+ vars.EXTENSION_BROWSER = browserValue;
1294
+ vars.EXTENSION_PUBLIC_BROWSER = browserValue;
1295
+ vars.EXTENSION_MODE = modeValue;
1296
+ vars.EXTENSION_PUBLIC_MODE = modeValue;
1297
+ return vars;
1298
+ }
1298
1299
  function sanitize(input) {
1299
1300
  return input.toLowerCase().replace(/[^a-z0-9 ]/gi, '').trim().replace(/\s+/g, '-');
1300
1301
  }
@@ -1318,6 +1319,46 @@ function resolveManifestName(rawName, manifest, searchRoots, fallback) {
1318
1319
  return fallback;
1319
1320
  }
1320
1321
  const toPosix = (p)=>p.replace(/\\/g, '/');
1322
+ function zipEntryFor(absPath) {
1323
+ const stat = __rspack_external_node_fs_5ea92f0c.statSync(absPath);
1324
+ return [
1325
+ new Uint8Array(__rspack_external_node_fs_5ea92f0c.readFileSync(absPath)),
1326
+ {
1327
+ mtime: stat.mtime,
1328
+ os: 3,
1329
+ attrs: (4095 & stat.mode | 32768) << 16 >>> 0
1330
+ }
1331
+ ];
1332
+ }
1333
+ function writeZipFile(zipPath, entries) {
1334
+ const zippable = {};
1335
+ for (const entry of entries)zippable[toPosix(entry.name)] = zipEntryFor(entry.absPath);
1336
+ __rspack_external_node_fs_5ea92f0c.writeFileSync(zipPath, zipSync(zippable));
1337
+ }
1338
+ function listFilesUnder(root, skipNames) {
1339
+ const out = [];
1340
+ const stack = [
1341
+ ''
1342
+ ];
1343
+ while(stack.length){
1344
+ const relDir = stack.pop();
1345
+ const absDir = __rspack_external_node_path_c5b9b54f.join(root, relDir);
1346
+ let entries = [];
1347
+ try {
1348
+ entries = __rspack_external_node_fs_5ea92f0c.readdirSync(absDir, {
1349
+ withFileTypes: true
1350
+ });
1351
+ } catch {
1352
+ continue;
1353
+ }
1354
+ for (const entry of entries){
1355
+ const rel = relDir ? __rspack_external_node_path_c5b9b54f.join(relDir, entry.name) : entry.name;
1356
+ if (entry.isDirectory()) stack.push(rel);
1357
+ else if (entry.isFile() && !skipNames.has(toPosix(rel))) out.push(rel);
1358
+ }
1359
+ }
1360
+ return out.sort();
1361
+ }
1321
1362
  const COMPANION_DIR = 'extensions';
1322
1363
  function isCompanionExtension(file) {
1323
1364
  const [first] = toPosix(file).split('/');
@@ -1333,10 +1374,12 @@ function isDeniedEnvFile(basename) {
1333
1374
  if (!basename.startsWith('.env')) return false;
1334
1375
  return !basename.endsWith('.example');
1335
1376
  }
1377
+ const STAGING_DIR_PREFIX = '.extension-build-';
1336
1378
  function isDeniedFromSourceZip(file) {
1337
1379
  const posix = toPosix(file);
1338
1380
  const segments = posix.split('/');
1339
1381
  if (segments.some((segment)=>DENIED_SEGMENTS.has(segment))) return true;
1382
+ if (segments.some((segment)=>segment.startsWith(STAGING_DIR_PREFIX))) return true;
1340
1383
  if (isDeniedEnvFile(segments[segments.length - 1])) return true;
1341
1384
  return posix === SESSION_ARTIFACTS_PREFIX || posix.startsWith(`${SESSION_ARTIFACTS_PREFIX}/`);
1342
1385
  }
@@ -1385,27 +1428,28 @@ class ZipPlugin {
1385
1428
  ], __rspack_external_node_path_c5b9b54f.basename(packageJsonDir)));
1386
1429
  const name = `${base}-${manifest.version || '0.0.0'}`;
1387
1430
  if (this.zipData.zipSource) {
1388
- const sourceZip = new adm_zip();
1389
1431
  const files = await getFilesToZip(packageJsonDir);
1390
- files.forEach((file)=>{
1391
- const root = __rspack_external_node_path_c5b9b54f.dirname(file);
1392
- sourceZip.addLocalFile(__rspack_external_node_path_c5b9b54f.join(packageJsonDir, file), '.' === root ? '' : toPosix(root));
1393
- });
1394
1432
  const sourcePath = __rspack_external_node_path_c5b9b54f.join(__rspack_external_node_path_c5b9b54f.dirname(outPath), `${name}-source.zip`);
1395
1433
  if (isDebug()) console.log(packagingSourceFiles(sourcePath));
1396
- sourceZip.writeZip(sourcePath);
1434
+ writeZipFile(sourcePath, files.map((file)=>({
1435
+ name: file,
1436
+ absPath: __rspack_external_node_path_c5b9b54f.join(packageJsonDir, file)
1437
+ })));
1397
1438
  created.push({
1398
1439
  kind: 'source',
1399
1440
  path: sourcePath
1400
1441
  });
1401
1442
  }
1402
1443
  if (this.zipData.zip) {
1403
- const distZip = new adm_zip();
1404
- distZip.addLocalFolder(outPath);
1405
1444
  const zipName = this.zipData.zipFilename ? explicitZipFilename(this.zipData.zipFilename) : `${name}.zip`;
1406
1445
  const distPath = __rspack_external_node_path_c5b9b54f.join(outPath, zipName);
1407
1446
  if (isDebug()) console.log(packagingDistributionFiles(distPath));
1408
- distZip.writeZip(distPath);
1447
+ writeZipFile(distPath, listFilesUnder(outPath, new Set([
1448
+ toPosix(zipName)
1449
+ ])).map((file)=>({
1450
+ name: file,
1451
+ absPath: __rspack_external_node_path_c5b9b54f.join(outPath, file)
1452
+ })));
1409
1453
  created.push({
1410
1454
  kind: 'dist',
1411
1455
  path: distPath
@@ -3544,13 +3588,33 @@ class JsFrameworksPlugin {
3544
3588
  manifestDir,
3545
3589
  ...resolveTranspilePackageDirs(projectPath, this.transpilePackages)
3546
3590
  ]));
3591
+ const expandWithRealpaths = (dirs)=>{
3592
+ const out = new Set();
3593
+ for (const dir of dirs)if (dir) {
3594
+ out.add(dir);
3595
+ try {
3596
+ out.add(__rspack_external_node_fs_5ea92f0c.realpathSync(dir));
3597
+ } catch {}
3598
+ }
3599
+ return Array.from(out);
3600
+ };
3601
+ const addBothPathForms = (set, absPath)=>{
3602
+ set.add(toResourceKey(absPath));
3603
+ try {
3604
+ set.add(toResourceKey(__rspack_external_node_fs_5ea92f0c.realpathSync(absPath)));
3605
+ } catch {}
3606
+ };
3547
3607
  const contentScriptLikePaths = new Set();
3548
- const scriptsDir = toResourceKey(__rspack_external_node_path_c5b9b54f.resolve(projectPath, "scripts"));
3608
+ const scriptsDirs = expandWithRealpaths([
3609
+ __rspack_external_node_path_c5b9b54f.resolve(projectPath, "scripts")
3610
+ ]).map(toResourceKey);
3549
3611
  const isfeatureScriptsContentLike = (resourcePath)=>{
3550
3612
  const normalized = toResourceKey(resourcePath);
3551
3613
  if (contentScriptLikePaths.has(normalized)) return true;
3552
- const relToScripts = __rspack_external_node_path_c5b9b54f.relative(scriptsDir, normalized);
3553
- return !!relToScripts && !relToScripts.startsWith('..') && !__rspack_external_node_path_c5b9b54f.isAbsolute(relToScripts);
3614
+ return scriptsDirs.some((scriptsDir)=>{
3615
+ const relToScripts = __rspack_external_node_path_c5b9b54f.relative(scriptsDir, normalized);
3616
+ return !!relToScripts && !relToScripts.startsWith('..') && !__rspack_external_node_path_c5b9b54f.isAbsolute(relToScripts);
3617
+ });
3554
3618
  };
3555
3619
  const devtool = compiler.options.devtool;
3556
3620
  const wantsSourceMaps = false !== devtool && ('development' === mode || null != devtool);
@@ -3561,13 +3625,13 @@ class JsFrameworksPlugin {
3561
3625
  const contentScripts = Array.isArray(manifest?.content_scripts) ? manifest.content_scripts : [];
3562
3626
  for (const contentScript of contentScripts){
3563
3627
  const jsList = Array.isArray(contentScript?.js) ? contentScript.js : [];
3564
- for (const jsFile of jsList)contentScriptLikePaths.add(toResourceKey(__rspack_external_node_path_c5b9b54f.resolve(manifestDir, jsFile)));
3628
+ for (const jsFile of jsList)addBothPathForms(contentScriptLikePaths, __rspack_external_node_path_c5b9b54f.resolve(manifestDir, jsFile));
3565
3629
  }
3566
3630
  const platformModulePaths = new Set();
3567
3631
  try {
3568
3632
  const browserManifest = external_browser_extension_manifest_fields_filterKeysForThisBrowser(manifest, this.browser);
3569
3633
  const background = browserManifest?.background;
3570
- if (background?.type === 'module' && 'string' == typeof background?.service_worker) platformModulePaths.add(toResourceKey(__rspack_external_node_path_c5b9b54f.resolve(manifestDir, background.service_worker)));
3634
+ if (background?.type === 'module' && 'string' == typeof background?.service_worker) addBothPathForms(platformModulePaths, __rspack_external_node_path_c5b9b54f.resolve(manifestDir, background.service_worker));
3571
3635
  const htmlPages = {
3572
3636
  ...getManifestFieldsData({
3573
3637
  manifestPath: this.manifestPath,
@@ -3575,7 +3639,7 @@ class JsFrameworksPlugin {
3575
3639
  }).html,
3576
3640
  ...getSpecialFoldersDataForCompiler(compiler).pages
3577
3641
  };
3578
- for (const htmlPage of Object.values(htmlPages))if ('string' == typeof htmlPage) for (const moduleScript of getAssetsFromHtml(htmlPage)?.moduleJs || [])platformModulePaths.add(toResourceKey(moduleScript));
3642
+ for (const htmlPage of Object.values(htmlPages))if ('string' == typeof htmlPage) for (const moduleScript of getAssetsFromHtml(htmlPage)?.moduleJs || [])addBothPathForms(platformModulePaths, moduleScript);
3579
3643
  } catch {}
3580
3644
  const maybeInstallReact = await maybeUseReact(projectPath, {
3581
3645
  disableRefresh: 'development' !== mode,
@@ -3587,7 +3651,7 @@ class JsFrameworksPlugin {
3587
3651
  const tsConfigPath = getUserTypeScriptConfigFile(projectPath);
3588
3652
  const tsRoot = tsConfigPath ? __rspack_external_node_path_c5b9b54f.dirname(tsConfigPath) : manifestDir;
3589
3653
  const transpilePackageDirs = swcIncludeDirs.filter((dir)=>dir !== projectPath && dir !== manifestDir);
3590
- const preferTypeScript = !!tsConfigPath || isUsingTypeScript(projectPath);
3654
+ const preferTypeScript = !!tsConfigPath;
3591
3655
  let targets = [
3592
3656
  'chrome >= 100'
3593
3657
  ];
@@ -3622,10 +3686,10 @@ class JsFrameworksPlugin {
3622
3686
  const swcRuleBase = {
3623
3687
  test: /\.(js|cjs|mjs|jsx|mjsx|ts|mts|tsx|mtsx)$/,
3624
3688
  type: "javascript/auto",
3625
- include: Array.from(new Set([
3689
+ include: expandWithRealpaths(Array.from(new Set([
3626
3690
  tsRoot,
3627
3691
  ...swcIncludeDirs
3628
- ])),
3692
+ ]))),
3629
3693
  exclude: [
3630
3694
  (resourcePath)=>{
3631
3695
  const isInNodeModules = /[\\/]node_modules[\\/]/.test(resourcePath);
@@ -3674,10 +3738,10 @@ class JsFrameworksPlugin {
3674
3738
  {
3675
3739
  ...swcRuleBase,
3676
3740
  layer: EXTENSIONJS_CONTENT_SCRIPT_LAYER,
3677
- include: (resourcePath)=>Array.from(new Set([
3741
+ include: (resourcePath)=>expandWithRealpaths(Array.from(new Set([
3678
3742
  tsRoot,
3679
3743
  ...swcIncludeDirs
3680
- ])).some((dir)=>isSubPath(resourcePath, dir)) && isfeatureScriptsContentLike(resourcePath),
3744
+ ]))).some((dir)=>isSubPath(resourcePath, dir)) && isfeatureScriptsContentLike(resourcePath),
3681
3745
  use: {
3682
3746
  ...swcLoaderBase,
3683
3747
  options: {
@@ -3831,12 +3895,14 @@ function categorizeAsset(rawName) {
3831
3895
  if (/(^|\/)content_scripts\//.test(name)) return "content-script";
3832
3896
  if (/(^|\/)background\//.test(name) || /(^|\/)service[-_]?worker\.(js|css|wasm)$/i.test(name)) return 'service-worker';
3833
3897
  for (const dir of PAGE_DIRS)if (new RegExp(`(^|\\/)${dir}\\/`).test(name)) return 'page';
3898
+ if (!name.includes('/') || /\.wasm$/i.test(name)) return 'runtime';
3834
3899
  return 'ignored';
3835
3900
  }
3836
3901
  const BUDGET_BYTES = {
3837
3902
  "content-script": 524288,
3838
3903
  'service-worker': 524288,
3839
3904
  page: 1048576,
3905
+ runtime: 1048576,
3840
3906
  ignored: 1 / 0
3841
3907
  };
3842
3908
  function fmtKiB(bytes) {
@@ -3862,6 +3928,8 @@ function categoryRole(c) {
3862
3928
  return 'service worker / background, wakes from cold each session';
3863
3929
  case 'page':
3864
3930
  return 'UI page, opened on demand';
3931
+ case 'runtime':
3932
+ return 'runtime payload, shipped at the output root';
3865
3933
  default:
3866
3934
  return 'asset';
3867
3935
  }
@@ -7517,7 +7585,7 @@ class SpecialFoldersPlugin {
7517
7585
  });
7518
7586
  });
7519
7587
  const copyIgnore = [
7520
- 'manifest.json'
7588
+ __rspack_external_node_path_c5b9b54f.join(publicDir, 'manifest.json').replace(/\\/g, '/')
7521
7589
  ];
7522
7590
  new rspack.CopyRspackPlugin({
7523
7591
  patterns: [
@@ -7689,12 +7757,30 @@ class WasmPlugin {
7689
7757
  this.manifestPath = options.manifestPath;
7690
7758
  this.mode = options.mode;
7691
7759
  }
7760
+ collectSearchRoots(projectRoot) {
7761
+ const roots = [];
7762
+ const seen = new Set();
7763
+ const addAncestors = (startDir)=>{
7764
+ let current = __rspack_external_node_path_c5b9b54f.resolve(startDir);
7765
+ while(true){
7766
+ if (!seen.has(current)) {
7767
+ seen.add(current);
7768
+ roots.push(current);
7769
+ }
7770
+ const parent = __rspack_external_node_path_c5b9b54f.dirname(current);
7771
+ if (parent === current) break;
7772
+ current = parent;
7773
+ }
7774
+ };
7775
+ addAncestors(projectRoot);
7776
+ addAncestors(process.cwd());
7777
+ return roots;
7778
+ }
7692
7779
  resolveAssetPath(projectRoot, relativePath) {
7693
- const candidates = [
7694
- __rspack_external_node_path_c5b9b54f.join(projectRoot, 'node_modules', relativePath),
7695
- __rspack_external_node_path_c5b9b54f.join(process.cwd(), 'node_modules', relativePath)
7696
- ];
7697
- for (const candidate of candidates)if (__rspack_external_node_fs_5ea92f0c.existsSync(candidate)) return candidate;
7780
+ for (const root of this.collectSearchRoots(projectRoot)){
7781
+ const candidate = __rspack_external_node_path_c5b9b54f.join(root, 'node_modules', relativePath);
7782
+ if (__rspack_external_node_fs_5ea92f0c.existsSync(candidate)) return candidate;
7783
+ }
7698
7784
  return null;
7699
7785
  }
7700
7786
  buildAssetAliases(projectRoot) {
@@ -8672,11 +8758,16 @@ class ThrowIfRecompileIsNeeded {
8672
8758
  this.storeInitialHtmlAssets(htmlFields);
8673
8759
  compiler.hooks.make.tapAsync('html:throw-if-recompile-is-needed', (compilation, done)=>{
8674
8760
  const files = compiler.modifiedFiles || new Set();
8675
- const changedFile = Array.from(files)[0];
8676
- if (changedFile && this.initialHtmlAssets[changedFile]) {
8677
- const isRemoteUrl = (p)=>/^(https?:)?\/\//i.test(p);
8678
- const looksLikePublicRootUrl = (p)=>p.startsWith('/') && !__rspack_external_node_fs_5ea92f0c.existsSync(p);
8679
- const updatedAssets = __rspack_external_node_fs_5ea92f0c.existsSync(changedFile) ? getAssetsFromHtml(changedFile) : void 0;
8761
+ const isRemoteUrl = (p)=>/^(https?:)?\/\//i.test(p);
8762
+ const looksLikePublicRootUrl = (p)=>p.startsWith('/') && !__rspack_external_node_fs_5ea92f0c.existsSync(p);
8763
+ for (const changedFile of files){
8764
+ if (!this.initialHtmlAssets[changedFile]) continue;
8765
+ let updatedAssets;
8766
+ try {
8767
+ updatedAssets = getAssetsFromHtml(changedFile, __rspack_external_node_fs_5ea92f0c.readFileSync(changedFile, 'utf8'));
8768
+ } catch {
8769
+ updatedAssets = void 0;
8770
+ }
8680
8771
  const updatedJsEntries = (updatedAssets?.js || []).filter((p)=>!looksLikePublicRootUrl(p) && !isRemoteUrl(p));
8681
8772
  const updatedCssEntries = (updatedAssets?.css || []).filter((p)=>!looksLikePublicRootUrl(p) && !isRemoteUrl(p));
8682
8773
  const { js, css } = this.initialHtmlAssets[changedFile];
@@ -9591,11 +9682,11 @@ function serverRestartRequiredFromManifestError(fileAdded, fileRemoved) {
9591
9682
  lines.push("Restart the dev server to pick up changes to manifest entrypoints.");
9592
9683
  return lines.join('\n');
9593
9684
  }
9594
- function legacyManifestPathWarning(legacyPath) {
9685
+ function legacyManifestPathWarning(field, legacyPath, modernPath) {
9595
9686
  const lines = [];
9596
- lines.push(`${messaging_prefix('warn')} The manifest uses a deprecated path.`);
9687
+ lines.push(`${messaging_prefix('warn')} The ${pintor.blue(field)} field uses a deprecated scaffold path.`);
9597
9688
  lines.push(`${pintor.gray('PATH')} ${pintor.underline(legacyPath)}`);
9598
- lines.push("Extension.js rewrites it to the standardized folders in the next major.");
9689
+ lines.push(`Point it at ${pintor.underline(modernPath)}, Extension.js already emits the page there.`);
9599
9690
  return lines.join('\n');
9600
9691
  }
9601
9692
  function fatalManifestShapeFixed(field, detail) {
@@ -9865,7 +9956,9 @@ function patchWebResourcesV2(manifest) {
9865
9956
  '/*.gif',
9866
9957
  '/*.webp',
9867
9958
  '/*.ico',
9868
- '/*.avif'
9959
+ '/*.avif',
9960
+ '/*.wasm',
9961
+ '/*.bin'
9869
9962
  ];
9870
9963
  const resources = manifest.web_accessible_resources;
9871
9964
  if (!resources || 0 === resources.length) return defaultResources;
@@ -9892,7 +9985,9 @@ function patchWebResourcesV3(manifest) {
9892
9985
  '/*.gif',
9893
9986
  '/*.webp',
9894
9987
  '/*.ico',
9895
- '/*.avif'
9988
+ '/*.avif',
9989
+ '/*.wasm',
9990
+ '/*.bin'
9896
9991
  ];
9897
9992
  return [
9898
9993
  ...manifest.web_accessible_resources || [],
@@ -10053,45 +10148,131 @@ class EmitManifest {
10053
10148
  });
10054
10149
  }
10055
10150
  }
10151
+ const LEGACY_MANIFEST_PATH_RULES = [
10152
+ {
10153
+ field: 'devtools_page',
10154
+ legacyPath: 'devtools_page/devtools_page.html',
10155
+ modernPath: 'devtools/index.html'
10156
+ },
10157
+ {
10158
+ field: 'options_ui.page',
10159
+ legacyPath: 'options_ui/page.html',
10160
+ modernPath: 'options/index.html'
10161
+ },
10162
+ {
10163
+ field: 'background.page',
10164
+ legacyPath: 'background/page.html',
10165
+ modernPath: 'background/index.html'
10166
+ },
10167
+ {
10168
+ field: 'browser_action.default_popup',
10169
+ legacyPath: 'browser_action/default_popup.html',
10170
+ modernPath: 'action/index.html'
10171
+ },
10172
+ {
10173
+ field: 'page_action.default_popup',
10174
+ legacyPath: 'page_action/default_popup.html',
10175
+ modernPath: 'action/index.html'
10176
+ },
10177
+ {
10178
+ field: 'side_panel.default_path',
10179
+ legacyPath: 'side_panel/default_path.html',
10180
+ modernPath: 'sidebar/index.html'
10181
+ },
10182
+ {
10183
+ field: 'sidebar_action.default_panel',
10184
+ legacyPath: 'sidebar_action/default_panel.html',
10185
+ modernPath: 'sidebar/index.html'
10186
+ }
10187
+ ];
10188
+ function normalizeLegacyPathRef(raw) {
10189
+ return String(raw || '').replace(/\\/g, '/').replace(/^\.\//, '').replace(/^\//, '');
10190
+ }
10191
+ function readField(manifest, field) {
10192
+ if (!manifest || 'object' != typeof manifest || Array.isArray(manifest)) return;
10193
+ let current = manifest;
10194
+ for (const part of field.split('.')){
10195
+ if (!current || 'object' != typeof current || Array.isArray(current) || !(part in current)) return;
10196
+ current = current[part];
10197
+ }
10198
+ return current;
10199
+ }
10200
+ function findLegacyManifestPathHits(manifest) {
10201
+ const hits = [];
10202
+ for (const rule of LEGACY_MANIFEST_PATH_RULES){
10203
+ const value = readField(manifest, rule.field);
10204
+ if ('string' == typeof value && value.trim()) {
10205
+ if (normalizeLegacyPathRef(value) === rule.legacyPath) hits.push({
10206
+ field: rule.field,
10207
+ legacyPath: rule.legacyPath,
10208
+ modernPath: rule.modernPath
10209
+ });
10210
+ }
10211
+ }
10212
+ return hits;
10213
+ }
10056
10214
  class ManifestLegacyWarnings {
10057
10215
  static name = 'manifest:legacy-warnings';
10216
+ reportedHits = new Set();
10058
10217
  apply(compiler) {
10059
- if ('production' === (compiler.options.mode || 'development')) return;
10060
- const legacy = [
10061
- 'devtools_page/devtools_page.html',
10062
- 'options_ui/page.html',
10063
- 'background/page.html',
10064
- 'browser_action/default_popup.html',
10065
- 'page_action/default_popup.html',
10066
- 'side_panel/default_path.html',
10067
- 'sidebar_action/default_panel.html'
10068
- ];
10069
10218
  compiler.hooks.thisCompilation.tap(ManifestLegacyWarnings.name, (compilation)=>{
10070
10219
  compilation.hooks.processAssets.tap({
10071
10220
  name: ManifestLegacyWarnings.name,
10072
10221
  stage: core_Compilation.PROCESS_ASSETS_STAGE_REPORT
10073
10222
  }, ()=>{
10074
- const asset = compilation.getAsset('manifest.json');
10075
- if (!asset) return;
10076
- const text = asset.source.source().toString();
10077
- let count = 0;
10078
- legacy.forEach((needle)=>{
10079
- if (text.includes(needle)) {
10080
- const message = legacyManifestPathWarning(needle);
10081
- humanLine(message);
10082
- const warn = new core_WebpackError(message);
10083
- warn.name = 'ManifestLegacyWarning';
10084
- warn.file = 'manifest.json';
10085
- compilation.warnings.push(warn);
10086
- count++;
10223
+ const original = getOriginalManifestContent(compilation);
10224
+ if (!original) return;
10225
+ const manifest = parseJsonSafe(original);
10226
+ const hits = findLegacyManifestPathHits(manifest);
10227
+ if (0 === hits.length) return;
10228
+ const isDev = 'development' === compiler.options.mode;
10229
+ let printed = 0;
10230
+ for (const hit of hits){
10231
+ const signature = `${hit.field}\0${hit.legacyPath}`;
10232
+ if (isDev) {
10233
+ if (this.reportedHits.has(signature)) continue;
10234
+ this.reportedHits.add(signature);
10087
10235
  }
10088
- });
10089
- if (isDebug()) console.log(manifestLegacyWarningsSummary(count));
10236
+ const message = legacyManifestPathWarning(hit.field, hit.legacyPath, hit.modernPath);
10237
+ humanLine(message);
10238
+ const warn = new core_WebpackError(message);
10239
+ warn.name = 'ManifestLegacyWarning';
10240
+ warn.file = 'manifest.json';
10241
+ compilation.warnings.push(warn);
10242
+ printed++;
10243
+ }
10244
+ if (isDebug()) console.log(manifestLegacyWarningsSummary(printed));
10090
10245
  });
10091
10246
  });
10092
10247
  }
10093
10248
  }
10249
+ function toFileArray(value) {
10250
+ if (!value) return [];
10251
+ return Array.isArray(value) ? value : Array.from(value);
10252
+ }
10094
10253
  const EMITTED_ASSET_REF_PATTERN = /assets\/[A-Za-z0-9._-]+(?:\/[A-Za-z0-9._-]+)*/g;
10254
+ function isExcludedFromWar(fileName) {
10255
+ const name = String(fileName || '');
10256
+ if (!name || 'manifest.json' === name) return true;
10257
+ if (name.endsWith('.js') || name.endsWith('.map')) return true;
10258
+ if (/(^|\/)hot\//.test(name)) return true;
10259
+ return false;
10260
+ }
10261
+ function listEmittedAssetNames(compilation) {
10262
+ if ('function' == typeof compilation.getAssets) try {
10263
+ return compilation.getAssets().map((asset)=>String(asset.name));
10264
+ } catch {}
10265
+ return Object.keys(compilation.assets || {});
10266
+ }
10267
+ function collectReferencedRuntimePayloads(source, emittedAssetNames) {
10268
+ if (!source) return [];
10269
+ const found = new Set();
10270
+ const patternHits = source.match(EMITTED_ASSET_REF_PATTERN) || [];
10271
+ for (const hit of patternHits)if (!isExcludedFromWar(hit)) found.add(hit);
10272
+ const eligible = emittedAssetNames.filter((name)=>!isExcludedFromWar(name)).sort((a, b)=>b.length - a.length);
10273
+ for (const asset of eligible)if (source.includes(asset)) found.add(unixify(asset));
10274
+ return Array.from(found);
10275
+ }
10095
10276
  function forEachStringKey(objectOrMap, callback) {
10096
10277
  if (!objectOrMap) return;
10097
10278
  if (objectOrMap instanceof Map) {
@@ -10134,10 +10315,9 @@ function collectContentScriptEntryImports(compilation, includeList) {
10134
10315
  }
10135
10316
  entry.chunks.forEach((chunk)=>{
10136
10317
  const currentChunk = chunk;
10137
- const chunkFilesArray = Array.isArray(currentChunk.files) ? currentChunk.files : [];
10318
+ const chunkFilesArray = toFileArray(currentChunk.files);
10138
10319
  for(let i = 0; i < chunkFilesArray.length; i++)addFileIfRelevant(chunkFilesArray[i]);
10139
- let chunkAuxFilesArray = [];
10140
- if (Array.isArray(currentChunk.auxiliaryFiles)) chunkAuxFilesArray = currentChunk.auxiliaryFiles;
10320
+ const chunkAuxFilesArray = toFileArray(currentChunk.auxiliaryFiles);
10141
10321
  for(let i = 0; i < chunkAuxFilesArray.length; i++)addFileIfRelevant(chunkAuxFilesArray[i]);
10142
10322
  const modulesArray = Array.from(chunkGraph.getChunkModulesIterable(chunk));
10143
10323
  for(let j = 0; j < modulesArray.length; j++){
@@ -10145,7 +10325,7 @@ function collectContentScriptEntryImports(compilation, includeList) {
10145
10325
  const moduleChunksArray = Array.from(chunkGraph.getModuleChunks(moduleObj));
10146
10326
  for(let k = 0; k < moduleChunksArray.length; k++){
10147
10327
  const mk = moduleChunksArray[k];
10148
- const mkAuxFilesArr = Array.isArray(mk.auxiliaryFiles) ? mk.auxiliaryFiles : [];
10328
+ const mkAuxFilesArr = toFileArray(mk.auxiliaryFiles);
10149
10329
  for(let l = 0; l < mkAuxFilesArr.length; l++)addFileIfRelevant(mkAuxFilesArr[l]);
10150
10330
  }
10151
10331
  const moduleWithBuildInfo = moduleObj;
@@ -10157,20 +10337,21 @@ function collectContentScriptEntryImports(compilation, includeList) {
10157
10337
  addFileIfRelevant(key);
10158
10338
  });
10159
10339
  }
10340
+ const emittedAssetNames = listEmittedAssetNames(compilation);
10160
10341
  for(let i = 0; i < chunkFilesArray.length; i++){
10161
10342
  const chunkFileName = chunkFilesArray[i];
10162
10343
  if (!String(chunkFileName).endsWith('.js')) continue;
10163
10344
  const jsSource = getAssetSource(compilation, chunkFileName);
10164
10345
  if (!jsSource) continue;
10165
- const matchedStrings = jsSource.match(EMITTED_ASSET_REF_PATTERN) || [];
10166
- for(let m = 0; m < matchedStrings.length; m++)addFileIfRelevant(matchedStrings[m]);
10346
+ const referenced = collectReferencedRuntimePayloads(jsSource, emittedAssetNames);
10347
+ for(let m = 0; m < referenced.length; m++)addFileIfRelevant(referenced[m]);
10167
10348
  }
10168
10349
  });
10169
10350
  const logicalJsAssetName = `${entryName}.js`;
10170
10351
  const logicalJsAssetSource = getAssetSource(compilation, logicalJsAssetName);
10171
10352
  if (logicalJsAssetSource) {
10172
- const matchedStrings = logicalJsAssetSource.match(EMITTED_ASSET_REF_PATTERN) || [];
10173
- for(let n = 0; n < matchedStrings.length; n++)addFileIfRelevant(matchedStrings[n]);
10353
+ const referenced = collectReferencedRuntimePayloads(logicalJsAssetSource, listEmittedAssetNames(compilation));
10354
+ for(let n = 0; n < referenced.length; n++)addFileIfRelevant(referenced[n]);
10174
10355
  }
10175
10356
  entryImports[entryName] = Array.from(collectedFilesSet);
10176
10357
  });
@@ -10489,6 +10670,10 @@ function generate_manifest_getAssetSource(compilation, filename) {
10489
10670
  const source = asset.source;
10490
10671
  if (!source) return '';
10491
10672
  if ('string' == typeof source) return source;
10673
+ if ('function' == typeof source) {
10674
+ const out = source();
10675
+ return 'string' == typeof out ? out : '';
10676
+ }
10492
10677
  if ('function' == typeof source.source) {
10493
10678
  const out = source.source();
10494
10679
  return 'string' == typeof out ? out : '';
@@ -10563,22 +10748,28 @@ function generateManifestPatches(compilation, manifestPath, entryImports, browse
10563
10748
  resources: Array.from(g.resources)
10564
10749
  })) : [];
10565
10750
  const webAccessibleResourcesV2 = 2 === canonicalManifest.manifest_version ? Array.from(resolved.v2) : [];
10566
- if (3 === canonicalManifest.manifest_version && Array.isArray(canonicalManifest.content_scripts)) for (const contentScript of canonicalManifest.content_scripts){
10567
- const matches = contentScript.matches || [];
10568
- const normalizedMatches = cleanMatches(matches);
10569
- const jsFiles = Array.isArray(contentScript.js) ? contentScript.js : [];
10570
- for (const jsFile of jsFiles){
10571
- const assetForCache = 'function' == typeof compilation.getAsset ? compilation.getAsset(jsFile) : void 0;
10572
- const cacheKey = assetForCache && 'object' == typeof assetForCache.source ? assetForCache.source : void 0;
10573
- let filtered = cacheKey ? assetScanCache.get(cacheKey) : void 0;
10574
- if (!filtered) {
10575
- const source = generate_manifest_getAssetSource(compilation, jsFile);
10576
- if (!source) continue;
10577
- const found = source.match(EMITTED_ASSET_REF_PATTERN) || [];
10578
- filtered = Array.from(new Set(found.filter((r)=>!r.endsWith('.js') && !r.endsWith('.map')))).sort();
10579
- if (cacheKey) assetScanCache.set(cacheKey, filtered);
10751
+ if (Array.isArray(canonicalManifest.content_scripts)) {
10752
+ const emittedAssetNames = listEmittedAssetNames(compilation);
10753
+ for (const contentScript of canonicalManifest.content_scripts){
10754
+ const matches = contentScript.matches || [];
10755
+ const jsFiles = Array.isArray(contentScript.js) ? contentScript.js : [];
10756
+ const referenced = [];
10757
+ for (const jsFile of jsFiles){
10758
+ const assetForCache = 'function' == typeof compilation.getAsset ? compilation.getAsset(jsFile) : void 0;
10759
+ const cacheKey = assetForCache && 'object' == typeof assetForCache.source ? assetForCache.source : void 0;
10760
+ let filtered = cacheKey ? assetScanCache.get(cacheKey) : void 0;
10761
+ if (!filtered) {
10762
+ const source = generate_manifest_getAssetSource(compilation, jsFile);
10763
+ if (!source) continue;
10764
+ filtered = collectReferencedRuntimePayloads(source, emittedAssetNames);
10765
+ if (cacheKey) assetScanCache.set(cacheKey, filtered);
10766
+ }
10767
+ for (const resource of filtered)referenced.push(resource);
10768
+ }
10769
+ if (0 !== referenced.length) {
10770
+ if (3 === canonicalManifest.manifest_version) mergeIntoV3Group(webAccessibleResourcesV3, cleanMatches(matches), referenced);
10771
+ else for (const resource of referenced)if (!webAccessibleResourcesV2.includes(resource)) webAccessibleResourcesV2.push(resource);
10580
10772
  }
10581
- if (0 !== filtered.length) mergeIntoV3Group(webAccessibleResourcesV3, normalizedMatches, filtered);
10582
10773
  }
10583
10774
  }
10584
10775
  for (const [entryName, resources] of Object.entries(entryImports)){
@@ -11953,6 +12144,7 @@ function patchGeckoBackground(manifest, browser) {
11953
12144
  class UpdateManifest {
11954
12145
  manifestPath;
11955
12146
  browser;
12147
+ reportedFatalFixes = new Set();
11956
12148
  constructor(options){
11957
12149
  this.manifestPath = options.manifestPath;
11958
12150
  this.browser = options.browser || 'chrome';
@@ -12001,7 +12193,13 @@ class UpdateManifest {
12001
12193
  } catch {}
12002
12194
  const sanitized = sanitizeFatalManifestShapes(patchedManifest, __rspack_external_node_path_c5b9b54f.dirname(this.manifestPath));
12003
12195
  patchedManifest = sanitized.manifest;
12196
+ const isDev = 'development' === compiler.options.mode;
12004
12197
  for (const fix of sanitized.fixes){
12198
+ if (isDev) {
12199
+ const signature = `${fix.field}\0${fix.detail}`;
12200
+ if (this.reportedFatalFixes.has(signature)) continue;
12201
+ this.reportedFatalFixes.add(signature);
12202
+ }
12005
12203
  const message = fatalManifestShapeFixed(fix.field, fix.detail);
12006
12204
  humanLine(message);
12007
12205
  const warn = new core_WebpackError(message);
@@ -12547,6 +12745,102 @@ class WebResourcesPlugin {
12547
12745
  }).apply(compiler);
12548
12746
  }
12549
12747
  }
12748
+ const PANELS_CREATE_PATTERN = /panels\s*\.\s*create\s*\(\s*(['"`])(?:(?!\1).)*\1\s*,\s*(['"`])(?:(?!\2).)*\2\s*,\s*(['"`])((?:(?!\3).)*)\3/g;
12749
+ const SCRIPT_SRC_PATTERN = /<script[^>]*\ssrc\s*=\s*["']([^"']+)["']/gi;
12750
+ const RELATIVE_IMPORT_PATTERN = /(?:import\s[^'"]*|import\s*\(\s*|require\s*\(\s*|from\s*)['"](\.{1,2}\/[^'"]+)['"]/g;
12751
+ const discover_devtools_panels_SOURCE_SIBLING_EXTENSIONS = [
12752
+ '.ts',
12753
+ '.mts',
12754
+ '.tsx',
12755
+ '.jsx',
12756
+ '.mjs'
12757
+ ];
12758
+ const MAX_IMPORT_DEPTH = 3;
12759
+ function readIfFile(absPath) {
12760
+ try {
12761
+ if (__rspack_external_node_fs_5ea92f0c.statSync(absPath).isFile()) return __rspack_external_node_fs_5ea92f0c.readFileSync(absPath, 'utf-8');
12762
+ } catch {}
12763
+ }
12764
+ function readScriptSource(absPath) {
12765
+ const direct = readIfFile(absPath);
12766
+ if (void 0 !== direct) return direct;
12767
+ const parsed = __rspack_external_node_path_c5b9b54f.parse(absPath);
12768
+ for (const ext of discover_devtools_panels_SOURCE_SIBLING_EXTENSIONS){
12769
+ const sibling = readIfFile(__rspack_external_node_path_c5b9b54f.join(parsed.dir, parsed.name + ext));
12770
+ if (void 0 !== sibling) return sibling;
12771
+ }
12772
+ }
12773
+ function collectPanelLiterals(source) {
12774
+ const literals = [];
12775
+ for (const match of source.matchAll(PANELS_CREATE_PATTERN)){
12776
+ const literal = String(match[4] || '').trim();
12777
+ if (literal) literals.push(literal);
12778
+ }
12779
+ return literals;
12780
+ }
12781
+ function collectRelativeImports(source) {
12782
+ const specifiers = [];
12783
+ for (const match of source.matchAll(RELATIVE_IMPORT_PATTERN))specifiers.push(match[1]);
12784
+ return specifiers;
12785
+ }
12786
+ function scanScriptGraph(entryAbsPath, found) {
12787
+ const queue = [
12788
+ {
12789
+ file: entryAbsPath,
12790
+ depth: 0
12791
+ }
12792
+ ];
12793
+ const seen = new Set();
12794
+ while(queue.length){
12795
+ const { file, depth } = queue.shift();
12796
+ if (seen.has(file)) continue;
12797
+ seen.add(file);
12798
+ const source = readScriptSource(file);
12799
+ if (void 0 === source) continue;
12800
+ found.push(...collectPanelLiterals(source));
12801
+ if (depth >= MAX_IMPORT_DEPTH) continue;
12802
+ for (const specifier of collectRelativeImports(source)){
12803
+ const resolved = __rspack_external_node_path_c5b9b54f.resolve(__rspack_external_node_path_c5b9b54f.dirname(file), specifier);
12804
+ const withExt = __rspack_external_node_path_c5b9b54f.extname(resolved) ? resolved : `${resolved}.js`;
12805
+ queue.push({
12806
+ file: withExt,
12807
+ depth: depth + 1
12808
+ });
12809
+ }
12810
+ }
12811
+ }
12812
+ function discoverDevtoolsPanelPages(manifestPath) {
12813
+ const projectDir = __rspack_external_node_path_c5b9b54f.dirname(manifestPath);
12814
+ let devtoolsPage = '';
12815
+ try {
12816
+ const manifest = JSON.parse(__rspack_external_node_fs_5ea92f0c.readFileSync(manifestPath, 'utf-8'));
12817
+ if ('string' == typeof manifest?.devtools_page) devtoolsPage = manifest.devtools_page;
12818
+ } catch {}
12819
+ if (!devtoolsPage) return {};
12820
+ const devtoolsHtmlPath = __rspack_external_node_path_c5b9b54f.join(projectDir, devtoolsPage.replace(/^\/+/, ''));
12821
+ const devtoolsHtml = readIfFile(devtoolsHtmlPath);
12822
+ if (void 0 === devtoolsHtml) return {};
12823
+ const literals = [];
12824
+ literals.push(...collectPanelLiterals(devtoolsHtml));
12825
+ for (const match of devtoolsHtml.matchAll(SCRIPT_SRC_PATTERN)){
12826
+ const src = String(match[1] || '');
12827
+ if (/^(https?:)?\/\//i.test(src)) continue;
12828
+ const scriptAbs = src.startsWith('/') ? __rspack_external_node_path_c5b9b54f.join(projectDir, src.slice(1)) : __rspack_external_node_path_c5b9b54f.resolve(__rspack_external_node_path_c5b9b54f.dirname(devtoolsHtmlPath), src);
12829
+ scanScriptGraph(scriptAbs, literals);
12830
+ }
12831
+ const pages = {};
12832
+ for (const literal of literals){
12833
+ const rootRel = literal.replace(/^\.?\/+/, '');
12834
+ if (!rootRel || !/\.html?$/i.test(rootRel)) continue;
12835
+ const absPage = __rspack_external_node_path_c5b9b54f.join(projectDir, rootRel);
12836
+ const relToProject = __rspack_external_node_path_c5b9b54f.relative(projectDir, absPage);
12837
+ if (!relToProject || relToProject.startsWith('..')) continue;
12838
+ if (!__rspack_external_node_fs_5ea92f0c.existsSync(absPage)) continue;
12839
+ const key = rootRel.replace(/\.html?$/i, '').replace(/\\/g, '/');
12840
+ pages[key] = absPage;
12841
+ }
12842
+ return pages;
12843
+ }
12550
12844
  function isCriticalJsonFeatureKey(key) {
12551
12845
  return key.startsWith('declarative_net_request') || 'storage.managed_schema' === key;
12552
12846
  }
@@ -12730,6 +13024,7 @@ class plugin_web_extension_WebExtensionPlugin {
12730
13024
  browser: this.browser,
12731
13025
  includeList: {
12732
13026
  ...manifestFieldsData.html,
13027
+ ...discoverDevtoolsPanelPages(manifestPath),
12733
13028
  ...specialFoldersData.pages
12734
13029
  }
12735
13030
  }).apply(compiler);