extension-develop 4.0.26 → 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 (55) hide show
  1. package/README.md +5 -1
  2. package/dist/0~dev-server.mjs +81 -19
  3. package/dist/0~rspack-config.mjs +399 -184
  4. package/dist/101.mjs +1099 -972
  5. package/dist/494.mjs +12 -1
  6. package/dist/839.mjs +108 -27
  7. package/dist/bridge.mjs +1 -1
  8. package/dist/command-preview.d.ts +7 -0
  9. package/dist/dev-server/control-bridge/controller-client.d.ts +1 -0
  10. package/dist/dev-server/control-bridge/producer-runtime.d.ts +2 -1
  11. package/dist/dev-server/index.d.ts +2 -0
  12. package/dist/extension-js-devtools/chrome/background/service_worker.js +1 -1
  13. package/dist/extension-js-devtools/chrome/content_scripts/content-0.js +2 -2
  14. package/dist/extension-js-devtools/chrome/pages/centralized-logger.css +1 -1
  15. package/dist/extension-js-devtools/chrome/pages/centralized-logger.js +1 -1
  16. package/dist/extension-js-devtools/chrome/pages/welcome.css +1 -1
  17. package/dist/extension-js-devtools/chromium/background/service_worker.js +1 -1
  18. package/dist/extension-js-devtools/chromium/content_scripts/content-0.js +2 -2
  19. package/dist/extension-js-devtools/chromium/pages/centralized-logger.css +1 -1
  20. package/dist/extension-js-devtools/chromium/pages/centralized-logger.js +1 -1
  21. package/dist/extension-js-devtools/chromium/pages/welcome.css +1 -1
  22. package/dist/extension-js-devtools/edge/background/service_worker.js +1 -1
  23. package/dist/extension-js-devtools/edge/content_scripts/content-0.js +2 -2
  24. package/dist/extension-js-devtools/edge/pages/centralized-logger.css +1 -1
  25. package/dist/extension-js-devtools/edge/pages/centralized-logger.js +1 -1
  26. package/dist/extension-js-devtools/edge/pages/welcome.css +1 -1
  27. package/dist/extension-js-devtools/firefox/background/scripts.js +1 -1
  28. package/dist/extension-js-devtools/firefox/content_scripts/content-0.js +2 -2
  29. package/dist/extension-js-devtools/firefox/manifest.json +6 -1
  30. package/dist/extension-js-devtools/firefox/pages/centralized-logger.css +1 -1
  31. package/dist/extension-js-devtools/firefox/pages/centralized-logger.js +1 -1
  32. package/dist/extension-js-devtools/firefox/pages/welcome.css +1 -1
  33. package/dist/extension-js-theme/chrome/manifest.json +20 -5
  34. package/dist/extension-js-theme/chromium/manifest.json +20 -5
  35. package/dist/extension-js-theme/edge/manifest.json +20 -5
  36. package/dist/extension-js-theme/firefox/manifest.json +47 -12
  37. package/dist/feature-scripts-content-script-wrapper.js +2 -1
  38. package/dist/feature-scripts-content-script-wrapper.mjs +2 -1
  39. package/dist/lib/atomic-dist.d.ts +5 -0
  40. package/dist/lib/config-loader.d.ts +12 -12
  41. package/dist/lib/constants.d.ts +2 -0
  42. package/dist/lib/merge-options.d.ts +67 -0
  43. package/dist/lib/paths.d.ts +1 -1
  44. package/dist/lib/session-paths.d.ts +1 -0
  45. package/dist/plugin-compilation/boring.d.ts +1 -0
  46. package/dist/plugin-compilation/zip.d.ts +2 -0
  47. package/dist/plugin-playwright/index.d.ts +2 -0
  48. package/dist/plugin-web-extension/feature-html/html-lib/utils.d.ts +2 -1
  49. package/dist/plugin-web-extension/feature-json/messages.d.ts +2 -0
  50. package/dist/plugin-web-extension/feature-manifest/manifest-lib/theme-values.d.ts +1 -0
  51. package/dist/plugin-web-extension/feature-manifest/messages.d.ts +1 -0
  52. package/dist/plugin-web-extension/feature-manifest/steps/patch-chromium-theme-colors.d.ts +2 -0
  53. package/dist/plugin-web-extension/feature-web-resources/collect-entry-imports.d.ts +1 -0
  54. package/dist/types.d.ts +26 -5
  55. package/package.json +1 -1
package/README.md CHANGED
@@ -175,7 +175,11 @@ Options accepted by each command. Values shown are typical types or enumerations
175
175
  - browser.chrome | .firefox | .edge | .chromium-based | .gecko-based: start flags, excluded flags, preferences, binaries, profile reuse (persistProfile), and per-browser `extensions`.
176
176
  - extensions: load-only companion extensions (unpacked dirs) loaded alongside your extension in dev/preview/start.
177
177
  - Example: { dir: "./extensions" } loads every "./extensions/\*" folder that contains a manifest.json.
178
- - Precedence when composing options: browser._ → commands._ → CLI flags. CLI flags always win over config defaults.
178
+ - Precedence when composing options (one contract for every command): stock defaults → browser._ → commands._ → CLI flags.
179
+ - Scalars: an unset flag never clobbers config, and an explicit flag (including `false`) always wins.
180
+ - Example: `commands.dev.polyfill: false` turns the polyfill off for the team, and `--polyfill` turns it back on for one run.
181
+ - Lists (`browserFlags`, `excludeBrowserFlags`): concatenate across layers in order (browser, then command, then CLI) and dedupe.
182
+ - Objects (`preferences`): deep-merge, later layers win on key conflict.
179
183
  - Browser key aliases when resolving `browser.*` from `extension.config.*`:
180
184
  - When the runtime asks for `chromium`, `loadBrowserConfig` prefers `browser.chromium` and then falls back to `browser['chromium-based']`.
181
185
  - When the runtime asks for `chromium-based`, it prefers `browser['chromium-based']` and then `browser.chromium`.
@@ -7,12 +7,13 @@ import { RspackDevServer } from "@rspack/dev-server";
7
7
  import { merge } from "webpack-merge";
8
8
  import { WebSocket, WebSocketServer } from "ws";
9
9
  import { classifyReloadFromSources, attachLifecycleStream, readContentScriptCount, humanLine, buildSourceFeatureIndex, createChangedSourcesTracker, createLifecycleStream, dispatchReload } from "./839.mjs";
10
- import { autoExitForceKill, loadCommandConfig, sanitize, extensionJsRunnerError, portInUse, devServerStartTimeout, autoExitTriggered, asAbsolute, shouldWarnPortConflict, isGeckoBasedBrowser, createPlaywrightMetadataWriter, autoExitModeEnabled, getSessionRunId, loadCustomConfig, loadBrowserConfig, getDistPath, resolveCompanionExtensionsConfig, getSpecialFoldersDataForProjectRoot } from "./101.mjs";
10
+ import { DEV_COMMAND_DEFAULTS, autoExitForceKill, loadCommandConfig, sanitize, extensionJsRunnerError, portInUse, devServerStartTimeout, autoExitTriggered, asAbsolute, mergeOptionLayers, shouldWarnPortConflict, isGeckoBasedBrowser, createPlaywrightMetadataWriter, autoExitModeEnabled, getSessionRunId, loadCustomConfig, loadBrowserConfig, getDistPath, resolveCompanionExtensionsConfig, getSpecialFoldersDataForProjectRoot } from "./101.mjs";
11
11
  import { CONTROL_WS_PATH, writePersistedControlPort, writeControlToken, clearControlToken, readPersistedControlPort } from "./887.mjs";
12
12
  import { hasProjectDependency, findNearestProjectManifestDirSync } from "./80.mjs";
13
13
  import { setupNoBrowserBannerOnFirstDone, webpackConfig, resolveConnectableHost, setupCompilerLifecycleHooks } from "./0~rspack-config.mjs";
14
- import { actionsPath, controlPortFilePath, logsPath, legacyControlPortFilePath, ensureSessionArtifactsIgnoreFile } from "./494.mjs";
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;
@@ -1049,14 +1100,15 @@ async function dev_server_devServer(projectStructure, devOptions) {
1049
1100
  const primaryDistPath = getDistPath(asAbsolute(packageJsonDir), browserName);
1050
1101
  const bridgeLogsAbsPath = logsPath(packageJsonDir, browserName);
1051
1102
  ensureSessionArtifactsIgnoreFile(packageJsonDir);
1103
+ ensureSessionStateInProjectGitignore(packageJsonDir);
1052
1104
  const bridgeLogsRelPath = __rspack_external_node_path_c5b9b54f.relative(packageJsonDir, bridgeLogsAbsPath);
1053
1105
  const sessionRunId = getSessionRunId(packageJsonDir, browserName);
1054
1106
  const bridgeLogFile = new LogsFileWriter({
1055
1107
  filePath: bridgeLogsAbsPath,
1056
1108
  runId: sessionRunId
1057
1109
  });
1058
- const allowControl = Boolean(extendedOptions.allowControl);
1059
1110
  const allowEval = Boolean(extendedOptions.allowEval);
1111
+ const allowControl = Boolean(extendedOptions.allowControl) || allowEval;
1060
1112
  const authorMode = Boolean(extendedOptions.authorMode) || isDebug();
1061
1113
  const bridgeActionsFile = allowControl ? new ActionsFileWriter({
1062
1114
  filePath: actionsPath(packageJsonDir, browserName)
@@ -1144,6 +1196,7 @@ async function dev_server_devServer(projectStructure, devOptions) {
1144
1196
  const safeBrowserConfig = sanitize(browserConfig);
1145
1197
  const safeCommandConfig = sanitize(commandConfig);
1146
1198
  const safeDevOptions = sanitize(devOptions);
1199
+ const mergedDevOptions = mergeOptionLayers(DEV_COMMAND_DEFAULTS, safeBrowserConfig, safeCommandConfig, safeDevOptions);
1147
1200
  const specialFoldersData = getSpecialFoldersDataForProjectRoot(packageJsonDir);
1148
1201
  const mergedExtensionsConfig = safeDevOptions.extensions ?? safeCommandConfig.extensions ?? safeBrowserConfig.extensions ?? specialFoldersData.extensions;
1149
1202
  const resolvedExtensionsConfig = await resolveCompanionExtensionsConfig({
@@ -1152,9 +1205,7 @@ async function dev_server_devServer(projectStructure, devOptions) {
1152
1205
  config: mergedExtensionsConfig
1153
1206
  });
1154
1207
  const baseConfig = webpackConfig(projectStructure, {
1155
- ...safeBrowserConfig,
1156
- ...safeCommandConfig,
1157
- ...safeDevOptions,
1208
+ ...mergedDevOptions,
1158
1209
  extensions: resolvedExtensionsConfig,
1159
1210
  browser: devOptions.browser,
1160
1211
  mode: 'development',
@@ -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 {