extension 3.16.0 → 3.16.1

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.
package/dist/322.cjs CHANGED
@@ -1579,6 +1579,52 @@ exports.modules = {
1579
1579
  return false;
1580
1580
  }
1581
1581
  }
1582
+ async replayProgrammaticScripts(changedScriptFiles) {
1583
+ if (!this.cdp) return {
1584
+ replayed: 0
1585
+ };
1586
+ if (!Array.isArray(changedScriptFiles) || 0 === changedScriptFiles.length) return {
1587
+ replayed: 0
1588
+ };
1589
+ const runtimeTarget = await this.attachToExtensionRuntimeTarget();
1590
+ if (!runtimeTarget) return {
1591
+ replayed: 0
1592
+ };
1593
+ const result = await this.cdp.evaluate(runtimeTarget.sessionId, `(() => (async () => {
1594
+ if (typeof globalThis !== "object" || !globalThis) return {ok: false, reason: "no globalThis"};
1595
+ if (typeof globalThis.__extjsScriptsReplay !== "function") {
1596
+ return {ok: false, reason: "shim_missing"};
1597
+ }
1598
+ try {
1599
+ const outcome = await globalThis.__extjsScriptsReplay(${JSON.stringify(changedScriptFiles)});
1600
+ const list = Array.isArray(outcome) ? outcome : [];
1601
+ return {
1602
+ ok: true,
1603
+ replayed: list.filter((entry) => entry && entry.ok).length,
1604
+ failures: list.filter((entry) => entry && entry.ok === false).length
1605
+ };
1606
+ } catch (error) {
1607
+ return {ok: false, reason: "eval_error", message: String((error && error.message) || error)};
1608
+ }
1609
+ })())()`, {
1610
+ awaitPromise: true
1611
+ });
1612
+ if ('true' === process.env.EXTENSION_AUTHOR_MODE) try {
1613
+ console.log(`[CDP] scripts replay result: ${JSON.stringify({
1614
+ changedScriptFiles,
1615
+ result
1616
+ })}`);
1617
+ } catch {}
1618
+ if (result && 'object' == typeof result) {
1619
+ const replayed = Number(result.replayed);
1620
+ return {
1621
+ replayed: Number.isFinite(replayed) ? replayed : 0
1622
+ };
1623
+ }
1624
+ return {
1625
+ replayed: 0
1626
+ };
1627
+ }
1582
1628
  async hardReload() {
1583
1629
  if (!this.extensionId) return false;
1584
1630
  try {
package/dist/browsers.cjs CHANGED
@@ -50,6 +50,14 @@ var __webpack_modules__ = {
50
50
  if (pid) return `PID ${pid}`;
51
51
  return '';
52
52
  }
53
+ function encodeChromiumExtensionIdFromDigest(digest) {
54
+ let extensionId = '';
55
+ for (const byte of digest){
56
+ extensionId += String.fromCharCode(97 + (byte >> 4 & 0x0f));
57
+ extensionId += String.fromCharCode(97 + (0x0f & byte));
58
+ }
59
+ return extensionId;
60
+ }
53
61
  function deriveChromiumExtensionIdFromManifest(manifest) {
54
62
  const key = toNormalizedId(manifest?.key);
55
63
  if (!key) return '';
@@ -57,12 +65,19 @@ var __webpack_modules__ = {
57
65
  const decodedKey = Buffer.from(key.replace(/\s+/g, ''), 'base64');
58
66
  if (!decodedKey.length) return '';
59
67
  const digest = (0, external_crypto_namespaceObject.createHash)('sha256').update(decodedKey).digest().subarray(0, 16);
60
- let extensionId = '';
61
- for (const byte of digest){
62
- extensionId += String.fromCharCode(97 + (byte >> 4 & 0x0f));
63
- extensionId += String.fromCharCode(97 + (0x0f & byte));
64
- }
65
- return extensionId;
68
+ return encodeChromiumExtensionIdFromDigest(digest);
69
+ } catch {
70
+ return '';
71
+ }
72
+ }
73
+ function deriveChromiumExtensionIdFromPath(extensionPath) {
74
+ if (!extensionPath || 'string' != typeof extensionPath) return '';
75
+ try {
76
+ const absolute = external_path_.resolve(extensionPath);
77
+ const isWindows = 'win32' === process.platform;
78
+ const seedBuffer = isWindows ? Buffer.from(absolute.replace(/\//g, '\\'), 'utf16le') : Buffer.from(absolute, 'utf8');
79
+ const digest = (0, external_crypto_namespaceObject.createHash)('sha256').update(seedBuffer).digest().subarray(0, 16);
80
+ return encodeChromiumExtensionIdFromDigest(digest);
66
81
  } catch {
67
82
  return '';
68
83
  }
@@ -77,7 +92,11 @@ var __webpack_modules__ = {
77
92
  if (fromInfo) return fromInfo;
78
93
  const fromFallback = toNormalizedId(args.fallback?.extensionId);
79
94
  if (fromFallback) return fromFallback;
80
- if ('chrome' === args.browser || 'edge' === args.browser || 'chromium' === args.browser || 'chromium-based' === args.browser) return deriveChromiumExtensionIdFromManifest(args.manifest);
95
+ if ('chrome' === args.browser || 'edge' === args.browser || 'chromium' === args.browser || 'chromium-based' === args.browser) {
96
+ const fromKey = deriveChromiumExtensionIdFromManifest(args.manifest);
97
+ if (fromKey) return fromKey;
98
+ return deriveChromiumExtensionIdFromPath(args.extensionPath || '');
99
+ }
81
100
  if ('firefox' === args.browser || 'firefox-based' === args.browser) return deriveFirefoxExtensionIdFromManifest(args.manifest);
82
101
  return '';
83
102
  }
@@ -91,7 +110,8 @@ var __webpack_modules__ = {
91
110
  browser: opts.browser,
92
111
  info: null,
93
112
  fallback: opts.fallback,
94
- manifest
113
+ manifest,
114
+ extensionPath: opts.outPath
95
115
  });
96
116
  const info = manifestDerivedExtensionId ? await Promise.race([
97
117
  opts.getInfo().catch(()=>null),
@@ -101,7 +121,8 @@ var __webpack_modules__ = {
101
121
  browser: opts.browser,
102
122
  info,
103
123
  fallback: opts.fallback,
104
- manifest
124
+ manifest,
125
+ extensionPath: opts.outPath
105
126
  });
106
127
  if (!extensionId) return false;
107
128
  const name = info?.name || opts.fallback?.name || manifest.name;
@@ -141,7 +162,8 @@ var __webpack_modules__ = {
141
162
  const resolvedExtensionId = resolveExtensionId({
142
163
  browser: opts.browser,
143
164
  info: runtimeInfo,
144
- manifest
165
+ manifest,
166
+ extensionPath: opts.outPath
145
167
  });
146
168
  if (resolvedExtensionId) {
147
169
  const message = {
@@ -1452,6 +1474,10 @@ var __webpack_modules__ = {
1452
1474
  if ('function' == typeof ctrl.registerContentScriptsForFutureNavigations) try {
1453
1475
  await ctrl.registerContentScriptsForFutureNavigations(rules);
1454
1476
  } catch {}
1477
+ const changedScripts = (instruction.changedAssets || []).filter((asset)=>/(^|\/)scripts\//i.test(String(asset || '')) && /\.[cm]?[jt]sx?$/i.test(String(asset || '')));
1478
+ if (changedScripts.length > 0 && 'function' == typeof ctrl.replayProgrammaticScripts) try {
1479
+ await ctrl.replayProgrammaticScripts(changedScripts);
1480
+ } catch {}
1455
1481
  return;
1456
1482
  }
1457
1483
  }
package/dist/cli.cjs CHANGED
@@ -51,6 +51,14 @@ var __webpack_modules__ = {
51
51
  if (pid) return `PID ${pid}`;
52
52
  return '';
53
53
  }
54
+ function encodeChromiumExtensionIdFromDigest(digest) {
55
+ let extensionId = '';
56
+ for (const byte of digest){
57
+ extensionId += String.fromCharCode(97 + (byte >> 4 & 0x0f));
58
+ extensionId += String.fromCharCode(97 + (0x0f & byte));
59
+ }
60
+ return extensionId;
61
+ }
54
62
  function deriveChromiumExtensionIdFromManifest(manifest) {
55
63
  const key = toNormalizedId(manifest?.key);
56
64
  if (!key) return '';
@@ -58,12 +66,19 @@ var __webpack_modules__ = {
58
66
  const decodedKey = Buffer.from(key.replace(/\s+/g, ''), 'base64');
59
67
  if (!decodedKey.length) return '';
60
68
  const digest = (0, external_crypto_namespaceObject.createHash)('sha256').update(decodedKey).digest().subarray(0, 16);
61
- let extensionId = '';
62
- for (const byte of digest){
63
- extensionId += String.fromCharCode(97 + (byte >> 4 & 0x0f));
64
- extensionId += String.fromCharCode(97 + (0x0f & byte));
65
- }
66
- return extensionId;
69
+ return encodeChromiumExtensionIdFromDigest(digest);
70
+ } catch {
71
+ return '';
72
+ }
73
+ }
74
+ function deriveChromiumExtensionIdFromPath(extensionPath) {
75
+ if (!extensionPath || 'string' != typeof extensionPath) return '';
76
+ try {
77
+ const absolute = external_path_.resolve(extensionPath);
78
+ const isWindows = 'win32' === process.platform;
79
+ const seedBuffer = isWindows ? Buffer.from(absolute.replace(/\//g, '\\'), 'utf16le') : Buffer.from(absolute, 'utf8');
80
+ const digest = (0, external_crypto_namespaceObject.createHash)('sha256').update(seedBuffer).digest().subarray(0, 16);
81
+ return encodeChromiumExtensionIdFromDigest(digest);
67
82
  } catch {
68
83
  return '';
69
84
  }
@@ -78,7 +93,11 @@ var __webpack_modules__ = {
78
93
  if (fromInfo) return fromInfo;
79
94
  const fromFallback = toNormalizedId(args.fallback?.extensionId);
80
95
  if (fromFallback) return fromFallback;
81
- if ('chrome' === args.browser || 'edge' === args.browser || 'chromium' === args.browser || 'chromium-based' === args.browser) return deriveChromiumExtensionIdFromManifest(args.manifest);
96
+ if ('chrome' === args.browser || 'edge' === args.browser || 'chromium' === args.browser || 'chromium-based' === args.browser) {
97
+ const fromKey = deriveChromiumExtensionIdFromManifest(args.manifest);
98
+ if (fromKey) return fromKey;
99
+ return deriveChromiumExtensionIdFromPath(args.extensionPath || '');
100
+ }
82
101
  if ('firefox' === args.browser || 'firefox-based' === args.browser) return deriveFirefoxExtensionIdFromManifest(args.manifest);
83
102
  return '';
84
103
  }
@@ -92,7 +111,8 @@ var __webpack_modules__ = {
92
111
  browser: opts.browser,
93
112
  info: null,
94
113
  fallback: opts.fallback,
95
- manifest
114
+ manifest,
115
+ extensionPath: opts.outPath
96
116
  });
97
117
  const info = manifestDerivedExtensionId ? await Promise.race([
98
118
  opts.getInfo().catch(()=>null),
@@ -102,7 +122,8 @@ var __webpack_modules__ = {
102
122
  browser: opts.browser,
103
123
  info,
104
124
  fallback: opts.fallback,
105
- manifest
125
+ manifest,
126
+ extensionPath: opts.outPath
106
127
  });
107
128
  if (!extensionId) return false;
108
129
  const name = info?.name || opts.fallback?.name || manifest.name;
@@ -142,7 +163,8 @@ var __webpack_modules__ = {
142
163
  const resolvedExtensionId = resolveExtensionId({
143
164
  browser: opts.browser,
144
165
  info: runtimeInfo,
145
- manifest
166
+ manifest,
167
+ extensionPath: opts.outPath
146
168
  });
147
169
  if (resolvedExtensionId) {
148
170
  const message = {
@@ -1451,6 +1473,10 @@ var __webpack_modules__ = {
1451
1473
  if ('function' == typeof ctrl.registerContentScriptsForFutureNavigations) try {
1452
1474
  await ctrl.registerContentScriptsForFutureNavigations(rules);
1453
1475
  } catch {}
1476
+ const changedScripts = (instruction.changedAssets || []).filter((asset)=>/(^|\/)scripts\//i.test(String(asset || '')) && /\.[cm]?[jt]sx?$/i.test(String(asset || '')));
1477
+ if (changedScripts.length > 0 && 'function' == typeof ctrl.replayProgrammaticScripts) try {
1478
+ await ctrl.replayProgrammaticScripts(changedScripts);
1479
+ } catch {}
1454
1480
  return;
1455
1481
  }
1456
1482
  }
@@ -70,6 +70,23 @@ export declare class CDPExtensionController {
70
70
  private evaluateContentScriptOnNewContext;
71
71
  reinjectMatchingTabsViaExtensionRuntime(rules: ContentScriptTargetRule[]): Promise<number>;
72
72
  private reloadPageTarget;
73
+ /**
74
+ * Replay previously-tracked `chrome.scripting.executeScript` calls from the
75
+ * background SW. The dev-only `__extjsScriptsReplay` shim (injected by
76
+ * `feature-scripts/InjectScriptsReplayShim`) keeps an in-memory registry of
77
+ * `executeScript({target.tabId, files, world})` calls the user's SW has
78
+ * made. When the user edits a file in `/scripts/*` we evaluate that
79
+ * registry inside the SW and re-issue every matching injection — bringing
80
+ * programmatic injection HMR closer to parity with declarative content
81
+ * scripts.
82
+ *
83
+ * No-op if no scripts changed, if the shim isn't installed (e.g. the SW
84
+ * was injected before the shim shipped, or the user disabled reload), or
85
+ * if no runtime target is reachable.
86
+ */
87
+ replayProgrammaticScripts(changedScriptFiles: string[]): Promise<{
88
+ replayed: number;
89
+ }>;
73
90
  hardReload(): Promise<boolean>;
74
91
  private attachToExtensionRuntimeTarget;
75
92
  private connectFreshClient;
package/package.json CHANGED
@@ -38,7 +38,7 @@
38
38
  "extension": "./bin/extension.cjs"
39
39
  },
40
40
  "name": "extension",
41
- "version": "3.16.0",
41
+ "version": "3.16.1",
42
42
  "description": "Create cross-browser extensions with no build configuration.",
43
43
  "homepage": "https://extension.js.org/",
44
44
  "bugs": {
@@ -100,9 +100,9 @@
100
100
  "cross-spawn": "^7.0.6",
101
101
  "edge-location": "2.2.0",
102
102
  "firefox-location2": "3.0.0",
103
- "extension-create": "3.16.0",
104
- "extension-develop": "3.16.0",
105
- "extension-install": "3.16.0",
103
+ "extension-create": "3.16.1",
104
+ "extension-develop": "3.16.1",
105
+ "extension-install": "3.16.1",
106
106
  "commander": "^14.0.3",
107
107
  "pintor": "0.3.0",
108
108
  "semver": "^7.7.3",