extension-develop 4.0.27 → 4.0.28

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 (36) hide show
  1. package/dist/0~dev-server.mjs +76 -14
  2. package/dist/0~rspack-config.mjs +101 -45
  3. package/dist/101.mjs +1 -1
  4. package/dist/839.mjs +3 -2
  5. package/dist/bridge.mjs +1 -1
  6. package/dist/dev-server/control-bridge/controller-client.d.ts +1 -0
  7. package/dist/dev-server/index.d.ts +2 -0
  8. package/dist/extension-js-devtools/chrome/background/service_worker.js +1 -1
  9. package/dist/extension-js-devtools/chrome/content_scripts/content-0.js +2 -2
  10. package/dist/extension-js-devtools/chrome/pages/centralized-logger.css +1 -1
  11. package/dist/extension-js-devtools/chrome/pages/centralized-logger.js +1 -1
  12. package/dist/extension-js-devtools/chrome/pages/welcome.css +1 -1
  13. package/dist/extension-js-devtools/chromium/background/service_worker.js +1 -1
  14. package/dist/extension-js-devtools/chromium/content_scripts/content-0.js +2 -2
  15. package/dist/extension-js-devtools/chromium/pages/centralized-logger.css +1 -1
  16. package/dist/extension-js-devtools/chromium/pages/centralized-logger.js +1 -1
  17. package/dist/extension-js-devtools/chromium/pages/welcome.css +1 -1
  18. package/dist/extension-js-devtools/edge/background/service_worker.js +1 -1
  19. package/dist/extension-js-devtools/edge/content_scripts/content-0.js +2 -2
  20. package/dist/extension-js-devtools/edge/pages/centralized-logger.css +1 -1
  21. package/dist/extension-js-devtools/edge/pages/centralized-logger.js +1 -1
  22. package/dist/extension-js-devtools/edge/pages/welcome.css +1 -1
  23. package/dist/extension-js-devtools/firefox/background/scripts.js +1 -1
  24. package/dist/extension-js-devtools/firefox/content_scripts/content-0.js +2 -2
  25. package/dist/extension-js-devtools/firefox/manifest.json +6 -1
  26. package/dist/extension-js-devtools/firefox/pages/centralized-logger.css +1 -1
  27. package/dist/extension-js-devtools/firefox/pages/centralized-logger.js +1 -1
  28. package/dist/extension-js-devtools/firefox/pages/welcome.css +1 -1
  29. package/dist/extension-js-theme/chrome/manifest.json +20 -5
  30. package/dist/extension-js-theme/chromium/manifest.json +20 -5
  31. package/dist/extension-js-theme/edge/manifest.json +20 -5
  32. package/dist/extension-js-theme/firefox/manifest.json +47 -12
  33. package/dist/plugin-web-extension/feature-manifest/manifest-lib/theme-values.d.ts +1 -0
  34. package/dist/plugin-web-extension/feature-manifest/steps/patch-chromium-theme-colors.d.ts +2 -0
  35. package/dist/types.d.ts +2 -2
  36. package/package.json +1 -1
@@ -13,6 +13,7 @@ import { hasProjectDependency, findNearestProjectManifestDirSync } from "./80.mj
13
13
  import { setupNoBrowserBannerOnFirstDone, webpackConfig, resolveConnectableHost, setupCompilerLifecycleHooks } from "./0~rspack-config.mjs";
14
14
  import { ensureSessionStateInProjectGitignore, logsPath, actionsPath, controlPortFilePath, legacyControlPortFilePath, ensureSessionArtifactsIgnoreFile } from "./494.mjs";
15
15
  import { isDebug } from "./349.mjs";
16
+ import * as __rspack_external_node_os_74b4b876 from "node:os";
16
17
  import * as __rspack_external_node_path_c5b9b54f from "node:path";
17
18
  import * as __rspack_external_node_fs_5ea92f0c from "node:fs";
18
19
  import * as __rspack_external_node_crypto_9ba42079 from "node:crypto";
@@ -285,8 +286,8 @@ class BridgeBroker {
285
286
  this.engine = options.engine;
286
287
  this.ring = options.ring ?? new LogRingBuffer();
287
288
  this.file = options.file;
288
- this.allowControl = options.allowControl ?? false;
289
289
  this.allowEval = options.allowEval ?? false;
290
+ this.allowControl = (options.allowControl ?? false) || this.allowEval;
290
291
  this.controlToken = options.controlToken;
291
292
  this.actions = options.actions;
292
293
  this.authorMode = options.authorMode ?? false;
@@ -907,18 +908,35 @@ function createDiscardWriteStream() {
907
908
  });
908
909
  return stream;
909
910
  }
910
- const guardedManifestDiskWritePaths = new Set();
911
+ const guardedManifestDiskWritePaths = new Map();
911
912
  let isManifestDiskWriteGuardInstalled = false;
913
+ let restoreManifestDiskWriteGuardPatches = null;
912
914
  function hasGuardedManifestDiskPath(filePath) {
913
915
  if ('string' != typeof filePath) return false;
914
916
  const resolvedPath = __rspack_external_node_path_c5b9b54f.resolve(filePath);
915
- for (const guardedPath of guardedManifestDiskWritePaths)if (isSamePath(guardedPath, resolvedPath)) return true;
917
+ for (const guardedPath of guardedManifestDiskWritePaths.keys())if (isSamePath(guardedPath, resolvedPath)) return true;
916
918
  return false;
917
919
  }
918
920
  function suppressManifestOutputWrites(compiler, manifestOutputPath) {
919
921
  const outputFileSystem = compiler?.outputFileSystem;
920
- if (!outputFileSystem || outputFileSystem.__extensionjsManifestWriteGuard) return;
921
- const isManifestPath = (filePath)=>'string' == typeof filePath && isSamePath(filePath, manifestOutputPath);
922
+ if (!outputFileSystem) return ()=>{};
923
+ const resolvedManifestPath = __rspack_external_node_path_c5b9b54f.resolve(manifestOutputPath);
924
+ const alreadyGuardedPaths = outputFileSystem.__extensionjsGuardedManifestPaths;
925
+ if (alreadyGuardedPaths) {
926
+ alreadyGuardedPaths.add(resolvedManifestPath);
927
+ return ()=>{
928
+ alreadyGuardedPaths.delete(resolvedManifestPath);
929
+ };
930
+ }
931
+ const guardedPaths = new Set([
932
+ resolvedManifestPath
933
+ ]);
934
+ outputFileSystem.__extensionjsGuardedManifestPaths = guardedPaths;
935
+ const isManifestPath = (filePath)=>{
936
+ if ('string' != typeof filePath) return false;
937
+ for (const guardedPath of guardedPaths)if (isSamePath(guardedPath, filePath)) return true;
938
+ return false;
939
+ };
922
940
  if ('function' == typeof outputFileSystem.writeFile) {
923
941
  const originalWriteFile = outputFileSystem.writeFile.bind(outputFileSystem);
924
942
  outputFileSystem.writeFile = (filePath, ...args)=>{
@@ -955,12 +973,27 @@ function suppressManifestOutputWrites(compiler, manifestOutputPath) {
955
973
  return originalPromiseWriteFile(filePath, ...args);
956
974
  };
957
975
  }
958
- outputFileSystem.__extensionjsManifestWriteGuard = true;
976
+ return ()=>{
977
+ guardedPaths.delete(resolvedManifestPath);
978
+ };
959
979
  }
960
980
  function installManifestDiskWriteGuard(manifestOutputPath) {
961
981
  const guardKey = __rspack_external_node_path_c5b9b54f.resolve(manifestOutputPath);
962
- guardedManifestDiskWritePaths.add(guardKey);
963
- if (isManifestDiskWriteGuardInstalled) return;
982
+ guardedManifestDiskWritePaths.set(guardKey, (guardedManifestDiskWritePaths.get(guardKey) || 0) + 1);
983
+ let uninstalled = false;
984
+ const uninstall = ()=>{
985
+ if (uninstalled) return;
986
+ uninstalled = true;
987
+ const count = guardedManifestDiskWritePaths.get(guardKey) || 0;
988
+ if (count <= 1) guardedManifestDiskWritePaths.delete(guardKey);
989
+ else guardedManifestDiskWritePaths.set(guardKey, count - 1);
990
+ if (0 === guardedManifestDiskWritePaths.size && restoreManifestDiskWriteGuardPatches) {
991
+ restoreManifestDiskWriteGuardPatches();
992
+ restoreManifestDiskWriteGuardPatches = null;
993
+ isManifestDiskWriteGuardInstalled = false;
994
+ }
995
+ };
996
+ if (isManifestDiskWriteGuardInstalled) return uninstall;
964
997
  const guardedFs = node_fs;
965
998
  const isManifestPath = (filePath)=>hasGuardedManifestDiskPath(filePath);
966
999
  const allowManifestRename = (fromPath, toPath)=>'string' == typeof fromPath && 'string' == typeof toPath && isManifestPath(toPath) && isManifestTempPath(fromPath);
@@ -987,14 +1020,20 @@ function installManifestDiskWriteGuard(manifestOutputPath) {
987
1020
  }
988
1021
  return originalCreateWriteStream(filePath, ...args);
989
1022
  };
1023
+ const writeIntentFlagMask = node_fs.constants.O_WRONLY | node_fs.constants.O_RDWR | node_fs.constants.O_APPEND | node_fs.constants.O_CREAT | node_fs.constants.O_TRUNC;
1024
+ const isWriteIntentOpen = (flags)=>{
1025
+ if ('string' == typeof flags) return /[wa+]/.test(flags);
1026
+ if ('number' == typeof flags) return (flags & writeIntentFlagMask) !== 0;
1027
+ return false;
1028
+ };
990
1029
  const originalOpen = guardedFs.open.bind(guardedFs);
991
1030
  guardedFs.open = (pathLike, flags, ...args)=>{
992
- const nextPath = isManifestPath(pathLike) ? '/dev/null' : pathLike;
1031
+ const nextPath = isManifestPath(pathLike) && isWriteIntentOpen(flags) ? __rspack_external_node_os_74b4b876.devNull : pathLike;
993
1032
  return originalOpen(nextPath, flags, ...args);
994
1033
  };
995
1034
  const originalOpenSync = guardedFs.openSync.bind(guardedFs);
996
1035
  guardedFs.openSync = (pathLike, flags, ...args)=>{
997
- const nextPath = isManifestPath(pathLike) ? '/dev/null' : pathLike;
1036
+ const nextPath = isManifestPath(pathLike) && isWriteIntentOpen(flags) ? __rspack_external_node_os_74b4b876.devNull : pathLike;
998
1037
  return originalOpenSync(nextPath, flags, ...args);
999
1038
  };
1000
1039
  const originalRename = guardedFs.rename.bind(guardedFs);
@@ -1010,14 +1049,26 @@ function installManifestDiskWriteGuard(manifestOutputPath) {
1010
1049
  if (isManifestPath(newPath) && !allowManifestRename(oldPath, newPath)) return;
1011
1050
  return originalRenameSync(oldPath, newPath);
1012
1051
  };
1052
+ let originalPromiseWriteFile;
1013
1053
  if (guardedFs.promises?.writeFile) {
1014
- const originalPromiseWriteFile = guardedFs.promises.writeFile.bind(guardedFs.promises);
1054
+ originalPromiseWriteFile = guardedFs.promises.writeFile.bind(guardedFs.promises);
1015
1055
  guardedFs.promises.writeFile = async (filePath, ...args)=>{
1016
1056
  if (isManifestPath(filePath)) return;
1017
1057
  return originalPromiseWriteFile(filePath, ...args);
1018
1058
  };
1019
1059
  }
1060
+ restoreManifestDiskWriteGuardPatches = ()=>{
1061
+ guardedFs.writeFile = originalWriteFile;
1062
+ guardedFs.writeFileSync = originalWriteFileSync;
1063
+ guardedFs.createWriteStream = originalCreateWriteStream;
1064
+ guardedFs.open = originalOpen;
1065
+ guardedFs.openSync = originalOpenSync;
1066
+ guardedFs.rename = originalRename;
1067
+ guardedFs.renameSync = originalRenameSync;
1068
+ if (originalPromiseWriteFile) guardedFs.promises.writeFile = originalPromiseWriteFile;
1069
+ };
1020
1070
  isManifestDiskWriteGuardInstalled = true;
1071
+ return uninstall;
1021
1072
  }
1022
1073
  async function dev_server_devServer(projectStructure, devOptions) {
1023
1074
  const extendedOptions = devOptions;
@@ -1056,8 +1107,8 @@ async function dev_server_devServer(projectStructure, devOptions) {
1056
1107
  filePath: bridgeLogsAbsPath,
1057
1108
  runId: sessionRunId
1058
1109
  });
1059
- const allowControl = Boolean(extendedOptions.allowControl);
1060
1110
  const allowEval = Boolean(extendedOptions.allowEval);
1111
+ const allowControl = Boolean(extendedOptions.allowControl) || allowEval;
1061
1112
  const authorMode = Boolean(extendedOptions.authorMode) || isDebug();
1062
1113
  const bridgeActionsFile = allowControl ? new ActionsFileWriter({
1063
1114
  filePath: actionsPath(packageJsonDir, browserName)
@@ -1174,8 +1225,8 @@ async function dev_server_devServer(projectStructure, devOptions) {
1174
1225
  const compilerConfig = merge(finalConfig, {});
1175
1226
  const compiler = rspack(compilerConfig);
1176
1227
  const manifestOutputPath = __rspack_external_node_path_c5b9b54f.join(primaryDistPath, 'manifest.json');
1177
- installManifestDiskWriteGuard(manifestOutputPath);
1178
- suppressManifestOutputWrites(compiler, manifestOutputPath);
1228
+ const uninstallManifestGuard = installManifestDiskWriteGuard(manifestOutputPath);
1229
+ const releaseOutputFsGuard = suppressManifestOutputWrites(compiler, manifestOutputPath);
1179
1230
  if (!extendedOptions.browsersPlugin && compiler?.hooks?.watchRun) {
1180
1231
  const changedSources = createChangedSourcesTracker(compiler);
1181
1232
  let isFirstBridgeCompile = true;
@@ -1278,6 +1329,17 @@ async function dev_server_devServer(projectStructure, devOptions) {
1278
1329
  liveReload: true
1279
1330
  };
1280
1331
  const devServer = new RspackDevServer(serverConfig, compiler);
1332
+ if ('function' == typeof devServer.stop) {
1333
+ const originalDevServerStop = devServer.stop.bind(devServer);
1334
+ devServer.stop = async ()=>{
1335
+ try {
1336
+ await originalDevServerStop();
1337
+ } finally{
1338
+ uninstallManifestGuard();
1339
+ releaseOutputFsGuard();
1340
+ }
1341
+ };
1342
+ }
1281
1343
  const START_TIMEOUT_MS = parseInt(String(process.env.EXTENSION_START_TIMEOUT_MS || '30000'), 10);
1282
1344
  let startTimeout;
1283
1345
  try {
@@ -1065,8 +1065,15 @@ function getManifestOverrides(manifestPath, manifest) {
1065
1065
  return JSON.stringify(merged, null, 2);
1066
1066
  }
1067
1067
  const manifest_cjsRequire = createRequire(import.meta.url);
1068
- const INTERNAL_MANIFEST_SOURCE = '__extensionjs_manifest_source__';
1069
- const INTERNAL_MANIFEST_CURRENT_SOURCE = '__extensionjs_manifest_current_source__';
1068
+ const manifestSourceStore = new WeakMap();
1069
+ function manifestSourceEntry(compilation) {
1070
+ let entry = manifestSourceStore.get(compilation);
1071
+ if (!entry) {
1072
+ entry = {};
1073
+ manifestSourceStore.set(compilation, entry);
1074
+ }
1075
+ return entry;
1076
+ }
1070
1077
  function readAssetSource(asset) {
1071
1078
  if (!asset) return '';
1072
1079
  const source = asset.source;
@@ -1082,16 +1089,16 @@ function readAssetSource(asset) {
1082
1089
  return '';
1083
1090
  }
1084
1091
  function setOriginalManifestContent(compilation, source) {
1085
- compilation[INTERNAL_MANIFEST_SOURCE] = source;
1092
+ manifestSourceEntry(compilation).original = source;
1086
1093
  }
1087
1094
  function getOriginalManifestContent(compilation) {
1088
- return compilation[INTERNAL_MANIFEST_SOURCE];
1095
+ return manifestSourceStore.get(compilation)?.original;
1089
1096
  }
1090
1097
  function setCurrentManifestContent(compilation, source) {
1091
- compilation[INTERNAL_MANIFEST_CURRENT_SOURCE] = source;
1098
+ manifestSourceEntry(compilation).current = source;
1092
1099
  }
1093
1100
  function getCurrentManifestContent(compilation) {
1094
- return compilation[INTERNAL_MANIFEST_CURRENT_SOURCE];
1101
+ return manifestSourceStore.get(compilation)?.current;
1095
1102
  }
1096
1103
  function getManifestContent(compilation, manifestPath) {
1097
1104
  const currentManifest = getCurrentManifestContent(compilation);
@@ -10730,6 +10737,15 @@ function collectRequiredManifestFiles(manifest) {
10730
10737
  const backgroundScripts = background?.scripts;
10731
10738
  if (Array.isArray(backgroundScripts)) for (const script of backgroundScripts)addFile(script);
10732
10739
  addFile(manifestObj?.side_panel?.default_path);
10740
+ addFile(manifestObj?.action?.default_popup);
10741
+ addFile(manifestObj?.browser_action?.default_popup);
10742
+ addFile(manifestObj?.page_action?.default_popup);
10743
+ addFile(manifestObj?.options_ui?.page);
10744
+ addFile(manifestObj?.options_page);
10745
+ addFile(manifestObj?.devtools_page);
10746
+ addFile(manifestObj?.chrome_url_overrides?.newtab);
10747
+ addFile(manifestObj?.chrome_url_overrides?.history);
10748
+ addFile(manifestObj?.chrome_url_overrides?.bookmarks);
10733
10749
  const contentScripts = manifestObj?.content_scripts;
10734
10750
  if (Array.isArray(contentScripts)) for (const contentScript of contentScripts){
10735
10751
  const js = contentScript?.js;
@@ -11009,6 +11025,78 @@ function patchChromiumBackground(manifest, browser) {
11009
11025
  }
11010
11026
  };
11011
11027
  }
11028
+ const isChannel = (entry)=>'number' == typeof entry && Number.isInteger(entry) && entry >= 0 && entry <= 255;
11029
+ const isFiniteNumber = (entry)=>'number' == typeof entry && Number.isFinite(entry);
11030
+ function parseHexThemeColor(value) {
11031
+ if ('string' != typeof value) return;
11032
+ const match = /^#([0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/i.exec(value.trim());
11033
+ if (!match) return;
11034
+ const hex = match[1];
11035
+ const digits = hex.length >= 6 ? hex.match(/../g) : hex.split('').map((digit)=>digit + digit);
11036
+ const bytes = digits.map((pair)=>parseInt(pair, 16));
11037
+ if (3 === bytes.length) return bytes;
11038
+ return [
11039
+ ...bytes.slice(0, 3),
11040
+ Math.round(bytes[3] / 255 * 1000) / 1000
11041
+ ];
11042
+ }
11043
+ function colorValueDetail(value) {
11044
+ if (parseHexThemeColor(value)) return;
11045
+ if (!Array.isArray(value) || 3 !== value.length && 4 !== value.length) return 'Chrome only accepts an [R, G, B] or [R, G, B, A] array here.';
11046
+ for (const entry of value.slice(0, 3))if (!isChannel(entry)) return 'Chrome only accepts integer color channels from 0 to 255 here.';
11047
+ if (4 === value.length && !isFiniteNumber(value[3])) return 'Chrome only accepts a numeric alpha channel here.';
11048
+ }
11049
+ function tintValueDetail(value) {
11050
+ if (!Array.isArray(value) || 3 !== value.length || !value.every(isFiniteNumber)) return 'Chrome only accepts a [hue, saturation, lightness] array of 3 numbers here.';
11051
+ }
11052
+ function collectThemeValueIssues(manifest) {
11053
+ const issues = [];
11054
+ const theme = manifest?.theme;
11055
+ if (!theme || 'object' != typeof theme) return issues;
11056
+ const groups = [
11057
+ [
11058
+ 'colors',
11059
+ theme.colors,
11060
+ colorValueDetail
11061
+ ],
11062
+ [
11063
+ 'tints',
11064
+ theme.tints,
11065
+ tintValueDetail
11066
+ ]
11067
+ ];
11068
+ for (const [group, container, detailFor] of groups)if (!(!container || 'object' != typeof container || Array.isArray(container))) for (const [key, value] of Object.entries(container)){
11069
+ const detail = detailFor(value);
11070
+ if (detail) issues.push({
11071
+ field: `theme.${group}.${key}`,
11072
+ detail,
11073
+ value: JSON.stringify(value)
11074
+ });
11075
+ }
11076
+ return issues;
11077
+ }
11078
+ function patchChromiumThemeColors(manifest, browser) {
11079
+ if (!isChromiumBasedBrowser(String(browser))) return manifest;
11080
+ const theme = manifest.theme;
11081
+ if (!theme || 'object' != typeof theme || Array.isArray(theme)) return manifest;
11082
+ const colors = theme.colors;
11083
+ if (!colors || 'object' != typeof colors || Array.isArray(colors)) return manifest;
11084
+ let converted = false;
11085
+ const patchedColors = {};
11086
+ for (const [key, value] of Object.entries(colors)){
11087
+ const rgb = parseHexThemeColor(value);
11088
+ patchedColors[key] = rgb ?? value;
11089
+ if (rgb) converted = true;
11090
+ }
11091
+ if (!converted) return manifest;
11092
+ return {
11093
+ ...manifest,
11094
+ theme: {
11095
+ ...theme,
11096
+ colors: patchedColors
11097
+ }
11098
+ };
11099
+ }
11012
11100
  function patchDevContentScriptManifestPaths(compilation, manifest) {
11013
11101
  if ('development' !== compilation.options.mode) return manifest;
11014
11102
  const cs = manifest.content_scripts;
@@ -11127,6 +11215,7 @@ class UpdateManifest {
11127
11215
  let patchedManifest = buildCanonicalManifest(this.manifestPath, manifest, this.browser);
11128
11216
  patchedManifest = patchGeckoBackground(patchedManifest, this.browser);
11129
11217
  patchedManifest = patchChromiumBackground(patchedManifest, this.browser);
11218
+ patchedManifest = patchChromiumThemeColors(patchedManifest, this.browser);
11130
11219
  const overrides = getManifestOverrides(this.manifestPath, manifest);
11131
11220
  if ('development' === compiler.options.mode) {
11132
11221
  if (patchedManifest.content_scripts) patchedManifest.content_scripts = this.applyDevOverrides(patchedManifest);
@@ -11168,42 +11257,6 @@ class UpdateManifest {
11168
11257
  });
11169
11258
  }
11170
11259
  }
11171
- const isChannel = (entry)=>'number' == typeof entry && Number.isInteger(entry) && entry >= 0 && entry <= 255;
11172
- const isFiniteNumber = (entry)=>'number' == typeof entry && Number.isFinite(entry);
11173
- function colorValueDetail(value) {
11174
- if (!Array.isArray(value) || 3 !== value.length && 4 !== value.length) return 'Chrome only accepts an [R, G, B] or [R, G, B, A] array here.';
11175
- for (const entry of value.slice(0, 3))if (!isChannel(entry)) return 'Chrome only accepts integer color channels from 0 to 255 here.';
11176
- if (4 === value.length && !isFiniteNumber(value[3])) return 'Chrome only accepts a numeric alpha channel here.';
11177
- }
11178
- function tintValueDetail(value) {
11179
- if (!Array.isArray(value) || 3 !== value.length || !value.every(isFiniteNumber)) return 'Chrome only accepts a [hue, saturation, lightness] array of 3 numbers here.';
11180
- }
11181
- function collectThemeValueIssues(manifest) {
11182
- const issues = [];
11183
- const theme = manifest?.theme;
11184
- if (!theme || 'object' != typeof theme) return issues;
11185
- const groups = [
11186
- [
11187
- 'colors',
11188
- theme.colors,
11189
- colorValueDetail
11190
- ],
11191
- [
11192
- 'tints',
11193
- theme.tints,
11194
- tintValueDetail
11195
- ]
11196
- ];
11197
- for (const [group, container, detailFor] of groups)if (!(!container || 'object' != typeof container || Array.isArray(container))) for (const [key, value] of Object.entries(container)){
11198
- const detail = detailFor(value);
11199
- if (detail) issues.push({
11200
- field: `theme.${group}.${key}`,
11201
- detail,
11202
- value: JSON.stringify(value)
11203
- });
11204
- }
11205
- return issues;
11206
- }
11207
11260
  class ValidateThemeValues {
11208
11261
  static name = 'manifest:validate-theme-values';
11209
11262
  manifestPath;
@@ -11730,10 +11783,13 @@ class WebResourcesPlugin {
11730
11783
  function isCriticalJsonFeatureKey(key) {
11731
11784
  return key.startsWith('declarative_net_request') || 'storage.managed_schema' === key;
11732
11785
  }
11786
+ function toComparablePath(value) {
11787
+ return 'string' == typeof value ? value : JSON.stringify(value);
11788
+ }
11733
11789
  function flattenValues(map) {
11734
11790
  const paths = [];
11735
- for (const val of Object.values(map || {}))if (Array.isArray(val)) paths.push(...val.filter(Boolean));
11736
- else if (val) paths.push(val);
11791
+ for (const val of Object.values(map || {}))if (Array.isArray(val)) paths.push(...val.filter(Boolean).map(toComparablePath));
11792
+ else if (val) paths.push(toComparablePath(val));
11737
11793
  return paths;
11738
11794
  }
11739
11795
  function diffArray(prev, next) {
@@ -11786,7 +11842,7 @@ class ManifestFieldsChangeDetector {
11786
11842
  else if (val) scripts.push(val);
11787
11843
  const html = fields.html || {};
11788
11844
  const iconsRaw = fields.icons;
11789
- const icons = iconsRaw ? Array.isArray(iconsRaw) ? iconsRaw : flattenValues(iconsRaw) : [];
11845
+ const icons = iconsRaw ? Array.isArray(iconsRaw) ? iconsRaw.filter(Boolean).map(toComparablePath) : flattenValues(iconsRaw) : [];
11790
11846
  const jsonMap = fields.json || {};
11791
11847
  const json = [];
11792
11848
  for (const [key, val] of Object.entries(jsonMap))if (isCriticalJsonFeatureKey(key)) {
package/dist/101.mjs CHANGED
@@ -634,7 +634,7 @@ async function config_loader_isUsingExperimentalConfig(projectPath) {
634
634
  }
635
635
  return false;
636
636
  }
637
- var package_namespaceObject = /*#__PURE__*/ JSON.parse('{"rE":"4.0.27","El":{"@prefresh/core":"1.5.9","@prefresh/utils":"1.2.1","@rspack/core":"^2.1.1","@rspack/dev-server":"2.1.0","@rspack/plugin-preact-refresh":"2.0.1","@rspack/plugin-react-refresh":"2.0.2","@vue/compiler-sfc":"3.5.26","acorn":"^8.16.0","adm-zip":"^0.6.0","browser-extension-manifest-fields":"^2.2.9","case-sensitive-paths-webpack-plugin":"^2.4.0","content-security-policy-parser":"^0.6.0","dotenv":"^17.2.3","es-module-lexer":"^2.1.0","extension-from-store":"^0.1.1","go-git-it":"^5.1.5","ignore":"^7.0.5","less":"4.6.7","less-loader":"13.0.0","parse5-utilities":"^1.0.0","pintor":"0.3.0","postcss":"8.5.18","postcss-loader":"8.2.1","postcss-preset-env":"11.1.1","postcss-scss":"4.0.9","preact":"10.27.3","prefers-yarn":"2.0.1","react-refresh":"0.18.0","sass-loader":"17.0.0","schema-utils":"^4.3.3","svelte-loader":"3.2.4","tiny-glob":"^0.2.9","vue":"3.5.26","vue-loader":"17.4.2","webextension-polyfill":"^0.12.0","webpack-merge":"^6.0.1","webpack-target-webextension":"^2.1.3","ws":"^8.20.1"}}');
637
+ var package_namespaceObject = /*#__PURE__*/ JSON.parse('{"rE":"4.0.28","El":{"@prefresh/core":"1.5.9","@prefresh/utils":"1.2.1","@rspack/core":"^2.1.1","@rspack/dev-server":"2.1.0","@rspack/plugin-preact-refresh":"2.0.1","@rspack/plugin-react-refresh":"2.0.2","@vue/compiler-sfc":"3.5.26","acorn":"^8.16.0","adm-zip":"^0.6.0","browser-extension-manifest-fields":"^2.2.9","case-sensitive-paths-webpack-plugin":"^2.4.0","content-security-policy-parser":"^0.6.0","dotenv":"^17.2.3","es-module-lexer":"^2.1.0","extension-from-store":"^0.1.1","go-git-it":"^5.1.5","ignore":"^7.0.5","less":"4.6.7","less-loader":"13.0.0","parse5-utilities":"^1.0.0","pintor":"0.3.0","postcss":"8.5.18","postcss-loader":"8.2.1","postcss-preset-env":"11.1.1","postcss-scss":"4.0.9","preact":"10.27.3","prefers-yarn":"2.0.1","react-refresh":"0.18.0","sass-loader":"17.0.0","schema-utils":"^4.3.3","svelte-loader":"3.2.4","tiny-glob":"^0.2.9","vue":"3.5.26","vue-loader":"17.4.2","webextension-polyfill":"^0.12.0","webpack-merge":"^6.0.1","webpack-target-webextension":"^2.1.3","ws":"^8.20.1"}}');
638
638
  function asAbsolute(p) {
639
639
  return __rspack_external_node_path_c5b9b54f.isAbsolute(p) ? p : __rspack_external_node_path_c5b9b54f.resolve(p);
640
640
  }
package/dist/839.mjs CHANGED
@@ -1094,6 +1094,7 @@ async function extensionBuild(pathOrRemoteUrl, buildOptions) {
1094
1094
  compilerConfig.stats = false;
1095
1095
  const mergedOutputPath = 'string' == typeof compilerConfig.output?.path ? __rspack_external_node_path_c5b9b54f.resolve(compilerConfig.output.path) : '';
1096
1096
  const useStagingSwap = mergedOutputPath === __rspack_external_node_path_c5b9b54f.resolve(stagingDistPath);
1097
+ const displayDistPath = useStagingSwap || !mergedOutputPath ? distPath : mergedOutputPath;
1097
1098
  if (!useStagingSwap && mergedOutputPath) try {
1098
1099
  __rspack_external_node_fs_5ea92f0c.rmSync(mergedOutputPath, {
1099
1100
  recursive: true,
@@ -1122,7 +1123,7 @@ async function extensionBuild(pathOrRemoteUrl, buildOptions) {
1122
1123
  return reject(new Error('Build failed: bundler returned invalid stats output (no reliable compilation result).'));
1123
1124
  }
1124
1125
  try {
1125
- printBuildCard(projectStructure.manifestPath, browser, distPath);
1126
+ printBuildCard(projectStructure.manifestPath, browser, displayDistPath);
1126
1127
  if (!silent) {
1127
1128
  const assetsTree = buildAssetsTree(stats);
1128
1129
  if (assetsTree) humanLine(assetsTree);
@@ -1176,7 +1177,7 @@ async function extensionBuild(pathOrRemoteUrl, buildOptions) {
1176
1177
  const warningDetails = buildWarningsDetails((info?.warnings || []).filter((warning)=>!isEmitTimeWarning(warning)));
1177
1178
  if (warningDetails) humanLine(warningDetails);
1178
1179
  }
1179
- const distDisplay = relativeToCwd(distPath) || collapseHomeDir(distPath);
1180
+ const distDisplay = relativeToCwd(displayDistPath) || collapseHomeDir(displayDistPath);
1180
1181
  humanLine(buildComplete(browser, distDisplay, summary.total_bytes));
1181
1182
  for (const artifact of getZipArtifacts(stats.compilation)){
1182
1183
  const artifactPath = useStagingSwap && artifact.path.startsWith(stagingDistPath) ? distPath + artifact.path.slice(stagingDistPath.length) : artifact.path;
package/dist/bridge.mjs CHANGED
@@ -194,7 +194,7 @@ class BridgeController {
194
194
  if (!settled) {
195
195
  settled = true;
196
196
  clearTimeout(connectTimer);
197
- reject(new Error(`control channel refused the controller (code ${code}${reason ? `: ${reason}` : ''}). Is the session started with --allow-control?`));
197
+ reject(new Error(`control channel refused the controller (code ${code}${reason ? `: ${reason}` : ''}). Is the session started with ${this.opts.unlockFlag || '--allow-control'}?`));
198
198
  }
199
199
  this.failAllPending(new Error(`control channel closed (code ${code})`));
200
200
  this.socket = null;
@@ -6,6 +6,7 @@ export interface ControllerOptions {
6
6
  host?: string;
7
7
  path?: string;
8
8
  connectTimeoutMs?: number;
9
+ unlockFlag?: string;
9
10
  }
10
11
  export interface CommandInput {
11
12
  op: CommandOp;
@@ -1,3 +1,5 @@
1
1
  import type { ProjectStructure } from '../lib/project';
2
2
  import type { DevOptions } from '../types';
3
+ export declare function suppressManifestOutputWrites(compiler: unknown, manifestOutputPath: string): () => void;
4
+ export declare function installManifestDiskWriteGuard(manifestOutputPath: string): () => void;
3
5
  export declare function devServer(projectStructure: ProjectStructure, devOptions: DevOptions): Promise<void>;
@@ -1,4 +1,4 @@
1
- (()=>{"use strict";async function e(){try{if(!chrome.management.getAll)return[];return(await new Promise(e=>{chrome.management.getAll(e)})||[]).filter(e=>{let t;return e.id!==chrome.runtime.id&&"igcijhgmihmjbbahdabahfbpffalcfnn"!==e.id&&"development"===e.installType&&"theme"!==e.type&&!0===e.enabled&&!((t=String(e.name||"").toLowerCase()).includes("extension.js built-in developer tools")||t.includes("extension.js theme"))})}catch{return[]}}async function t(){let t=await e();return t[t.length-1]}function r(e,t){let r="chrome://extensions/";chrome.tabs.query({url:r},t=>{t.length>0||chrome.tabs.create({url:r,active:!1},function(t){chrome.tabs.move(t.id,{index:0},()=>{setTimeout(()=>{chrome.tabs.update(e.id,{active:!0})},500)})})})}async function n(){let e,r,n="chrome://extensions/";try{chrome.tabs.query({active:!0,currentWindow:!0},t=>{let r=Array.isArray(t)?t[0]:void 0;r&&"number"==typeof r.id&&(e=r.id)})}catch{console.error("Error querying active tab")}r=await t();let a=String("chrome").toLowerCase(),o=r?.id||`__first_run__:${a}`;chrome.storage.local.get(o,async t=>{let r;if(t?.[o]?.didRun)return;let a=e=>new Promise(t=>{try{let r=chrome.tabs.create(e,e=>{if(chrome.runtime.lastError){console.error("Error creating tab:",chrome.runtime.lastError.message),t(void 0);return}t(e)});r&&"function"==typeof r.then&&r.then(t,()=>t(void 0))}catch(e){console.error("Error creating tab:",e),t(void 0)}});try{let t=chrome.runtime.getURL("pages/welcome.html");1;if(r=await a({url:t,active:!0}),"number"==typeof e)try{chrome.tabs.update(e,{url:n})}catch{console.error("Error updating original active tab")}}catch{r=await a({url:"pages/welcome.html",active:!0})}r&&chrome.storage.local.set({[o]:{didRun:!0}})})}async function a(){try{chrome.tabs.query({active:!0,currentWindow:!0},async e=>{let t=Array.isArray(e)?e[0]:void 0,a="chrome",o=`${a}://extensions/`;if(console.log(`%c
1
+ (()=>{"use strict";async function e(){try{if(!chrome.management.getAll)return[];return(await new Promise(e=>{chrome.management.getAll(e)})||[]).filter(e=>{let t;return e.id!==chrome.runtime.id&&"igcijhgmihmjbbahdabahfbpffalcfnn"!==e.id&&"development"===e.installType&&"theme"!==e.type&&!0===e.enabled&&!((t=String(e.name||"").toLowerCase()).includes("extension.js built-in developer tools")||t.includes("extension.js theme"))})}catch{return[]}}async function t(){let t=await e();return t[t.length-1]}function r(e,t){let r="chrome://extensions/";chrome.tabs.query({url:r},t=>{t.length>0||chrome.tabs.create({url:r,active:!1},function(t){chrome.tabs.move(t.id,{index:0},()=>{setTimeout(()=>{chrome.tabs.update(e.id,{active:!0})},500)})})})}async function n(){let e,r,n="chrome://extensions/";try{chrome.tabs.query({active:!0,currentWindow:!0},t=>{let r=Array.isArray(t)?t[0]:void 0;r&&"number"==typeof r.id&&(e=r.id)})}catch{console.error("Error querying active tab")}r=await t();let a=String("chrome").toLowerCase(),o=r?.id||`__first_run__:${a}`;chrome.storage.local.get(o,async t=>{let r,a=t?.[o];if(a?.didRun)return;let i=e=>new Promise(t=>{try{let r=chrome.tabs.create(e,e=>{if(chrome.runtime.lastError){console.error("Error creating tab:",chrome.runtime.lastError.message),t(void 0);return}t(e)});r&&"function"==typeof r.then&&r.then(t,()=>t(void 0))}catch(e){console.error("Error creating tab:",e),t(void 0)}});try{let t=chrome.runtime.getURL("pages/welcome.html");1;if(r=await i({url:t,active:!0}),"number"==typeof e)try{chrome.tabs.update(e,{url:n})}catch{console.error("Error updating original active tab")}}catch{r=await i({url:"pages/welcome.html",active:!0})}r&&chrome.storage.local.set({[o]:{didRun:!0}})})}async function a(){try{chrome.tabs.query({active:!0,currentWindow:!0},async e=>{let t=Array.isArray(e)?e[0]:void 0,a="chrome",o=`${a}://extensions/`;if(console.log(`%c
2
2
  ██████████████████████████████████████████████████████████
3
3
  ██████████████████████████████████████████████████████████
4
4
  ████████████████████████████ ██████████████████████████