extension 3.15.0 → 3.15.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
@@ -1334,13 +1334,18 @@ exports.modules = {
1334
1334
  if (!sessionId) return;
1335
1335
  const session = this.watchedPageSessions.get(sessionId);
1336
1336
  if (!session) return;
1337
+ if (this.suppressInitialContextBurst.has(sessionId)) return;
1337
1338
  const context = params?.context;
1338
1339
  if (!context) return;
1339
1340
  this.evaluateContentScriptOnNewContext(sessionId, session, context).catch(()=>{});
1340
1341
  return;
1341
1342
  }
1342
1343
  if ('Target.detachedFromTarget' === method) {
1343
- if (sessionId) this.watchedPageSessions.delete(sessionId);
1344
+ if (sessionId) {
1345
+ this.watchedPageSessions.delete(sessionId);
1346
+ this.releaseSessionContexts(sessionId);
1347
+ this.suppressInitialContextBurst.delete(sessionId);
1348
+ }
1344
1349
  }
1345
1350
  });
1346
1351
  }
@@ -1366,10 +1371,15 @@ exports.modules = {
1366
1371
  targetId,
1367
1372
  url
1368
1373
  });
1374
+ this.suppressInitialContextBurst.add(sessionId);
1369
1375
  try {
1370
1376
  await this.cdp.sendCommand('Runtime.enable', {}, sessionId);
1377
+ setTimeout(()=>{
1378
+ this.suppressInitialContextBurst.delete(sessionId);
1379
+ }, 250);
1371
1380
  } catch {
1372
1381
  this.watchedPageSessions.delete(sessionId);
1382
+ this.suppressInitialContextBurst.delete(sessionId);
1373
1383
  }
1374
1384
  }
1375
1385
  async evaluateContentScriptOnNewContext(sessionId, session, context) {
@@ -1792,9 +1802,15 @@ exports.modules = {
1792
1802
  if (existing && typeof existing.cleanup === 'function') existing.cleanup();
1793
1803
  } catch (error) {}
1794
1804
  if (${allowCoarseCleanup ? 'true' : 'false'}) {
1805
+ // Bundle-scoped sweep: only remove roots owned by this bundleId. The inner
1806
+ // wrapper tags every host with data-extjs-reinject-key on mount, so this
1807
+ // catches roots from a manifest-cached run before the outer cleanup
1808
+ // registry was populated. A broad querySelector('[data-extension-root]')
1809
+ // would destroy roots owned by sibling content_scripts entries that
1810
+ // didn't change — leaving the page with only this bundle's roots.
1795
1811
  try {
1796
- const staleRoots = Array.from(document.querySelectorAll(rootSelector));
1797
- for (const root of staleRoots) {
1812
+ const staleKeyed = Array.from(document.querySelectorAll(keyedSelector));
1813
+ for (const root of staleKeyed) {
1798
1814
  if (root && typeof root.remove === 'function') root.remove();
1799
1815
  }
1800
1816
  } catch (error) {}
@@ -1945,22 +1961,39 @@ exports.modules = {
1945
1961
  }
1946
1962
  async collectExecutionContexts(sessionId) {
1947
1963
  if (!this.cdp) return [];
1964
+ const cached = this.sessionContexts.get(sessionId);
1965
+ if (cached) return Array.from(cached.values());
1948
1966
  const contextsById = new Map();
1967
+ this.sessionContexts.set(sessionId, contextsById);
1949
1968
  const unsubscribe = this.cdp.onProtocolEvent((message)=>{
1950
1969
  if (String(message.sessionId || '') !== sessionId) return;
1951
- if ('Runtime.executionContextCreated' !== String(message.method || '')) return;
1952
- const context = message.params?.context;
1953
- const contextId = context?.id;
1954
- if ('number' == typeof contextId) contextsById.set(contextId, context);
1970
+ const method = String(message.method || '');
1971
+ if ('Runtime.executionContextCreated' === method) {
1972
+ const context = message.params?.context;
1973
+ const contextId = context?.id;
1974
+ if ('number' == typeof contextId) contextsById.set(contextId, context);
1975
+ return;
1976
+ }
1977
+ if ('Runtime.executionContextDestroyed' === method) {
1978
+ const params = message.params || {};
1979
+ if ('number' == typeof params.executionContextId) contextsById.delete(params.executionContextId);
1980
+ return;
1981
+ }
1982
+ if ('Runtime.executionContextsCleared' === method) contextsById.clear();
1955
1983
  });
1956
- try {
1957
- await this.cdp.sendCommand('Runtime.enable', {}, sessionId);
1958
- await new Promise((resolve)=>setTimeout(resolve, 100));
1959
- } finally{
1960
- unsubscribe();
1961
- }
1984
+ this.sessionContextsUnsubscribe.set(sessionId, unsubscribe);
1985
+ await this.cdp.sendCommand('Runtime.enable', {}, sessionId);
1986
+ await new Promise((resolve)=>setTimeout(resolve, 100));
1962
1987
  return Array.from(contextsById.values());
1963
1988
  }
1989
+ releaseSessionContexts(sessionId) {
1990
+ const unsubscribe = this.sessionContextsUnsubscribe.get(sessionId);
1991
+ if (unsubscribe) try {
1992
+ unsubscribe();
1993
+ } catch {}
1994
+ this.sessionContextsUnsubscribe.delete(sessionId);
1995
+ this.sessionContexts.delete(sessionId);
1996
+ }
1964
1997
  constructor(args){
1965
1998
  cdp_extension_controller_define_property(this, "outPath", void 0);
1966
1999
  cdp_extension_controller_define_property(this, "browser", void 0);
@@ -1975,6 +2008,9 @@ exports.modules = {
1975
2008
  cdp_extension_controller_define_property(this, "activeContentScriptRules", []);
1976
2009
  cdp_extension_controller_define_property(this, "contentScriptTargetListenerInstalled", false);
1977
2010
  cdp_extension_controller_define_property(this, "watchedPageSessions", new Map());
2011
+ cdp_extension_controller_define_property(this, "sessionContexts", new Map());
2012
+ cdp_extension_controller_define_property(this, "sessionContextsUnsubscribe", new Map());
2013
+ cdp_extension_controller_define_property(this, "suppressInitialContextBurst", new Set());
1978
2014
  this.outPath = args.outPath;
1979
2015
  this.browser = args.browser;
1980
2016
  this.cdpPort = args.cdpPort;
@@ -20,6 +20,9 @@ export declare class CDPExtensionController {
20
20
  private activeContentScriptRules;
21
21
  private contentScriptTargetListenerInstalled;
22
22
  private watchedPageSessions;
23
+ private sessionContexts;
24
+ private sessionContextsUnsubscribe;
25
+ private suppressInitialContextBurst;
23
26
  constructor(args: {
24
27
  outPath: string;
25
28
  browser: 'chrome' | 'edge' | 'chromium-based';
@@ -86,5 +89,6 @@ export declare class CDPExtensionController {
86
89
  private resolveExecutionContextId;
87
90
  private getTopFrameId;
88
91
  private collectExecutionContexts;
92
+ private releaseSessionContexts;
89
93
  }
90
94
  export {};
package/package.json CHANGED
@@ -38,7 +38,7 @@
38
38
  "extension": "./bin/extension.cjs"
39
39
  },
40
40
  "name": "extension",
41
- "version": "3.15.0",
41
+ "version": "3.15.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.15.0",
104
- "extension-develop": "3.15.0",
105
- "extension-install": "3.15.0",
103
+ "extension-create": "3.15.1",
104
+ "extension-develop": "3.15.1",
105
+ "extension-install": "3.15.1",
106
106
  "commander": "^14.0.3",
107
107
  "pintor": "0.3.0",
108
108
  "semver": "^7.7.3",