extension-develop 3.15.0-next.1 → 3.15.0

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/221.cjs CHANGED
@@ -464,7 +464,9 @@ exports.modules = {
464
464
  compress: false,
465
465
  devMiddleware: {
466
466
  writeToDisk: shouldWriteAssetToDisk,
467
- stats: false
467
+ stats: {
468
+ all: false
469
+ }
468
470
  },
469
471
  watchFiles: {
470
472
  paths: [
@@ -488,7 +490,7 @@ exports.modules = {
488
490
  },
489
491
  port,
490
492
  hot: true,
491
- liveReload: false
493
+ liveReload: true
492
494
  };
493
495
  const devServer = new dev_server_.RspackDevServer(serverConfig, compiler);
494
496
  const START_TIMEOUT_MS = parseInt(String(process.env.EXTENSION_START_TIMEOUT_MS || '30000'), 10);
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  exports.ids = [
3
- 512
3
+ 442
4
4
  ];
5
5
  exports.modules = {
6
6
  "./dev-server/compiler-hooks.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
@@ -1451,6 +1451,7 @@ exports.modules = {
1451
1451
  bannerPrinted: false,
1452
1452
  pendingCompilationLine: ''
1453
1453
  };
1454
+ const BANNER_PRINTED_EVENT = 'extensionjs:banner-printed';
1454
1455
  function markBannerPrinted() {
1455
1456
  sharedState.bannerPrinted = true;
1456
1457
  if (sharedState.pendingCompilationLine) {
@@ -1458,6 +1459,15 @@ exports.modules = {
1458
1459
  sharedState.pendingCompilationLine = '';
1459
1460
  }
1460
1461
  }
1462
+ let listenerInstalled = false;
1463
+ function ensureBannerListener() {
1464
+ if (listenerInstalled) return;
1465
+ listenerInstalled = true;
1466
+ process.on(BANNER_PRINTED_EVENT, ()=>{
1467
+ markBannerPrinted();
1468
+ });
1469
+ }
1470
+ ensureBannerListener();
1461
1471
  function isBannerPrinted() {
1462
1472
  if (sharedState.bannerPrinted) return true;
1463
1473
  if ('true' === process.env.EXTENSION_CLI_BANNER_PRINTED) {
@@ -5322,6 +5332,7 @@ exports.modules = {
5322
5332
  ];
5323
5333
  if ('development' === compiler.options.mode) {
5324
5334
  if (devServerHmrImports.length > 0) fileAssets.unshift(...devServerHmrImports);
5335
+ fileAssets.unshift((0, develop_context.G5)('preact-refresh-shim'));
5325
5336
  const hmrScript = (0, develop_context.G5)("minimum-script-file");
5326
5337
  fileAssets.push(hmrScript);
5327
5338
  }
@@ -7534,8 +7545,7 @@ Set background.noDynamicEntryWarning to true to disable this warning.
7534
7545
  manifestPath: this.manifestPath,
7535
7546
  includeList: this.includeList || {}
7536
7547
  }).apply(compiler);
7537
- const wrapperDisabled = 'production' === compiler.options.mode || 'true' === process.env.EXTENSION_NO_RELOAD;
7538
- if (!wrapperDisabled) new AddContentScriptWrapper({
7548
+ new AddContentScriptWrapper({
7539
7549
  manifestPath: this.manifestPath,
7540
7550
  browser: this.browser
7541
7551
  }).apply(compiler);
@@ -7600,6 +7610,9 @@ Set background.noDynamicEntryWarning to true to disable this warning.
7600
7610
  function localesValidationDetected(issue) {
7601
7611
  return `Locales validation detected: ${issue}`;
7602
7612
  }
7613
+ function localesMustBeAtProjectRoot(foundAt, expectedAt) {
7614
+ return `_locales/ is canonically placed at the project root (sibling of package.json, public/, dist/) — mirroring public/ and how Chrome reads locales from the extension root in dist. Found in the legacy next-to-manifest location; the build will use it, but consider moving it for consistency with public/ and to silence this warning.\n\n found: ${foundAt}\n preferred: ${expectedAt}`;
7615
+ }
7603
7616
  function pushCompilationError(compiler, compilation, name, message, file) {
7604
7617
  const ErrorConstructor = compiler?.rspack?.WebpackError || Error;
7605
7618
  const error = new ErrorConstructor(message);
@@ -7608,14 +7621,60 @@ Set background.noDynamicEntryWarning to true to disable this warning.
7608
7621
  if (!compilation.errors) compilation.errors = [];
7609
7622
  compilation.errors.push(error);
7610
7623
  }
7624
+ function isUsableDir(p) {
7625
+ try {
7626
+ return external_fs_.existsSync(p) && external_fs_.statSync(p).isDirectory();
7627
+ } catch {
7628
+ return false;
7629
+ }
7630
+ }
7631
+ function resolveLocalesFolder(manifestPath, projectRoot) {
7632
+ if (projectRoot) {
7633
+ const fromRoot = external_path_.join(projectRoot, '_locales');
7634
+ if (isUsableDir(fromRoot)) return fromRoot;
7635
+ }
7636
+ const fromManifest = external_path_.join(external_path_.dirname(manifestPath), '_locales');
7637
+ if (isUsableDir(fromManifest)) return fromManifest;
7638
+ }
7639
+ function listLocaleFiles(folder) {
7640
+ const out = [];
7641
+ for (const locale of external_fs_.readdirSync(folder)){
7642
+ const localeDir = external_path_.join(folder, locale);
7643
+ try {
7644
+ if (!external_fs_.statSync(localeDir).isDirectory()) continue;
7645
+ } catch {
7646
+ continue;
7647
+ }
7648
+ for (const entry of external_fs_.readdirSync(localeDir))out.push(external_path_.join(localeDir, entry));
7649
+ }
7650
+ return out;
7651
+ }
7652
+ function getLocales(manifestPath, projectRoot) {
7653
+ const localesFolder = resolveLocalesFolder(manifestPath, projectRoot);
7654
+ if (!localesFolder) return [];
7655
+ return listLocaleFiles(localesFolder);
7656
+ }
7611
7657
  function validateLocales(compiler, compilation, manifestPath) {
7658
+ const projectRoot = compiler.options.context || void 0;
7612
7659
  try {
7613
- const manifestDir = external_path_.dirname(manifestPath);
7614
7660
  const manifestRaw = external_fs_.readFileSync(manifestPath, 'utf8');
7615
7661
  const manifest = JSON.parse(manifestRaw);
7616
7662
  const defaultLocale = manifest?.default_locale;
7617
- const localesRoot = external_path_.join(manifestDir, '_locales');
7618
- const hasLocalesRoot = external_fs_.existsSync(localesRoot);
7663
+ const resolvedLocalesRoot = resolveLocalesFolder(manifestPath, projectRoot);
7664
+ const localesRoot = resolvedLocalesRoot || external_path_.join(external_path_.dirname(manifestPath), '_locales');
7665
+ const hasLocalesRoot = Boolean(resolvedLocalesRoot);
7666
+ if (projectRoot && resolvedLocalesRoot) {
7667
+ const manifestDir = external_path_.dirname(manifestPath);
7668
+ const sameAsRoot = external_path_.resolve(manifestDir) === external_path_.resolve(projectRoot);
7669
+ const usedManifestDirFallback = !sameAsRoot && external_path_.resolve(resolvedLocalesRoot) === external_path_.resolve(external_path_.join(manifestDir, '_locales'));
7670
+ if (usedManifestDirFallback) {
7671
+ const ErrorConstructor = compiler?.rspack?.WebpackError || Error;
7672
+ const warning = new ErrorConstructor(localesMustBeAtProjectRoot(resolvedLocalesRoot, external_path_.join(projectRoot, '_locales')));
7673
+ warning.name = 'LocalesLayoutWarning';
7674
+ if (!compilation.warnings) compilation.warnings = [];
7675
+ compilation.warnings.push(warning);
7676
+ }
7677
+ }
7619
7678
  if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(localesIncludeSummary(true, hasLocalesRoot, 'string' == typeof defaultLocale ? defaultLocale : void 0));
7620
7679
  if ('string' == typeof defaultLocale && defaultLocale.trim()) {
7621
7680
  if (!hasLocalesRoot) {
@@ -7675,9 +7734,8 @@ Set background.noDynamicEntryWarning to true to disable this warning.
7675
7734
  }
7676
7735
  } catch {}
7677
7736
  try {
7678
- const manifestDir = external_path_.dirname(manifestPath);
7679
- const localesRoot = external_path_.join(manifestDir, '_locales');
7680
- if (external_fs_.existsSync(localesRoot)) {
7737
+ const localesRoot = resolveLocalesFolder(manifestPath, projectRoot);
7738
+ if (localesRoot && external_fs_.existsSync(localesRoot)) {
7681
7739
  const localeDirs = external_fs_.readdirSync(localesRoot).map((d)=>external_path_.join(localesRoot, d)).filter((p)=>external_fs_.statSync(p).isDirectory());
7682
7740
  for (const localeDir of localeDirs){
7683
7741
  const msgPath = external_path_.join(localeDir, 'messages.json');
@@ -7694,19 +7752,12 @@ Set background.noDynamicEntryWarning to true to disable this warning.
7694
7752
  } catch {}
7695
7753
  return true;
7696
7754
  }
7697
- function getLocales(manifestPath) {
7698
- const localesFolder = external_path_.join(external_path_.dirname(manifestPath), '_locales');
7699
- const localeFiles = [];
7700
- if (external_fs_.existsSync(localesFolder)) for (const locale of external_fs_.readdirSync(localesFolder)){
7701
- const localeDir = external_path_.join(localesFolder, locale);
7702
- if (localeDir && external_fs_.statSync(localeDir).isDirectory()) for (const localeEntity of external_fs_.readdirSync(localeDir))localeFiles.push(external_path_.join(external_path_.dirname(manifestPath), '_locales', locale, localeEntity));
7703
- }
7704
- return localeFiles;
7705
- }
7706
7755
  function processLocaleAssets(compiler, compilation, manifestPath) {
7707
7756
  if (compilation.errors.length > 0) return;
7708
- const localesFields = getLocales(manifestPath);
7709
- const discoveredList = getLocales(manifestPath) || [];
7757
+ const projectRoot = compiler.options.context || void 0;
7758
+ const localesFields = getLocales(manifestPath, projectRoot);
7759
+ const discoveredList = getLocales(manifestPath, projectRoot) || [];
7760
+ const resolvedLocalesRoot = resolveLocalesFolder(manifestPath, projectRoot);
7710
7761
  let emittedCount = 0;
7711
7762
  let missingCount = 0;
7712
7763
  for (const field of Object.entries(localesFields || [])){
@@ -7726,8 +7777,7 @@ Set background.noDynamicEntryWarning to true to disable this warning.
7726
7777
  }
7727
7778
  const source = external_fs_.readFileSync(thisResource);
7728
7779
  const rawSource = new core_.sources.RawSource(source);
7729
- const manifestDir = external_path_.dirname(manifestPath);
7730
- const localesRoot = external_path_.join(manifestDir, '_locales');
7780
+ const localesRoot = resolvedLocalesRoot || external_path_.join(external_path_.dirname(manifestPath), '_locales');
7731
7781
  const relativeToLocales = external_path_.relative(localesRoot, thisResource);
7732
7782
  const normalizedRel = relativeToLocales.split(external_path_.sep).join('/');
7733
7783
  const filename = `_locales/${normalizedRel}`;
@@ -7737,22 +7787,14 @@ Set background.noDynamicEntryWarning to true to disable this warning.
7737
7787
  }
7738
7788
  if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(localesEmitSummary(emittedCount, missingCount, discoveredList.length));
7739
7789
  }
7740
- function trackLocaleDependencies(compilation, manifestPath) {
7790
+ function trackLocaleDependencies(compilation, manifestPath, projectRoot) {
7741
7791
  if (compilation.errors?.length) return;
7742
- const localesFields = getLocales(manifestPath);
7792
+ const localesFields = getLocales(manifestPath, projectRoot) || [];
7743
7793
  let added = 0;
7744
- for (const field of Object.entries(localesFields || [])){
7745
- const [, resource] = field;
7746
- if (resource) {
7747
- const fileDependencies = new Set(compilation.fileDependencies);
7748
- const fileResources = localesFields || [];
7749
- for (const thisResource of fileResources)if (external_fs_.existsSync(thisResource) && '.json' === external_path_.extname(thisResource)) {
7750
- if (!fileDependencies.has(thisResource)) {
7751
- fileDependencies.add(thisResource);
7752
- compilation.fileDependencies.add(thisResource);
7753
- added++;
7754
- }
7755
- }
7794
+ for (const thisResource of localesFields)if (external_fs_.existsSync(thisResource) && '.json' === external_path_.extname(thisResource)) {
7795
+ if (!compilation.fileDependencies.has(thisResource)) {
7796
+ compilation.fileDependencies.add(thisResource);
7797
+ added++;
7756
7798
  }
7757
7799
  }
7758
7800
  if ('true' === process.env.EXTENSION_AUTHOR_MODE) console.log(localesDepsTracked(added));
@@ -7788,13 +7830,9 @@ Set background.noDynamicEntryWarning to true to disable this warning.
7788
7830
  processLocaleAssets(compiler, compilation, this.manifestPath);
7789
7831
  });
7790
7832
  });
7791
- compiler.hooks.thisCompilation.tap('locales:module', (compilation)=>{
7792
- compilation.hooks.processAssets.tap({
7793
- name: 'locales:module',
7794
- stage: core_.Compilation.PROCESS_ASSETS_STAGE_ADDITIONS
7795
- }, ()=>{
7796
- trackLocaleDependencies(compilation, this.manifestPath);
7797
- });
7833
+ compiler.hooks.afterCompile.tap('locales:module', (compilation)=>{
7834
+ const projectRoot = compiler.options.context || void 0;
7835
+ trackLocaleDependencies(compilation, this.manifestPath, projectRoot);
7798
7836
  });
7799
7837
  }
7800
7838
  constructor(options){
@@ -8524,7 +8562,7 @@ Set background.noDynamicEntryWarning to true to disable this warning.
8524
8562
  else if (val) scripts.push(val);
8525
8563
  const html = fields.html || {};
8526
8564
  const iconsRaw = fields.icons;
8527
- const icons = iconsRaw ? Array.isArray(iconsRaw) ? iconsRaw : Object.values(iconsRaw) : [];
8565
+ const icons = iconsRaw ? Array.isArray(iconsRaw) ? iconsRaw : flattenValues(iconsRaw) : [];
8528
8566
  const jsonMap = fields.json || {};
8529
8567
  const json = [];
8530
8568
  for (const [key, val] of Object.entries(jsonMap))if (isCriticalJsonFeatureKey(key)) {
@@ -8871,6 +8909,117 @@ Set background.noDynamicEntryWarning to true to disable this warning.
8871
8909
  }
8872
8910
  }
8873
8911
  plugin_wasm_define_property(WasmPlugin, "name", 'plugin-wasm');
8912
+ const PAGE_DIRS = [
8913
+ 'pages',
8914
+ 'sidebar',
8915
+ 'popup',
8916
+ 'options',
8917
+ 'options_ui',
8918
+ 'devtools',
8919
+ 'newtab',
8920
+ 'sandbox',
8921
+ 'action',
8922
+ 'browser_action',
8923
+ 'page_action'
8924
+ ];
8925
+ const isCodeAsset = (name)=>/\.(js|css|wasm)$/i.test(name);
8926
+ const categorize_isSourceMap = (name)=>/\.map$/i.test(name);
8927
+ const isHotUpdate = (name)=>/(^|\/)hot\//.test(name);
8928
+ function categorizeAsset(rawName) {
8929
+ const name = String(rawName || '').replace(/\\/g, '/');
8930
+ if (!name) return 'ignored';
8931
+ if (!isCodeAsset(name)) return 'ignored';
8932
+ if (categorize_isSourceMap(name)) return 'ignored';
8933
+ if (isHotUpdate(name)) return 'ignored';
8934
+ if (/(^|\/)content_scripts\//.test(name)) return "content-script";
8935
+ if (/(^|\/)background\//.test(name) || /(^|\/)service[-_]?worker\.(js|css|wasm)$/i.test(name)) return 'service-worker';
8936
+ for (const dir of PAGE_DIRS)if (new RegExp(`(^|\\/)${dir}\\/`).test(name)) return 'page';
8937
+ return 'ignored';
8938
+ }
8939
+ const BUDGET_BYTES = {
8940
+ "content-script": 153600,
8941
+ 'service-worker': 204800,
8942
+ page: 512000,
8943
+ ignored: 1 / 0
8944
+ };
8945
+ function fmtKiB(bytes) {
8946
+ const kib = bytes / 1024;
8947
+ if (kib >= 1024) return `${(kib / 1024).toFixed(2)} MiB`;
8948
+ return `${kib.toFixed(1)} KiB`;
8949
+ }
8950
+ function perfBudgetWarning(assets) {
8951
+ const header = `${1 === assets.length ? 'asset exceeds' : 'assets exceed'} the extension performance budget. Browser extensions inject content scripts on every navigation and wake service workers from cold, so we apply tighter budgets than the rspack default.`;
8952
+ const lines = assets.map((a)=>{
8953
+ const over = (a.size / a.budget * 100 - 100).toFixed(0);
8954
+ return ` ${a.name}\n size: ${fmtKiB(a.size)}\n budget: ${fmtKiB(a.budget)} (over by ${over}%)\n role: ${categoryRole(a.category)}`;
8955
+ });
8956
+ const remediation = "Recommended: lazy-load with dynamic import(), code-split per route, or replace large SDKs with thin fetch wrappers. See https://rspack.rs/guide/optimization/code-splitting";
8957
+ return `${header}\n\n${lines.join('\n')}\n\n${remediation}`;
8958
+ }
8959
+ function categoryRole(c) {
8960
+ switch(c){
8961
+ case "content-script":
8962
+ return "content script — injected on every page navigation";
8963
+ case 'service-worker':
8964
+ return 'service worker / background — wakes from cold each session';
8965
+ case 'page':
8966
+ return 'UI page — opened on demand';
8967
+ default:
8968
+ return 'asset';
8969
+ }
8970
+ }
8971
+ function plugin_perf_budgets_define_property(obj, key, value) {
8972
+ if (key in obj) Object.defineProperty(obj, key, {
8973
+ value: value,
8974
+ enumerable: true,
8975
+ configurable: true,
8976
+ writable: true
8977
+ });
8978
+ else obj[key] = value;
8979
+ return obj;
8980
+ }
8981
+ class PerfBudgetsPlugin {
8982
+ apply(compiler) {
8983
+ const enabled = 'boolean' == typeof this.options.enabled ? this.options.enabled : 'production' === compiler.options.mode;
8984
+ if (!enabled) return;
8985
+ const budgets = {
8986
+ ...BUDGET_BYTES,
8987
+ ...this.options.budgets || {}
8988
+ };
8989
+ compiler.hooks.afterCompile.tap(PerfBudgetsPlugin.name, (compilation)=>{
8990
+ if (compilation.errors?.length) return;
8991
+ const oversized = [];
8992
+ const assets = compilation.assets || {};
8993
+ for (const [name, source] of Object.entries(assets)){
8994
+ const size = source?.size?.() ?? 0;
8995
+ if (!size) continue;
8996
+ const category = categorizeAsset(name);
8997
+ if ('ignored' === category) continue;
8998
+ const budget = budgets[category];
8999
+ if (isFinite(budget)) {
9000
+ if (!(size <= budget)) oversized.push({
9001
+ name,
9002
+ size,
9003
+ budget,
9004
+ category
9005
+ });
9006
+ }
9007
+ }
9008
+ if (0 === oversized.length) return;
9009
+ oversized.sort((a, b)=>b.size - a.size);
9010
+ const ErrorConstructor = compiler?.rspack?.WebpackError || Error;
9011
+ const warning = new ErrorConstructor(perfBudgetWarning(oversized));
9012
+ warning.name = 'PerfBudgetWarning';
9013
+ if (!compilation.warnings) compilation.warnings = [];
9014
+ compilation.warnings.push(warning);
9015
+ });
9016
+ }
9017
+ constructor(options = {}){
9018
+ plugin_perf_budgets_define_property(this, "options", void 0);
9019
+ this.options = options;
9020
+ }
9021
+ }
9022
+ plugin_perf_budgets_define_property(PerfBudgetsPlugin, "name", 'plugin-perf-budgets');
8874
9023
  function webpackConfig(projectStructure, devOptions) {
8875
9024
  const { manifestPath } = projectStructure;
8876
9025
  const { packageJsonDir } = (0, lib_paths.fu)(projectStructure);
@@ -8927,7 +9076,8 @@ Set background.noDynamicEntryWarning to true to disable this warning.
8927
9076
  }),
8928
9077
  new SpecialFoldersPlugin({
8929
9078
  manifestPath
8930
- })
9079
+ }),
9080
+ new PerfBudgetsPlugin()
8931
9081
  ];
8932
9082
  if (devOptions.noBrowser) plugins.push(new plugin_playwright.Tb({
8933
9083
  packageJsonDir,
@@ -9066,7 +9216,7 @@ Set background.noDynamicEntryWarning to true to disable this warning.
9066
9216
  console: (0, branding.P)('Extension.js')
9067
9217
  },
9068
9218
  performance: {
9069
- hints: 'production' === devOptions.mode ? 'warning' : false
9219
+ hints: false
9070
9220
  },
9071
9221
  optimization: {
9072
9222
  minimize: 'production' === devOptions.mode,
@@ -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,t=>{if(t?.[o]?.didRun)return;let r=()=>{try{let t=chrome.runtime.getURL("pages/welcome.html");1;chrome.tabs.create({url:t,active:!0});try{if("number"==typeof e)try{chrome.tabs.update(e,{url:n})}catch{console.error("Error updating original active tab")}}catch{console.error("Error updating original active tab")}}catch{try{chrome.tabs.create({url:"pages/welcome.html",active:!0})}catch{console.error("Error creating welcome tab")}}};try{chrome.tabs.query({url:chrome.runtime.getURL("pages/welcome.html")},e=>{Array.isArray(e)&&e.length>0||r()})}catch{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;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
2
2
  ██████████████████████████████████████████████████████████
3
3
  ██████████████████████████████████████████████████████████
4
4
  ████████████████████████████ ██████████████████████████
@@ -23,4 +23,4 @@
23
23
  ██████████████████████████████████████████████████████████
24
24
  ██████████████████████████████████████████████████████████
25
25
  MIT (c) ${new Date().getFullYear()} - Cezar Augusto and the Extension.js authors.
26
- `,"background: transparent; color: #0971fe; "),!t){try{await n()}catch{try{chrome.tabs.create({url:o})}catch{}}return}let i=String(t.url||""),s=i.startsWith(`${a}://newtab`)||i.startsWith(`${a}://welcome`);0;s?await n():r(t,o)})}catch{}}let o=[],i=new Map,s=new Set;try{chrome.storage.session.get(["logger_capture_stacks"],e=>{e?.logger_capture_stacks}),chrome.storage.session.onChanged.addListener((e,t)=>{"session"===t&&"logger_capture_stacks"in e&&e.logger_capture_stacks?.newValue})}catch{}function c(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{let t=16*Math.random()|0;return("x"===e?t:3&t|8).toString(16)})}function l(e){if(o.push(e),o.length>2e3&&o.shift(),"number"==typeof e.tabId){let t=i.get(e.tabId)||[];t.push(e),t.length>1e3&&t.shift(),i.set(e.tabId,t)}for(let t of s)try{let r={type:"append",event:e};t.postMessage(r)}catch{}}chrome.runtime.onConnect.addListener(e=>{if("logger"!==e.name)return;let t=t=>(function(e,t){var r;let n,a;if("subscribe"===t.type){s.add(e);try{e.postMessage({type:"init",events:o})}catch{}return}let i=e.sender?.id;if(i&&i===chrome.runtime.id)return;let l=e.sender?.tab?.id,d=e.sender?.frameId,u=e.sender?.tab?.incognito,m=e.sender?.tab?.windowId;if(r=i||`tab:${l??"unknown"}`,n=Date.now(),(a=h.get(r))?n-a.ts>1e3?(a.ts=n,a.count=1,!!0):(a.count+=1,!!(a.count>200)):(h.set(r,{ts:n,count:1}),!!0))return;let y=b(t.messageParts),v={id:c(),timestamp:Date.now(),level:t.level,context:t.context,messageParts:y,eventType:"dx.signal"===t.eventType||"log"===t.eventType?t.eventType:"log",code:"string"==typeof t.code?f(t.code,128):void 0,status:"ok"===t.status||"warn"===t.status||"fail"===t.status?t.status:void 0,data:p(t.data),remediation:"string"==typeof t.remediation?f(t.remediation,512):void 0,url:t.url,stack:t.stack,errorName:t.errorName,tabId:l,frameId:d,sourceExtensionId:i,incognito:u,windowId:m};g(v)})(e,t);e.onMessage.addListener(t),e.onDisconnect.addListener(()=>{s.delete(e);try{e.onMessage.removeListener(t)}catch{}})}),chrome.action.onClicked.addListener(async()=>{try{await chrome.sidePanel.setPanelBehavior({openPanelOnActionClick:!0})}catch{}});let d=[],u=new Set;function m(e){try{return JSON.stringify(e)}catch{return String(e)}}function g(e){let t=`${e.eventType??"log"}|${e.code??""}|${e.status??""}|${e.level}|${e.context}|${e.tabId??""}|${e.frameId??""}|${e.url??""}|${m(e.messageParts)}|${m(e.data)}`.slice(0,512);if(!u.has(t)){if(u.add(t),d.push(t),d.length>2e3){let e=d.shift();e&&u.delete(e)}if(e.url&&!e.hostname)try{let t=new URL(e.url);e.hostname=`${t.hostname}${t.pathname}`}catch{}if(null!=e.tabId&&null==e.title)try{chrome.tabs.get(e.tabId,t=>{if(chrome.runtime.lastError)return l(e);e.title=t?.title||e.title,l(e)});return}catch{}l(e)}}let h=new Map;function f(e,t=2048){return e.length<=t?e:e.slice(0,t)+"..."}function y(e){try{return JSON.stringify(e)}catch{try{return String(e)}catch{return"[unserializable]"}}}function b(e){try{let t=[];for(let r of e??[])if("string"==typeof r?t.push(f(r)):r instanceof Error?t.push(f(`${r.name}: ${r.message}`)):t.push(f(y(r))),t.join(" ").length>8192)break;return t}catch{return[y(e)]}}function p(e){if(e&&"object"==typeof e)try{let t=JSON.stringify(e);if(!t)return;let r=JSON.parse(t);if(0===Object.keys(r).length)return;return r}catch{return}}function v(e,t,r={}){g({id:c(),timestamp:Date.now(),level:e,context:"background",messageParts:t,url:"string"==typeof r.url?r.url:void 0,tabId:"number"==typeof r.tabId?r.tabId:void 0,frameId:"number"==typeof r.frameId?r.frameId:void 0})}async function x(){let e=(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&&!((t=String(e.name||"").toLowerCase()).includes("extension.js built-in developer tools")||t.includes("extension.js theme"))});if(0===e.length)return{ok:!0,extensionEnabled:null};let t=e.find(e=>e.enabled)||e[e.length-1];return{ok:!0,extensionEnabled:!!t?.enabled,extensionName:t?.name,extensionId:t?.id}}async function w(e){if(e.startsWith("data:"))return e;let t=await fetch(e);if(!t.ok)throw Error(`Failed to fetch icon: ${t.status}`);let r=await t.blob();return await new Promise((e,t)=>{let n=new FileReader;n.onload=()=>e(String(n.result||"")),n.onerror=()=>t(Error("Failed to read icon blob")),n.readAsDataURL(r)})}chrome.runtime.onInstalled.addListener(e=>{v("info",["extension installed",e.reason,e.previousVersion??null])}),chrome.storage.session.get(["logger_events"],e=>{let t=Array.isArray(e?.logger_events)?e.logger_events:[];if(t.length)for(let e of t.slice(-2e3))o.push(e)}),setInterval(()=>{chrome.storage.session.set({logger_events:o.slice(-200)})},2e3),chrome.runtime.onStartup.addListener(()=>{v("info",["extension startup"]);try{v("info",["TEST_LOG: background-start"])}catch{}}),chrome.tabs.onCreated.addListener(e=>{v("info",["tab created"],{tabId:e.id??void 0,url:e.url})}),chrome.tabs.onUpdated.addListener((e,t,r)=>{"loading"===t.status&&v("debug",["tab loading"],{tabId:e,url:r.url}),"complete"===t.status&&v("debug",["tab complete"],{tabId:e,url:r.url}),"string"==typeof t.url&&v("info",["tab url changed",t.url],{tabId:e,url:t.url})}),chrome.tabs.onRemoved.addListener((e,t)=>{v("info",["tab removed",{windowId:t.windowId,isWindowClosing:t.isWindowClosing}],{tabId:e})}),chrome.webNavigation.onBeforeNavigate.addListener(e=>{0===e.frameId&&v("info",["Before navigate"],{tabId:e.tabId,frameId:e.frameId,url:e.url,title:"[navigation]"})}),chrome.webNavigation.onCommitted.addListener(e=>{0===e.frameId&&v("info",["Navigation committed"],{tabId:e.tabId,frameId:e.frameId,url:e.url,title:"[navigation]"})}),chrome.webNavigation.onCompleted.addListener(e=>{0===e.frameId&&v("info",["Navigation completed"],{tabId:e.tabId,frameId:e.frameId,url:e.url,title:"[navigation]"})}),chrome.webNavigation.onErrorOccurred.addListener(e=>{0===e.frameId&&v("error",["Navigation error",e.error],{tabId:e.tabId,frameId:e.frameId,url:e.url,title:"[navigation]"})}),chrome.webNavigation.onHistoryStateUpdated.addListener(e=>{0===e.frameId&&v("info",["History state updated"],{tabId:e.tabId,frameId:e.frameId,url:e.url,title:"[navigation]"})}),chrome.runtime.onMessage.addListener((e,t,r)=>e&&"get-events"===e.type?(r({events:o.slice(-500)}),!0):!!e&&"clear-events"===e.type&&(o.length=0,r({ok:!0}),!0)),chrome.runtime.onMessage.addListener((e,t,r)=>{if((!t?.id||t.id===chrome.runtime.id)&&e){if("resolve-icon-url"===e.type)return e.url&&function(e){if(e.startsWith("data:"))return!0;try{let t=new URL(e);return"moz-extension:"===t.protocol||"chrome-extension:"===t.protocol}catch{return!1}}(e.url)?(w(e.url).then(e=>r({ok:!0,dataUrl:e})).catch(e=>r({ok:!1,error:String(e)})),!0):void r({ok:!1,error:"Unsupported icon URL"});if("get-dx-status"===e.type)return x().then(e=>r(e)).catch(e=>r({ok:!1,error:String(e||"Unknown error")})),!0;if("dx-signal"===e.type){try{var n={level:e.level||"info",context:e.context||"content",messageParts:Array.isArray(e.messageParts)&&e.messageParts.length>0?e.messageParts:[e.code||"DX_SIGNAL"],eventType:e.eventType||"dx.signal",code:e.code,status:e.status,data:e.data,remediation:e.remediation,url:"string"==typeof e.url?e.url:void 0,stack:"string"==typeof e.stack?e.stack:void 0,errorName:"string"==typeof e.errorName?e.errorName:void 0};g({id:c(),timestamp:Date.now(),level:n.level,context:n.context,messageParts:b(n.messageParts||[]),eventType:"dx.signal"===n.eventType||"log"===n.eventType?n.eventType:"log",code:"string"==typeof n.code?f(String(n.code),128):void 0,status:"ok"===n.status||"warn"===n.status||"fail"===n.status?n.status:void 0,data:p(n.data),remediation:"string"==typeof n.remediation?f(n.remediation,512):void 0,url:n.url,stack:n.stack,errorName:n.errorName,tabId:n.tabId,frameId:n.frameId}),r({ok:!0})}catch(e){r({ok:!1,error:String(e||"Unknown error")})}return!0}}}),chrome.runtime.onStartup.addListener(async()=>{await a()}),chrome.runtime.onInstalled.addListener(async()=>{await a()})})();
26
+ `,"background: transparent; color: #0971fe; "),!t){try{await n()}catch{try{chrome.tabs.create({url:o})}catch{}}return}let i=String(t.url||""),s=i.startsWith(`${a}://newtab`)||i.startsWith(`${a}://welcome`);0;s?await n():r(t,o)})}catch{}}let o=[],i=new Map,s=new Set;try{chrome.storage.session.get(["logger_capture_stacks"],e=>{e?.logger_capture_stacks}),chrome.storage.session.onChanged.addListener((e,t)=>{"session"===t&&"logger_capture_stacks"in e&&e.logger_capture_stacks?.newValue})}catch{}function c(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{let t=16*Math.random()|0;return("x"===e?t:3&t|8).toString(16)})}function l(e){if(o.push(e),o.length>2e3&&o.shift(),"number"==typeof e.tabId){let t=i.get(e.tabId)||[];t.push(e),t.length>1e3&&t.shift(),i.set(e.tabId,t)}for(let t of s)try{let r={type:"append",event:e};t.postMessage(r)}catch{}}chrome.runtime.onConnect.addListener(e=>{if("logger"!==e.name)return;let t=t=>(function(e,t){var r;let n,a;if("subscribe"===t.type){s.add(e);try{e.postMessage({type:"init",events:o})}catch{}return}let i=e.sender?.id;if(i&&i===chrome.runtime.id)return;let l=e.sender?.tab?.id,d=e.sender?.frameId,u=e.sender?.tab?.incognito,m=e.sender?.tab?.windowId;if(r=i||`tab:${l??"unknown"}`,n=Date.now(),(a=h.get(r))?n-a.ts>1e3?(a.ts=n,a.count=1,!!0):(a.count+=1,!!(a.count>200)):(h.set(r,{ts:n,count:1}),!!0))return;let y=p(t.messageParts),v={id:c(),timestamp:Date.now(),level:t.level,context:t.context,messageParts:y,eventType:"dx.signal"===t.eventType||"log"===t.eventType?t.eventType:"log",code:"string"==typeof t.code?f(t.code,128):void 0,status:"ok"===t.status||"warn"===t.status||"fail"===t.status?t.status:void 0,data:b(t.data),remediation:"string"==typeof t.remediation?f(t.remediation,512):void 0,url:t.url,stack:t.stack,errorName:t.errorName,tabId:l,frameId:d,sourceExtensionId:i,incognito:u,windowId:m};g(v)})(e,t);e.onMessage.addListener(t),e.onDisconnect.addListener(()=>{s.delete(e);try{e.onMessage.removeListener(t)}catch{}})}),chrome.action.onClicked.addListener(async()=>{try{await chrome.sidePanel.setPanelBehavior({openPanelOnActionClick:!0})}catch{}});let d=[],u=new Set;function m(e){try{return JSON.stringify(e)}catch{return String(e)}}function g(e){let t=`${e.eventType??"log"}|${e.code??""}|${e.status??""}|${e.level}|${e.context}|${e.tabId??""}|${e.frameId??""}|${e.url??""}|${m(e.messageParts)}|${m(e.data)}`.slice(0,512);if(!u.has(t)){if(u.add(t),d.push(t),d.length>2e3){let e=d.shift();e&&u.delete(e)}if(e.url&&!e.hostname)try{let t=new URL(e.url);e.hostname=`${t.hostname}${t.pathname}`}catch{}if(null!=e.tabId&&null==e.title)try{chrome.tabs.get(e.tabId,t=>{if(chrome.runtime.lastError)return l(e);e.title=t?.title||e.title,l(e)});return}catch{}l(e)}}let h=new Map;function f(e,t=2048){return e.length<=t?e:e.slice(0,t)+"..."}function y(e){try{return JSON.stringify(e)}catch{try{return String(e)}catch{return"[unserializable]"}}}function p(e){try{let t=[];for(let r of e??[])if("string"==typeof r?t.push(f(r)):r instanceof Error?t.push(f(`${r.name}: ${r.message}`)):t.push(f(y(r))),t.join(" ").length>8192)break;return t}catch{return[y(e)]}}function b(e){if(e&&"object"==typeof e)try{let t=JSON.stringify(e);if(!t)return;let r=JSON.parse(t);if(0===Object.keys(r).length)return;return r}catch{return}}function v(e,t,r={}){g({id:c(),timestamp:Date.now(),level:e,context:"background",messageParts:t,url:"string"==typeof r.url?r.url:void 0,tabId:"number"==typeof r.tabId?r.tabId:void 0,frameId:"number"==typeof r.frameId?r.frameId:void 0})}async function x(){let e=(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&&!((t=String(e.name||"").toLowerCase()).includes("extension.js built-in developer tools")||t.includes("extension.js theme"))});if(0===e.length)return{ok:!0,extensionEnabled:null};let t=e.find(e=>e.enabled)||e[e.length-1];return{ok:!0,extensionEnabled:!!t?.enabled,extensionName:t?.name,extensionId:t?.id}}async function w(e){if(e.startsWith("data:"))return e;let t=await fetch(e);if(!t.ok)throw Error(`Failed to fetch icon: ${t.status}`);let r=await t.blob();return await new Promise((e,t)=>{let n=new FileReader;n.onload=()=>e(String(n.result||"")),n.onerror=()=>t(Error("Failed to read icon blob")),n.readAsDataURL(r)})}chrome.runtime.onInstalled.addListener(e=>{v("info",["extension installed",e.reason,e.previousVersion??null])}),chrome.storage.session.get(["logger_events"],e=>{let t=Array.isArray(e?.logger_events)?e.logger_events:[];if(t.length)for(let e of t.slice(-2e3))o.push(e)}),setInterval(()=>{chrome.storage.session.set({logger_events:o.slice(-200)})},2e3),chrome.runtime.onStartup.addListener(()=>{v("info",["extension startup"]);try{v("info",["TEST_LOG: background-start"])}catch{}}),chrome.tabs.onCreated.addListener(e=>{v("info",["tab created"],{tabId:e.id??void 0,url:e.url})}),chrome.tabs.onUpdated.addListener((e,t,r)=>{"loading"===t.status&&v("debug",["tab loading"],{tabId:e,url:r.url}),"complete"===t.status&&v("debug",["tab complete"],{tabId:e,url:r.url}),"string"==typeof t.url&&v("info",["tab url changed",t.url],{tabId:e,url:t.url})}),chrome.tabs.onRemoved.addListener((e,t)=>{v("info",["tab removed",{windowId:t.windowId,isWindowClosing:t.isWindowClosing}],{tabId:e})}),chrome.webNavigation.onBeforeNavigate.addListener(e=>{0===e.frameId&&v("info",["Before navigate"],{tabId:e.tabId,frameId:e.frameId,url:e.url,title:"[navigation]"})}),chrome.webNavigation.onCommitted.addListener(e=>{0===e.frameId&&v("info",["Navigation committed"],{tabId:e.tabId,frameId:e.frameId,url:e.url,title:"[navigation]"})}),chrome.webNavigation.onCompleted.addListener(e=>{0===e.frameId&&v("info",["Navigation completed"],{tabId:e.tabId,frameId:e.frameId,url:e.url,title:"[navigation]"})}),chrome.webNavigation.onErrorOccurred.addListener(e=>{0===e.frameId&&v("error",["Navigation error",e.error],{tabId:e.tabId,frameId:e.frameId,url:e.url,title:"[navigation]"})}),chrome.webNavigation.onHistoryStateUpdated.addListener(e=>{0===e.frameId&&v("info",["History state updated"],{tabId:e.tabId,frameId:e.frameId,url:e.url,title:"[navigation]"})}),chrome.runtime.onMessage.addListener((e,t,r)=>e&&"get-events"===e.type?(r({events:o.slice(-500)}),!0):!!e&&"clear-events"===e.type&&(o.length=0,r({ok:!0}),!0)),chrome.runtime.onMessage.addListener((e,t,r)=>{if((!t?.id||t.id===chrome.runtime.id)&&e){if("resolve-icon-url"===e.type)return e.url&&function(e){if(e.startsWith("data:"))return!0;try{let t=new URL(e);return"moz-extension:"===t.protocol||"chrome-extension:"===t.protocol}catch{return!1}}(e.url)?(w(e.url).then(e=>r({ok:!0,dataUrl:e})).catch(e=>r({ok:!1,error:String(e)})),!0):void r({ok:!1,error:"Unsupported icon URL"});if("get-dx-status"===e.type)return x().then(e=>r(e)).catch(e=>r({ok:!1,error:String(e||"Unknown error")})),!0;if("dx-signal"===e.type){try{var n={level:e.level||"info",context:e.context||"content",messageParts:Array.isArray(e.messageParts)&&e.messageParts.length>0?e.messageParts:[e.code||"DX_SIGNAL"],eventType:e.eventType||"dx.signal",code:e.code,status:e.status,data:e.data,remediation:e.remediation,url:"string"==typeof e.url?e.url:void 0,stack:"string"==typeof e.stack?e.stack:void 0,errorName:"string"==typeof e.errorName?e.errorName:void 0};g({id:c(),timestamp:Date.now(),level:n.level,context:n.context,messageParts:p(n.messageParts||[]),eventType:"dx.signal"===n.eventType||"log"===n.eventType?n.eventType:"log",code:"string"==typeof n.code?f(String(n.code),128):void 0,status:"ok"===n.status||"warn"===n.status||"fail"===n.status?n.status:void 0,data:b(n.data),remediation:"string"==typeof n.remediation?f(n.remediation,512):void 0,url:n.url,stack:n.stack,errorName:n.errorName,tabId:n.tabId,frameId:n.frameId}),r({ok:!0})}catch(e){r({ok:!1,error:String(e||"Unknown error")})}return!0}}}),chrome.runtime.onStartup.addListener(async()=>{await a()}),chrome.runtime.onInstalled.addListener(async()=>{await a()})})();