extension-develop 4.1.18 → 4.1.20

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 (107) hide show
  1. package/dist/672~0.mjs +70 -14
  2. package/dist/832~0.mjs +26 -6
  3. package/dist/840~0.mjs +75 -6
  4. package/dist/938~0.mjs +1 -1
  5. package/dist/950~0.mjs +3 -2
  6. package/dist/command-preview.d.ts +0 -8
  7. package/dist/dev-server/control-bridge/actions-file.d.ts +0 -1
  8. package/dist/dev-server/control-bridge/broker.d.ts +6 -4
  9. package/dist/dev-server/control-bridge/consumer-client.d.ts +0 -10
  10. package/dist/dev-server/control-bridge/contracts.d.ts +1 -43
  11. package/dist/dev-server/control-bridge/logs-file.d.ts +0 -1
  12. package/dist/dev-server/control-bridge/logs-query.d.ts +0 -16
  13. package/dist/dev-server/control-bridge/producer-runtime.d.ts +1 -2
  14. package/dist/dev-server/control-bridge/ws-control-server.d.ts +1 -0
  15. package/dist/dev-server~0.mjs +23 -6
  16. package/dist/extension-js-devtools/chrome/images/icon-128.png +0 -0
  17. package/dist/extension-js-devtools/chrome/images/icon-16.png +0 -0
  18. package/dist/extension-js-devtools/chrome/images/icon-32.png +0 -0
  19. package/dist/extension-js-devtools/chrome/images/icon-48.png +0 -0
  20. package/dist/extension-js-devtools/chrome/manifest.json +4 -1
  21. package/dist/extension-js-devtools/chrome/pages/welcome.css +1 -1
  22. package/dist/extension-js-devtools/chrome/pages/welcome.html +1 -1
  23. package/dist/extension-js-devtools/chrome/pages/welcome.js +2 -20
  24. package/dist/extension-js-devtools/chromium/images/icon-128.png +0 -0
  25. package/dist/extension-js-devtools/chromium/images/icon-16.png +0 -0
  26. package/dist/extension-js-devtools/chromium/images/icon-32.png +0 -0
  27. package/dist/extension-js-devtools/chromium/images/icon-48.png +0 -0
  28. package/dist/extension-js-devtools/chromium/manifest.json +4 -1
  29. package/dist/extension-js-devtools/chromium/pages/welcome.css +1 -1
  30. package/dist/extension-js-devtools/chromium/pages/welcome.html +1 -1
  31. package/dist/extension-js-devtools/chromium/pages/welcome.js +2 -20
  32. package/dist/extension-js-devtools/edge/images/icon-128.png +0 -0
  33. package/dist/extension-js-devtools/edge/images/icon-16.png +0 -0
  34. package/dist/extension-js-devtools/edge/images/icon-32.png +0 -0
  35. package/dist/extension-js-devtools/edge/images/icon-48.png +0 -0
  36. package/dist/extension-js-devtools/edge/manifest.json +4 -2
  37. package/dist/extension-js-devtools/edge/pages/welcome.css +1 -1
  38. package/dist/extension-js-devtools/edge/pages/welcome.html +1 -1
  39. package/dist/extension-js-devtools/edge/pages/welcome.js +2 -20
  40. package/dist/extension-js-devtools/firefox/images/icon-128.png +0 -0
  41. package/dist/extension-js-devtools/firefox/images/icon-16.png +0 -0
  42. package/dist/extension-js-devtools/firefox/images/icon-32.png +0 -0
  43. package/dist/extension-js-devtools/firefox/images/icon-48.png +0 -0
  44. package/dist/extension-js-devtools/firefox/manifest.json +4 -1
  45. package/dist/extension-js-devtools/firefox/pages/welcome.css +1 -1
  46. package/dist/extension-js-devtools/firefox/pages/welcome.html +1 -1
  47. package/dist/extension-js-devtools/firefox/pages/welcome.js +2 -20
  48. package/dist/lib/build-summary.d.ts +0 -11
  49. package/dist/lib/constants.d.ts +1 -0
  50. package/dist/lib/ensure-develop-artifacts.d.ts +0 -7
  51. package/dist/lib/has-dependency.d.ts +0 -5
  52. package/dist/lib/manifest-utils.d.ts +8 -0
  53. package/dist/lib/merge-options.d.ts +0 -40
  54. package/dist/lib/messages.d.ts +1 -1
  55. package/dist/lib/project-manifest.d.ts +0 -1
  56. package/dist/lib/session-paths.d.ts +0 -22
  57. package/dist/plugin-browsers/index.d.ts +0 -35
  58. package/dist/plugin-browsers/safari-dev-plugin.d.ts +4 -0
  59. package/dist/plugin-compatibility/feature-polyfill.d.ts +0 -4
  60. package/dist/plugin-compilation/env.d.ts +1 -5
  61. package/dist/plugin-css/css-lib/dead-url-refs.d.ts +0 -6
  62. package/dist/plugin-css/css-lib/inline-content-script-css.d.ts +0 -15
  63. package/dist/plugin-css/css-lib/resolve-css-asset.d.ts +0 -8
  64. package/dist/plugin-js-frameworks/js-tools/vue.d.ts +1 -0
  65. package/dist/plugin-perf-budgets/index.d.ts +0 -21
  66. package/dist/plugin-playwright/index.d.ts +3 -2
  67. package/dist/plugin-reload/classify-reload.d.ts +0 -4
  68. package/dist/plugin-reload/index.d.ts +1 -19
  69. package/dist/plugin-reload/reload-dispatch.d.ts +6 -3
  70. package/dist/plugin-reload/steps/setup-chunk-loading-target.d.ts +0 -13
  71. package/dist/plugin-special-folders/folder-extensions/types.d.ts +0 -13
  72. package/dist/plugin-special-folders/index.d.ts +0 -9
  73. package/dist/plugin-web-extension/feature-html/html-lib/utils.d.ts +0 -1
  74. package/dist/plugin-web-extension/feature-html/index.d.ts +0 -27
  75. package/dist/plugin-web-extension/feature-icons/index.d.ts +0 -12
  76. package/dist/plugin-web-extension/feature-json/index.d.ts +0 -9
  77. package/dist/plugin-web-extension/feature-locales/index.d.ts +0 -4
  78. package/dist/plugin-web-extension/feature-manifest/index.d.ts +0 -10
  79. package/dist/plugin-web-extension/feature-manifest/manifest-lib/filter-key-edge.d.ts +5 -0
  80. package/dist/plugin-web-extension/feature-manifest/manifest-lib/filter-keys-safari.d.ts +11 -0
  81. package/dist/plugin-web-extension/feature-manifest/manifest-lib/gecko-data-collection.d.ts +0 -12
  82. package/dist/plugin-web-extension/feature-manifest/manifest-lib/legacy-paths.d.ts +0 -13
  83. package/dist/plugin-web-extension/feature-manifest/manifest-lib/sanitize-fatal-shapes.d.ts +0 -36
  84. package/dist/plugin-web-extension/feature-manifest/messages.d.ts +20 -0
  85. package/dist/plugin-web-extension/feature-manifest/steps/apply-dev-defaults-lib/dev-injected-hosts.d.ts +0 -5
  86. package/dist/plugin-web-extension/feature-manifest/steps/patch-war.d.ts +0 -5
  87. package/dist/plugin-web-extension/feature-manifest/steps/patch-webkit-background.d.ts +2 -0
  88. package/dist/plugin-web-extension/feature-manifest/steps/update-manifest.d.ts +1 -0
  89. package/dist/plugin-web-extension/feature-manifest/steps/warn-gecko-unsupported-apis.d.ts +117 -13
  90. package/dist/plugin-web-extension/feature-scripts/index.d.ts +0 -10
  91. package/dist/plugin-web-extension/feature-scripts/steps/native-geturl-import-loader.d.ts +0 -3
  92. package/dist/plugin-web-extension/feature-web-resources/index.d.ts +0 -10
  93. package/dist/plugin-web-extension/feature-web-resources/web-resources-lib/clean-matches.d.ts +0 -6
  94. package/dist/plugin-web-extension/shared/discover-devtools-panels.d.ts +0 -6
  95. package/dist/plugin-web-extension/shared/paths.d.ts +0 -1
  96. package/dist/rspack-config~0.mjs +690 -139
  97. package/dist/types.d.ts +0 -190
  98. package/package.json +3 -2
  99. package/runtime/process-shim.cjs +2 -0
  100. package/dist/extension-js-devtools/chrome/images/logo.png +0 -0
  101. package/dist/extension-js-devtools/chrome/shared/framework.js +0 -1
  102. package/dist/extension-js-devtools/chromium/images/logo.png +0 -0
  103. package/dist/extension-js-devtools/chromium/shared/framework.js +0 -1
  104. package/dist/extension-js-devtools/edge/images/logo.png +0 -0
  105. package/dist/extension-js-devtools/edge/shared/framework.js +0 -1
  106. package/dist/extension-js-devtools/firefox/images/logo.png +0 -0
  107. package/dist/extension-js-devtools/firefox/shared/framework.js +0 -1
package/dist/672~0.mjs CHANGED
@@ -4,14 +4,16 @@ import { isChromiumBasedBrowser, isGeckoBasedBrowser } from "./331~0.mjs";
4
4
  import { parseJsonSafe } from "./731~0.mjs";
5
5
  import { prefix as messaging_prefix } from "./852~0.mjs";
6
6
  import * as __rspack_external_node_fs_1b05aee1 from "node:fs";
7
- function filterKeysForThisBrowser(manifest, browser) {
7
+ const CHROMIUM_VENDOR_PREFIXES = [
8
+ 'chrome',
9
+ 'edge'
10
+ ];
11
+ function classifyPrefixes(browser) {
8
12
  const isSafariTarget = 'safari' === browser || 'webkit-based' === browser || String(browser).includes('webkit');
9
13
  const isChromiumTarget = isChromiumBasedBrowser(String(browser)) || isSafariTarget;
10
14
  const isGeckoTarget = isGeckoBasedBrowser(String(browser));
11
15
  const chromiumPrefixes = new Set([
12
- 'chromium',
13
- 'chrome',
14
- 'edge'
16
+ 'chromium'
15
17
  ]);
16
18
  const geckoPrefixes = new Set([
17
19
  'gecko',
@@ -23,31 +25,85 @@ function filterKeysForThisBrowser(manifest, browser) {
23
25
  ]);
24
26
  const isFamilyPrefix = (prefix)=>isChromiumTarget && chromiumPrefixes.has(prefix) || isGeckoTarget && geckoPrefixes.has(prefix);
25
27
  const isSpecificPrefix = (prefix)=>prefix === browser || isSafariTarget && webkitPrefixes.has(prefix);
28
+ return {
29
+ isChromiumTarget,
30
+ isFamilyPrefix,
31
+ isSpecificPrefix
32
+ };
33
+ }
34
+ function filterKeysForThisBrowser(manifest, browser) {
35
+ const { isFamilyPrefix, isSpecificPrefix } = classifyPrefixes(browser);
26
36
  const resolve = (node)=>{
27
37
  if (Array.isArray(node)) return node.map((item)=>resolve(item));
28
38
  if (node && 'object' == typeof node) {
29
- const result = {};
30
- const familyMatches = {};
31
- const specificMatches = {};
39
+ const result = new Map();
40
+ const familyMatches = new Map();
41
+ const specificMatches = new Map();
32
42
  for (const [key, value] of Object.entries(node)){
33
43
  const indexOfColon = key.indexOf(':');
34
44
  if (-1 === indexOfColon) {
35
- result[key] = resolve(value);
45
+ result.set(key, resolve(value));
36
46
  continue;
37
47
  }
38
48
  const prefix = key.substring(0, indexOfColon);
39
49
  const strippedKey = key.substring(indexOfColon + 1);
40
- if (isSpecificPrefix(prefix)) specificMatches[strippedKey] = resolve(value);
41
- else if (isFamilyPrefix(prefix)) familyMatches[strippedKey] = resolve(value);
50
+ if (isSpecificPrefix(prefix)) specificMatches.set(strippedKey, resolve(value));
51
+ else if (isFamilyPrefix(prefix)) familyMatches.set(strippedKey, resolve(value));
42
52
  }
43
- for (const [strippedKey, value] of Object.entries(familyMatches))result[strippedKey] = value;
44
- for (const [strippedKey, value] of Object.entries(specificMatches))result[strippedKey] = value;
45
- return result;
53
+ for (const [strippedKey, value] of familyMatches)result.set(strippedKey, value);
54
+ for (const [strippedKey, value] of specificMatches)result.set(strippedKey, value);
55
+ return Object.fromEntries(result);
46
56
  }
47
57
  return node;
48
58
  };
49
59
  return resolve(manifest);
50
60
  }
61
+ function findDroppedVendorKeys(manifest, browser) {
62
+ const { isChromiumTarget, isFamilyPrefix, isSpecificPrefix } = classifyPrefixes(browser);
63
+ const found = [];
64
+ if (!isChromiumTarget) return found;
65
+ const vendors = new Set(CHROMIUM_VENDOR_PREFIXES);
66
+ const formerFamily = new Set([
67
+ 'chromium',
68
+ ...vendors
69
+ ]);
70
+ const join = (at, key)=>at ? `${at}.${key}` : key;
71
+ const walk = (node, at)=>{
72
+ if (Array.isArray(node)) {
73
+ for (const [index, item] of node.entries())walk(item, join(at, String(index)));
74
+ return;
75
+ }
76
+ if (!node || 'object' != typeof node) return;
77
+ const lastFormerFamily = new Map();
78
+ const hasSpecific = new Set();
79
+ for (const key of Object.keys(node)){
80
+ const colon = key.indexOf(':');
81
+ if (-1 === colon) continue;
82
+ const prefix = key.substring(0, colon);
83
+ const strippedKey = key.substring(colon + 1);
84
+ if (isSpecificPrefix(prefix)) hasSpecific.add(strippedKey);
85
+ else if (formerFamily.has(prefix)) lastFormerFamily.set(strippedKey, key);
86
+ }
87
+ for (const [key, value] of Object.entries(node)){
88
+ const colon = key.indexOf(':');
89
+ if (-1 === colon) {
90
+ walk(value, join(at, key));
91
+ continue;
92
+ }
93
+ const prefix = key.substring(0, colon);
94
+ const strippedKey = key.substring(colon + 1);
95
+ if (isSpecificPrefix(prefix) || isFamilyPrefix(prefix)) walk(value, join(at, key));
96
+ else if (vendors.has(prefix)) found.push({
97
+ path: join(at, key),
98
+ familyPath: join(at, `chromium:${strippedKey}`),
99
+ vendor: prefix,
100
+ appliedBefore: !hasSpecific.has(strippedKey) && lastFormerFamily.get(strippedKey) === key
101
+ });
102
+ }
103
+ };
104
+ walk(manifest, '');
105
+ return found;
106
+ }
51
107
  const THEME_DISQUALIFYING_KEYS = [
52
108
  'background',
53
109
  "content_scripts",
@@ -187,4 +243,4 @@ function compiledSourceSpelling(assetName, api, literal, emittedPath) {
187
243
  lines.push(`Reference the emitted path: ${pintor.blue(emittedPath)}.`);
188
244
  return lines.join('\n');
189
245
  }
190
- export { compiledSourceSpelling, entrySplitAcrossInitialFiles, fetchedFileDependencyMissing, filterKeysForThisBrowser, getURLDependencyMissing, importScriptsDependencyMissing, injectedCompiledSourceLiteral, injectedFileDependencyMissing, isStaticTheme, isStaticThemeSource, reservedScriptsFolder, runtimeSetSurfaceDependencyMissing, staticImportDependencyMissing };
246
+ export { compiledSourceSpelling, entrySplitAcrossInitialFiles, fetchedFileDependencyMissing, filterKeysForThisBrowser, findDroppedVendorKeys, getURLDependencyMissing, importScriptsDependencyMissing, injectedCompiledSourceLiteral, injectedFileDependencyMissing, isStaticTheme, isStaticThemeSource, reservedScriptsFolder, runtimeSetSurfaceDependencyMissing, staticImportDependencyMissing };
package/dist/832~0.mjs CHANGED
@@ -19,7 +19,7 @@ import * as __rspack_external_node_fs_1b05aee1 from "node:fs";
19
19
  import * as __rspack_external_node_os_4f3c9d58 from "node:os";
20
20
  import * as __rspack_external_node_path_806ed179 from "node:path";
21
21
  import * as __rspack_external_node_vm_ef240610 from "node:vm";
22
- var package_namespaceObject = /*#__PURE__*/ JSON.parse('{"rE":"4.1.18","El":{"@prefresh/core":"1.5.9","@prefresh/utils":"1.2.1","@rspack/core":"^2.2.3","@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","browser-extension-manifest-fields":"^2.3.1","case-sensitive-paths-webpack-plugin":"^2.4.0","content-security-policy-parser":"^0.6.0","cross-spawn":"^7.0.6","dotenv":"^17.2.3","es-module-lexer":"^3.0.2","extension-from-store":"^0.2.5","fflate":"^0.8.3","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.23","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"}}');
22
+ var package_namespaceObject = /*#__PURE__*/ JSON.parse('{"rE":"4.1.20","El":{"@prefresh/core":"1.5.9","@prefresh/utils":"1.2.1","@rspack/core":"^2.2.3","@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","browser-extension-manifest-fields":"^3.0.1","case-sensitive-paths-webpack-plugin":"^2.4.0","content-security-policy-parser":"^0.6.0","cross-spawn":"^7.0.6","dotenv":"^17.2.3","es-module-lexer":"^3.0.2","extension-from-store":"^0.2.5","fflate":"^0.8.3","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.23","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"}}');
23
23
  const preloadedEnvKeys = new Set();
24
24
  function getPreloadedEnvKeys() {
25
25
  return preloadedEnvKeys;
@@ -682,7 +682,8 @@ function createPlaywrightMetadataWriter(options) {
682
682
  }
683
683
  if ('string' == typeof prev.executorAttachedAt) {
684
684
  payload.executorAttachedAt = prev.executorAttachedAt;
685
- payload.runtime = 'attached';
685
+ payload.runtime = 'detached' === prev.runtime ? 'detached' : 'attached';
686
+ if ('string' == typeof prev.executorDetachedAt) payload.executorDetachedAt = prev.executorDetachedAt;
686
687
  }
687
688
  if ('starting' !== status && 'string' == typeof prev.extensionLoadRefusedAt) {
688
689
  const target = payload;
@@ -738,14 +739,25 @@ function createPlaywrightMetadataWriter(options) {
738
739
  compiledAt: null
739
740
  });
740
741
  },
741
- writeShutdown () {
742
+ writeShutdown (message = 'the dev session ended (watch closed)') {
742
743
  if (foreignLiveDevSession) return;
743
744
  try {
744
745
  if (!__rspack_external_node_fs_1b05aee1.existsSync(readyPath)) return;
745
746
  const prev = JSON.parse(__rspack_external_node_fs_1b05aee1.readFileSync(readyPath, 'utf-8'));
746
747
  prev.status = 'stopped';
747
748
  prev.code = 'shutdown';
748
- prev.message = 'the dev session ended (watch closed)';
749
+ prev.message = message;
750
+ prev.ts = nowISO();
751
+ writeJsonAtomic(readyPath, prev);
752
+ } catch {}
753
+ },
754
+ stampExecutorDetached () {
755
+ try {
756
+ if (!__rspack_external_node_fs_1b05aee1.existsSync(readyPath)) return;
757
+ const prev = JSON.parse(__rspack_external_node_fs_1b05aee1.readFileSync(readyPath, 'utf-8'));
758
+ if ('string' != typeof prev.executorAttachedAt) return;
759
+ prev.runtime = 'detached';
760
+ prev.executorDetachedAt = nowISO();
749
761
  prev.ts = nowISO();
750
762
  writeJsonAtomic(readyPath, prev);
751
763
  } catch {}
@@ -754,9 +766,14 @@ function createPlaywrightMetadataWriter(options) {
754
766
  try {
755
767
  if (!__rspack_external_node_fs_1b05aee1.existsSync(readyPath)) return;
756
768
  const prev = JSON.parse(__rspack_external_node_fs_1b05aee1.readFileSync(readyPath, 'utf-8'));
757
- if ('string' == typeof prev.executorAttachedAt) return;
758
- prev.executorAttachedAt = nowISO();
759
769
  prev.runtime = 'attached';
770
+ delete prev.executorDetachedAt;
771
+ if ('string' == typeof prev.executorAttachedAt) {
772
+ prev.ts = nowISO();
773
+ writeJsonAtomic(readyPath, prev);
774
+ return;
775
+ }
776
+ prev.executorAttachedAt = nowISO();
760
777
  if ('string' == typeof prev.extensionLoadRefusedAt) {
761
778
  delete prev.extensionLoadRefusedAt;
762
779
  delete prev.extensionLoadRefusedReason;
@@ -1854,5 +1871,8 @@ async function extensionPreview(pathOrRemoteUrl, previewOptions, browserLauncher
1854
1871
  if (!browserLauncher) throw new Error("extensionPreview requires a browserLauncher callback. The browser launch code has moved to programs/extension/browsers/.");
1855
1872
  await browserLauncher(resolvedOpts);
1856
1873
  metadata.writeReady();
1874
+ process.once('exit', ()=>{
1875
+ metadata.writeShutdown(`the ${metadataCommand} session ended`);
1876
+ });
1857
1877
  }
1858
1878
  export { BUILD_COMMAND_DEFAULTS, DEV_COMMAND_DEFAULTS, PlaywrightPlugin, START_BUILD_DEFAULTS, assertNoManagedDependencyConflicts, autoExitForceKill, autoExitModeEnabled, autoExitTriggered, browserRunnerDisabled, bundlerFatalError, bundlerRecompiling, computeExtensionsToLoad, createPlaywrightMetadataWriter, devServerRestarting, devServerStartTimeout, extensionJsRunnerError, extensionPreview, getPreloadedEnvKeys, getSessionRunId, getSpecialFoldersDataForCompiler, getSpecialFoldersDataForProjectRoot, loadBrowserConfig, loadCommandConfig, loadCustomConfig, loadProjectConfigDefaults, mergeOptionLayers, messages_ready, noEntrypointsDetected, package_namespaceObject, portInUse, publicFolderShadowed, publicMustBeAtProjectRoot, resolveCompanionExtensionDirs, resolveCompanionExtensionsConfig, runnerCleanupError, runnerUncaughtException, runnerUnhandledRejection, sanitize, serverRestartRequiredFromSpecialFolderMessageOnly, shouldWarnPortConflict, spacerLine, specialFolderChangeDetected, specialFoldersSetupSummary, stampReadyDistExtensionId, stampReadyKnownExtensionId, withDarkMode };
package/dist/840~0.mjs CHANGED
@@ -2152,7 +2152,7 @@ async function extensionBuild(pathOrRemoteUrl, buildOptions) {
2152
2152
  if (warningDetails) humanLine(warningDetails);
2153
2153
  }
2154
2154
  for (const line of lintLines)humanLine(line);
2155
- humanLine(buildComplete(browser, distDisplay, summary.total_bytes));
2155
+ humanLine(buildComplete(browser, distDisplay, summary.total_bytes, resolvedMode));
2156
2156
  for (const artifact of getZipArtifacts(stats.compilation)){
2157
2157
  const artifactPath = useStagingSwap && artifact.path.startsWith(stagingDistPath) ? distPath + artifact.path.slice(stagingDistPath.length) : artifact.path;
2158
2158
  const zipDisplay = relativeToCwd(artifactPath) || artifactPath;
@@ -2212,6 +2212,9 @@ function viaBroker(broker, instruction) {
2212
2212
  function formatReloadingLine(label) {
2213
2213
  return `${messaging_prefix('info')} Reloading ${label}…`;
2214
2214
  }
2215
+ function formatQueuedReloadLine(label) {
2216
+ return `${messaging_prefix('info')} Queued ${label} for the extension to apply when it reconnects.`;
2217
+ }
2215
2218
  async function dispatchReload(instruction, executor) {
2216
2219
  if (!instruction) return;
2217
2220
  if ('true' === process.env.EXTENSION_NO_RELOAD) return;
@@ -2221,8 +2224,11 @@ async function dispatchReload(instruction, executor) {
2221
2224
  if (instruction.label) console.log(formatReloadingLine(instruction.label));
2222
2225
  return;
2223
2226
  }
2224
- const warning = executor.broker.undeliveredReloadWarning?.();
2225
- if (warning) console.warn(warning);
2227
+ const warning = executor.broker.undeliveredReloadWarning?.(executor.producerRestartExpected ? {
2228
+ producerRestartExpected: true
2229
+ } : void 0);
2230
+ if (warning) return void console.warn(warning);
2231
+ if (executor.producerRestartExpected && instruction.label) console.log(formatQueuedReloadLine(instruction.label));
2226
2232
  }
2227
2233
  }
2228
2234
  function isForcedFullPath(normalized) {
@@ -2674,6 +2680,43 @@ class BrowsersPlugin {
2674
2680
  });
2675
2681
  }
2676
2682
  }
2683
+ function union(previous, next) {
2684
+ return [
2685
+ ...new Set([
2686
+ ...previous || [],
2687
+ ...next || []
2688
+ ])
2689
+ ].sort();
2690
+ }
2691
+ function reloadSurvivingPackage(instruction) {
2692
+ if (!instruction) return;
2693
+ if ("content-scripts" === instruction.type || 'page' === instruction.type) return instruction;
2694
+ const entries = instruction.changedContentScriptEntries || [];
2695
+ if (0 === entries.length) return;
2696
+ return {
2697
+ ...instruction,
2698
+ type: "content-scripts",
2699
+ label: formatReloadContextLabel("content_script", instruction.changedAssets || [])
2700
+ };
2701
+ }
2702
+ function mergeInstructions(previous, next) {
2703
+ if (!previous) return next;
2704
+ if (!next) return previous;
2705
+ const entries = union(previous.changedContentScriptEntries, next.changedContentScriptEntries);
2706
+ const scriptFiles = union(previous.changedScriptFiles, next.changedScriptFiles);
2707
+ if (0 === entries.length) return scriptFiles.length > 0 ? {
2708
+ ...next,
2709
+ changedScriptFiles: scriptFiles
2710
+ } : next;
2711
+ const base = "content-scripts" === next.type ? next : previous;
2712
+ return {
2713
+ ...base,
2714
+ changedContentScriptEntries: entries,
2715
+ ...scriptFiles.length > 0 ? {
2716
+ changedScriptFiles: scriptFiles
2717
+ } : {}
2718
+ };
2719
+ }
2677
2720
  class SafariDevPlugin {
2678
2721
  packager;
2679
2722
  static name = 'safari-dev';
@@ -2683,23 +2726,45 @@ class SafariDevPlugin {
2683
2726
  active = false;
2684
2727
  pending = null;
2685
2728
  idleWaiters = [];
2729
+ reloadBroker;
2686
2730
  constructor(packager){
2687
2731
  this.packager = packager;
2688
2732
  }
2733
+ setReloadBroker(broker) {
2734
+ this.reloadBroker = broker;
2735
+ }
2689
2736
  apply(compiler) {
2737
+ const changedSources = compiler.hooks?.watchRun ? createChangedSourcesTracker(compiler) : void 0;
2690
2738
  compiler.hooks.done.tapPromise(SafariDevPlugin.name, async (stats)=>{
2691
2739
  const compilation = stats.compilation;
2692
2740
  const hasErrors = compilation.errors && compilation.errors.length > 0;
2693
2741
  if (hasErrors) return void this.emitter.emit('error', {
2694
2742
  errors: compilation.errors.map((e)=>'string' == typeof e ? e : e.message || String(e))
2695
2743
  });
2744
+ const outputPath = String(compilation.options?.output?.path || '');
2745
+ const contextDir = String(compilation.options?.context || '');
2746
+ let instruction;
2747
+ if (!this.firstRun && changedSources) {
2748
+ const { forcedFull, changedSources: sources } = changedSources.snapshot();
2749
+ instruction = reloadSurvivingPackage(classifyReloadFromSources({
2750
+ changedSources: sources,
2751
+ forcedFull,
2752
+ getContentScriptCount: ()=>readContentScriptCount(compilation, outputPath),
2753
+ getSourceFeatureIndex: ()=>buildSourceFeatureIndex(compilation, contextDir),
2754
+ outputPath
2755
+ }));
2756
+ }
2696
2757
  const target = {
2697
- outputPath: String(compilation.options?.output?.path || ''),
2698
- contextDir: String(compilation.options?.context || '')
2758
+ outputPath,
2759
+ contextDir,
2760
+ instruction
2699
2761
  };
2700
2762
  if (this.firstRun) return void await this.runOne(target, 'full');
2701
2763
  if (this.active) {
2702
- this.pending = target;
2764
+ this.pending = {
2765
+ ...target,
2766
+ instruction: mergeInstructions(this.pending?.instruction, target.instruction)
2767
+ };
2703
2768
  return;
2704
2769
  }
2705
2770
  this.active = true;
@@ -2736,6 +2801,10 @@ class SafariDevPlugin {
2736
2801
  return;
2737
2802
  }
2738
2803
  if (wasFirstRun) this.firstRun = false;
2804
+ if (!wasFirstRun && target.instruction && this.reloadBroker) await dispatchReload(target.instruction, {
2805
+ broker: this.reloadBroker,
2806
+ producerRestartExpected: true
2807
+ });
2739
2808
  this.emitter.emit('compiled', {
2740
2809
  outputPath: target.outputPath,
2741
2810
  contextDir: target.contextDir,
package/dist/938~0.mjs CHANGED
@@ -10,7 +10,7 @@ function canonicalizeDir(dir) {
10
10
  try {
11
11
  return __rspack_external_node_fs_1b05aee1.realpathSync(dir);
12
12
  } catch {
13
- return dir;
13
+ return __rspack_external_node_path_806ed179.resolve(dir);
14
14
  }
15
15
  }
16
16
  }
package/dist/950~0.mjs CHANGED
@@ -84,10 +84,11 @@ function buildAssetsTree(stats) {
84
84
  const assets = statsJson?.assets || [];
85
85
  return getAssetsTree(assets);
86
86
  }
87
- function buildComplete(browser, distDisplayPath, totalBytes) {
87
+ function buildComplete(browser, distDisplayPath, totalBytes, mode) {
88
88
  const noun = artifactNoun(String(browser));
89
+ const builtFor = 'development' === mode ? 'built for development in' : 'none' === mode ? 'built in' : 'built for production in';
89
90
  const size = 'number' == typeof totalBytes && totalBytes > 0 ? ` (${getHumanSize(totalBytes)})` : '';
90
- return `${getLoggingPrefix('success')} ${noun} built for production in ${pintor.underline(distDisplayPath)}${size}.`;
91
+ return `${getLoggingPrefix('success')} ${noun} ${builtFor} ${pintor.underline(distDisplayPath)}${size}.`;
91
92
  }
92
93
  function platformDocsUrl() {
93
94
  return String(process.env.EXTENSION_DEV_DOCS_URL || '').trim().replace(/\/+$/, '');
@@ -1,8 +1,4 @@
1
1
  import type { PreviewOptions } from './types.js';
2
- /**
3
- * Resolved browser launch options returned by extensionPreview.
4
- * The caller is responsible for actually launching the browser.
5
- */
6
2
  export interface ResolvedPreviewOptions {
7
3
  browser: string;
8
4
  outPath: string;
@@ -29,9 +25,5 @@ export interface ResolvedPreviewOptions {
29
25
  logUrl?: string;
30
26
  logTab?: number | string;
31
27
  }
32
- /**
33
- * Browser launcher callback. When provided, extensionPreview calls it
34
- * instead of requiring plugin-browsers internally.
35
- */
36
28
  export type PreviewLauncherFn = (opts: ResolvedPreviewOptions) => Promise<void>;
37
29
  export declare function extensionPreview(pathOrRemoteUrl: string | undefined, previewOptions: PreviewOptions, browserLauncher?: PreviewLauncherFn): Promise<void>;
@@ -28,7 +28,6 @@ export declare class ActionsFileWriter implements ActionsSink {
28
28
  private lines;
29
29
  private started;
30
30
  constructor(options: ActionsFileOptions);
31
- /** Rotate any prior file so a new run starts clean. No header is written. */
32
31
  start(): void;
33
32
  write(record: ActionRecord): void;
34
33
  close(): void;
@@ -10,7 +10,7 @@ export interface BridgeConnection {
10
10
  export interface BridgeBrokerOptions {
11
11
  instanceId: string;
12
12
  runId: string;
13
- engine?: 'chromium' | 'firefox';
13
+ engine?: 'chromium' | 'firefox' | 'webkit';
14
14
  ring?: LogRingBuffer;
15
15
  file?: LogsFileWriter;
16
16
  allowControl?: boolean;
@@ -22,6 +22,7 @@ export interface BridgeBrokerOptions {
22
22
  setTimer?: (fn: () => void, ms: number) => ReturnType<typeof setTimeout>;
23
23
  clearTimer?: (handle: ReturnType<typeof setTimeout>) => void;
24
24
  onExecutorAttached?: () => void;
25
+ onExecutorDetached?: () => void;
25
26
  }
26
27
  export { CLOSE_BAD_HELLO, CLOSE_BAD_INSTANCE, CLOSE_CONTROL_UNAVAILABLE, CLOSE_SLOW_CONSUMER } from './contracts.js';
27
28
  export declare const DEFAULT_CMD_TIMEOUT_MS = 5000;
@@ -47,8 +48,8 @@ export declare class BridgeBroker {
47
48
  private producerEverConnected;
48
49
  private readonly sessionStartedAt;
49
50
  private lastUndeliveredWarnKind;
50
- /** Fired once, on the first producer hello, to stamp ready.json. */
51
51
  private readonly onExecutorAttached?;
52
+ private readonly onExecutorDetached?;
52
53
  private lastProducerDisconnectedAt;
53
54
  private lastStaleHelloAt;
54
55
  private pendingReload?;
@@ -66,10 +67,11 @@ export declare class BridgeBroker {
66
67
  changedFiles?: string[];
67
68
  changedScriptFiles?: string[];
68
69
  }): number;
69
- undeliveredReloadWarning(): string | null;
70
+ undeliveredReloadWarning(options?: {
71
+ producerRestartExpected?: boolean;
72
+ }): string | null;
70
73
  pingProducers(): number;
71
74
  ingestLog(incoming: IncomingLogEvent): void;
72
- /** At most 3 stale-producer resync reloads per rolling minute. */
73
75
  private allowStaleProducerResync;
74
76
  private onHello;
75
77
  private diagnoseExecutorAbsence;
@@ -4,26 +4,17 @@ export interface ReadyContractInfo {
4
4
  controlPort: number;
5
5
  instanceId: string;
6
6
  runId: string;
7
- /** Ready-contract version, `ReadyMetadata['schemaVersion']` on current engines. */
8
7
  schemaVersion?: number;
9
- /** Result-envelope capability advertisement, `1` on current engines. */
10
8
  schema?: number;
11
9
  logsPath?: string;
12
10
  status?: string;
13
- /** Dev-server pid; absent in pre-4.1 contracts. */
14
11
  pid?: number;
15
- /** Browser CDP port, stamped post-launch, may lag `status: 'ready'`. */
16
12
  cdpPort?: number;
17
- /** Stamped when the launched browser exits while the server keeps running. */
18
13
  browserExitedAt?: string;
19
14
  browserExitCode?: number;
20
- /** When the compile finished (ISO), the meaning of `status: 'ready'`. */
21
15
  compiledAt?: string;
22
- /** When the extension's service worker attached to the control channel (ISO). */
23
16
  executorAttachedAt?: string;
24
- /** `'attached'` once the SW has connected; absent while still launching. */
25
17
  runtime?: string;
26
- /** Last contract write time (ISO). */
27
18
  ts?: string;
28
19
  binary?: string;
29
20
  binaryProvenance?: string;
@@ -55,7 +46,6 @@ export declare class BridgeConsumer {
55
46
  private timer;
56
47
  private lastCloseInfo;
57
48
  constructor(options: ConsumerOptions);
58
- /** Why the last socket closed; null until a close has happened. */
59
49
  get lastClose(): ConsumerCloseInfo | null;
60
50
  start(): void;
61
51
  close(): void;
@@ -40,21 +40,7 @@ export interface BridgeTarget {
40
40
  tabId?: number;
41
41
  }
42
42
  export type CommandOp = 'eval' | 'storage.get' | 'storage.set' | 'reload' | 'open' | 'tabs.query' | 'inspect';
43
- /**
44
- * Granularity of a dev-loop reload. Mirrors `ReloadType` in
45
- * plugin-reload/classify-reload.ts: the launched-browser path feeds this
46
- * decision to the CDP controller; the `--no-browser` path feeds the same
47
- * decision to the broker, which broadcasts a {@link ReloadFrame} to the SW
48
- * producer.
49
- */
50
43
  export type ReloadType = 'full' | 'service-worker' | 'content-scripts';
51
- /**
52
- * Everything a {@link ReloadFrame} can carry in `reloadType`: the extension
53
- * reload granularities plus `'page'`, a notify-only signal for page-only
54
- * edits (popup/options/sidebar/devtools/newtab). For `'page'` the producer
55
- * performs NO reload (livereload owns the refresh); it only forwards the
56
- * announcement so the devtools pill mirrors the dev loop.
57
- */
58
44
  export type DevReloadKind = ReloadType | 'page';
59
45
  export type GapReason = 'ring_overflow' | 'rate_limit' | 'disk_slow' | 'slow_consumer';
60
46
  export interface HelloFrame {
@@ -68,7 +54,7 @@ export interface ReadyFrame {
68
54
  type: 'ready';
69
55
  runId: string;
70
56
  bufferedFrom?: number;
71
- engine?: 'chromium' | 'firefox';
57
+ engine?: 'chromium' | 'firefox' | 'webkit';
72
58
  capabilities?: {
73
59
  eval?: boolean;
74
60
  storage?: boolean;
@@ -115,27 +101,12 @@ export interface ResultFrame {
115
101
  code?: BridgeRefusalCode;
116
102
  };
117
103
  }
118
- /**
119
- * Dev-loop reload broadcast, server → producer. Sent by the broker on a compile
120
- * that completed without a CDP controller (`--no-browser`, headless/CI, remote)
121
- * so the service-worker producer can self-reload. Unlike a `reload` CommandFrame
122
- * (a controller-issued, `--allow-control`-gated act verb that expects a result),
123
- * this is a fire-and-forget dev-server signal, no cmdId, no result.
124
- */
125
104
  export interface ReloadFrame {
126
105
  type: 'reload';
127
106
  reloadType: DevReloadKind;
128
107
  changedContentScriptEntries?: string[];
129
- /**
130
- * Server-built human context label, e.g. "content_script (content/scripts.tsx)".
131
- * Shown VERBATIM by every announcement surface (CLI stdout, the page's
132
- * devtools console line, the devtools-extension pill) so the three can
133
- * never disagree about what is reloading.
134
- */
135
108
  label?: string;
136
- /** Project-relative source files that triggered this reload. */
137
109
  changedFiles?: string[];
138
- /** Emitted scripts/ bundles the SW should replay its executeScript calls for. */
139
110
  changedScriptFiles?: string[];
140
111
  }
141
112
  export interface ReloadAckFrame {
@@ -143,15 +114,6 @@ export interface ReloadAckFrame {
143
114
  reloadType: DevReloadKind;
144
115
  label?: string;
145
116
  }
146
- /**
147
- * Server → producer keepalive. An MV3 service worker idles out after ~30s
148
- * without events, and a stopped SW holds no control socket, reload
149
- * broadcasts would reach zero producers and silently apply to nothing
150
- * (quiet extensions lost SW/manifest reloads once >30s passed between
151
- * edits). Receiving any WebSocket message resets the SW idle timer
152
- * (Chrome 116+), so a periodic ping keeps the dev extension's SW
153
- * responsive for the whole dev session. Producers ignore the frame.
154
- */
155
117
  export interface PingFrame {
156
118
  type: 'ping';
157
119
  }
@@ -159,11 +121,7 @@ export type ClientFrame = HelloFrame | LogFrame | CommandFrame | ReloadAckFrame;
159
121
  export type ServerFrame = ReadyFrame | LogFrame | GapFrame | ResultFrame | ReloadFrame | PingFrame;
160
122
  export type AnyFrame = ClientFrame | ServerFrame;
161
123
  export declare const CONTROL_WS_PATH = "/extjs-control";
162
- /** The hello named an instanceId from a previous dev session. */
163
124
  export declare const CLOSE_BAD_INSTANCE = 4001;
164
- /** The hello was malformed: wrong envelope version, or an unknown role. */
165
125
  export declare const CLOSE_BAD_HELLO = 4002;
166
- /** A controller dialed a session started without `--allow-control`. */
167
126
  export declare const CLOSE_CONTROL_UNAVAILABLE = 4003;
168
- /** The socket fell far enough behind that it was dropped to protect the broker. */
169
127
  export declare const CLOSE_SLOW_CONSUMER = 4008;
@@ -25,6 +25,5 @@ export declare class LogsFileWriter {
25
25
  private maybeNoteDrops;
26
26
  private writeHeader;
27
27
  private rotatedName;
28
- /** Shift generations: drop the oldest, age each, move current → .1 */
29
28
  private rotate;
30
29
  }
@@ -1,22 +1,13 @@
1
- /** Increasing verbosity; a level selects itself plus everything more severe. */
2
1
  export declare const LOG_LEVEL_ORDER: readonly ['error', 'warn', 'info', 'debug', 'trace'];
3
2
  export type LogLevelFilter = (typeof LOG_LEVEL_ORDER)[number] | 'all' | 'off' | (string & {});
4
3
  export interface LogQuery {
5
- /** One context, a comma-separated list, an array, or 'all'. */
6
4
  context?: string | string[];
7
- /** Minimum severity. 'all' and 'off' select every level. */
8
5
  level?: LogLevelFilter;
9
- /** Only structured dx.signal diagnostics. */
10
6
  signalsOnly?: boolean;
11
- /** Only events after this point: a sequence number, or an ISO timestamp
12
- * compared against the event's own clock. */
13
7
  since?: number | string;
14
- /** Glob (`*` = any run of chars) or plain substring over url then hostname. */
15
8
  url?: string;
16
- /** Only events carrying this tab id. */
17
9
  tab?: number | string;
18
10
  }
19
- /** A bridge log line as read off disk: dynamic, so the probed fields only. */
20
11
  export interface LogEventLike {
21
12
  type?: unknown;
22
13
  eventType?: unknown;
@@ -30,7 +21,6 @@ export interface LogEventLike {
30
21
  tabId?: unknown;
31
22
  }
32
23
  export declare function logLevelRank(level: string): number;
33
- /** How a `since` value is read: a sequence number, or a point in time. */
34
24
  export type LogSince = {
35
25
  seq: number;
36
26
  } | {
@@ -38,11 +28,5 @@ export type LogSince = {
38
28
  };
39
29
  export declare function parseLogSince(value: unknown): LogSince | null | undefined;
40
30
  export declare function isAfterSince(event: LogEventLike, since: LogSince): boolean;
41
- /** True when the event passes every clause of the query. */
42
31
  export declare function matchesLogQuery(event: LogEventLike, query: LogQuery): boolean;
43
- /**
44
- * One-shot read of a session's logs.ndjson. Returns an empty array when the
45
- * session has never written one: an absent file is "nothing logged yet", and
46
- * making that a throw would force every caller to guard it.
47
- */
48
32
  export declare function readLogEvents(projectPath: string, browser?: string, query?: LogQuery): LogEventLike[];