extension 4.1.35 → 4.1.36

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/cli.cjs CHANGED
@@ -365,7 +365,8 @@ var __webpack_modules__ = {
365
365
  function stageCompanionForSession(input) {
366
366
  const { extensionPaths } = input;
367
367
  const cdpOnly = (0, _browser_family__rspack_import_3.v$)(input.browser || '');
368
- if (!input.noOpen && !cdpOnly || !input.stageRoot) return extensionPaths;
368
+ const plain = !input.noOpen && !input.startingUrl && !cdpOnly;
369
+ if (plain || !input.stageRoot) return extensionPaths;
369
370
  const index = extensionPaths.findIndex((p)=>isDevtoolsCompanionPath(p));
370
371
  if (-1 === index) return extensionPaths;
371
372
  const source = extensionPaths[index];
@@ -380,7 +381,8 @@ var __webpack_modules__ = {
380
381
  recursive: true
381
382
  });
382
383
  const flags = {
383
- noOpen: Boolean(input.noOpen)
384
+ noOpen: Boolean(input.noOpen),
385
+ startingUrl: Boolean(input.startingUrl)
384
386
  };
385
387
  node_fs__rspack_import_0.writeFileSync(node_path__rspack_import_1.join(staged, COMPANION_SESSION_FLAGS_FILE), `${JSON.stringify(flags)}\n`, 'utf8');
386
388
  if (cdpOnly) dropNewTabOverride(staged);
@@ -810,6 +812,13 @@ var __webpack_modules__ = {
810
812
  function browserGoneBeforeReady(browser) {
811
813
  return `${getLoggingPrefix('error')} ${capitalizedBrowserName(browser)} exited before the extension loaded, so nothing is running.\nThe dev server keeps watching, but nothing will load until the browser is relaunched. Restart "extension dev".`;
812
814
  }
815
+ function browserUpNotAttached(opts) {
816
+ const name = capitalizedBrowserName(opts.browser);
817
+ const pid = opts.browserPid ? ` (pid ${opts.browserPid})` : '';
818
+ const seconds = Math.round(opts.waitedMs / 1000);
819
+ const profile = opts.profilePath ? opts.profileReused ? `Profile ${pintor__rspack_import_8_default().underline(opts.profilePath)} had been run before: a profile picker, a restore prompt or a stale copy of the extension in it can keep the extension from connecting.` : `Profile ${pintor__rspack_import_8_default().underline(opts.profilePath)} is fresh, so look at the browser window for a dialog or an extensions page error.` : "Look at the browser window for a dialog or an extensions page error.";
820
+ return `${getLoggingPrefix('warn')} ${name}${pid} is up, but the extension has not connected after ${seconds} s.\n${profile}\nDismiss any dialog there, or stop this session and run again on a fresh profile (delete that folder, or pass ${pintor__rspack_import_8_default().yellow('--profile <new path>')}). The session keeps waiting and says "ready" once the extension connects.`;
821
+ }
813
822
  function chromeProcessError(error) {
814
823
  return `${getLoggingPrefix('error')} The Chrome process reported an error.\n${pintor__rspack_import_8_default().red(errorDetail(error))}`;
815
824
  }
@@ -930,10 +939,24 @@ var __webpack_modules__ = {
930
939
  function safariOpening(target) {
931
940
  return `${getLoggingPrefix('info')} Opening ${pintor__rspack_import_8_default().underline(target)}`;
932
941
  }
933
- function safariToolFailed(tool, exitCode, outputTail) {
942
+ function safariToolFailed(tool, exitCode, outputTail, cause) {
934
943
  const code = null === exitCode ? 'no exit code' : `exit ${exitCode}`;
935
944
  const tail = outputTail.trim().length ? `\n${pintor__rspack_import_8_default().gray('── last output ──')}\n${outputTail}` : `\n${pintor__rspack_import_8_default().gray('(no output captured)')}`;
936
- return `${getLoggingPrefix('error')} Safari packaging tool ${pintor__rspack_import_8_default().underline(tool)} failed (${pintor__rspack_import_8_default().red(code)}).${tail}`;
945
+ return `${getLoggingPrefix('error')} Safari packaging tool ${pintor__rspack_import_8_default().underline(tool)} failed (${pintor__rspack_import_8_default().red(code)}).${cause ? `\n${cause}` : ''}${tail}`;
946
+ }
947
+ function safariKnownTeamsList(teams) {
948
+ return teams.map((team)=>team.name ? `${pintor__rspack_import_8_default().yellow(team.id)} (${team.name})` : pintor__rspack_import_8_default().yellow(team.id)).join(', ');
949
+ }
950
+ function safariTeamRemedyLines(team, knownTeams = []) {
951
+ const known = knownTeams.length ? `Set ${pintor__rspack_import_8_default().blue('developmentTeam')} to a team Xcode knows: ${safariKnownTeamsList(knownTeams)}.` : `Set ${pintor__rspack_import_8_default().blue('developmentTeam')} to a team Xcode is signed into.`;
952
+ return [
953
+ `Sign in to Xcode (Settings, Accounts) with the Apple ID that owns team ${pintor__rspack_import_8_default().yellow(team)}.`,
954
+ known,
955
+ `Drop ${pintor__rspack_import_8_default().blue('developmentTeam')} for an ad-hoc build.`
956
+ ];
957
+ }
958
+ function safariNoAccountForTeam(team, knownTeams = []) {
959
+ return `Xcode has no account for team ${pintor__rspack_import_8_default().yellow(team)}, so it couldn't sign the app with it.\n` + safariTeamRemedyLines(team, knownTeams).map((line)=>`- ${line}`).join('\n');
937
960
  }
938
961
  const SAFARI_KEPT_ON_PURPOSE = {
939
962
  world: 'Safari has honored the MAIN world since Safari 18, so the key stays'
@@ -958,14 +981,27 @@ var __webpack_modules__ = {
958
981
  function safariDryRunXcodebuild(cmd) {
959
982
  return `${getLoggingPrefix('info')} xcodebuild: ${pintor__rspack_import_8_default().gray(cmd)}.`;
960
983
  }
961
- function safariNextSteps(appName, signed) {
984
+ const SAFARI_AD_HOC_LOADING = 'Safari runs an ad-hoc build only while unsigned extensions are allowed, and Safari turns that off at quit';
985
+ const SAFARI_TEAM_SIGNED_LOADING = 'A team-signed build needs no toggle, and the Apple Development certificate of an Xcode account signed in on this Mac is enough for local runs, no Developer ID needed';
986
+ const SAFARI_DEVELOPMENT_TEAM_HELP = `sign the Safari app with an Apple Developer team id (safari targets only), so Safari loads it with no per-launch toggle. Without it the build is ad-hoc signed. ${SAFARI_AD_HOC_LOADING} (Settings ▸ Developer ▸ Allow unsigned extensions). ${SAFARI_TEAM_SIGNED_LOADING}`;
987
+ function safariNextSteps(appName, signed, signing = {}) {
962
988
  const name = pintor__rspack_import_8_default().yellow(appName);
963
- const unsignedStep = signed ? '' : ` ${pintor__rspack_import_8_default().gray('1.')} Safari ▸ Settings ▸ Developer ▸ Allow unsigned extensions (Safari forgets it on quit)\n`;
989
+ const unsignedStep = signed ? '' : ` ${pintor__rspack_import_8_default().gray('1.')} Safari ▸ Settings ▸ Developer ▸ Allow unsigned extensions (Safari turns it off at quit, so turn it on after each relaunch)\n`;
964
990
  const enableStep = ` ${pintor__rspack_import_8_default().gray(signed ? '1.' : '2.')} Safari ▸ Settings ▸ Extensions ▸ turn on ${name}\n`;
965
991
  const websitesStep = ` ${pintor__rspack_import_8_default().gray(signed ? '2.' : '3.')} Safari ▸ Settings ▸ Websites ▸ ${name} ▸ For other websites ▸ Allow\n`;
966
992
  const steps = `${getLoggingPrefix('info')} One-time setup to load ${name} in Safari, or pass ${pintor__rspack_import_8_default().blue('--enable-extension')} to let Extension.js do it:\n` + unsignedStep + enableStep + websitesStep + ` ${pintor__rspack_import_8_default().gray('→')} Use a regular Safari window for this, a trip to Settings from the automation window ends the WebDriver session.\n`;
967
- if (signed) return steps + ` ${pintor__rspack_import_8_default().gray('→')} Signed with your team id, so the identity is stable for distribution.`;
968
- return steps + ` ${pintor__rspack_import_8_default().gray('→')} Ad-hoc signed, so Safari lists it only while unsigned extensions are allowed.`;
993
+ if (signed) {
994
+ const team = signing.team ? `team ${pintor__rspack_import_8_default().yellow(signing.team)}` : 'your team id';
995
+ return steps + ` ${pintor__rspack_import_8_default().gray('→')} Signed with ${team}, so Safari loads it with no developer toggle and the identity is stable for distribution.`;
996
+ }
997
+ const adHoc = ` ${pintor__rspack_import_8_default().gray('→')} Ad-hoc signed. ${SAFARI_AD_HOC_LOADING}. With the toggle off after a relaunch, the toolbar button stays but does nothing.\n ${pintor__rspack_import_8_default().gray('→')} Pass ${pintor__rspack_import_8_default().blue('--development-team')} to sign with your team. ${SAFARI_TEAM_SIGNED_LOADING}.\n ${pintor__rspack_import_8_default().gray('→')} Safari keys stored data on the appex id, so ${pintor__rspack_import_8_default().yellow('storage.local')} survives rebuilds.`;
998
+ const requested = String(signing.requestedTeam || '').trim();
999
+ if (!requested) return steps + adHoc;
1000
+ const why = signing.noAccount ? 'Xcode has no account for that team' : 'Xcode did not sign with it';
1001
+ return steps + ` ${pintor__rspack_import_8_default().gray('→')} Ad-hoc signed although ${pintor__rspack_import_8_default().blue('developmentTeam')} ${pintor__rspack_import_8_default().yellow(requested)} was set: ${why}.\n` + safariTeamRemedyLines(requested, signing.knownTeams).map((line)=>` ${pintor__rspack_import_8_default().gray('→')} ${line}`).join('\n');
1002
+ }
1003
+ function safariSigningChanged(appName, before, after) {
1004
+ return `${getLoggingPrefix('info')} ${pintor__rspack_import_8_default().yellow(appName)} is now ${after} signed and the last build was ${before} signed, so Safari treats it as a new extension and the setup steps run again.`;
969
1005
  }
970
1006
  function safariEnableStep(step, before, after, detail) {
971
1007
  const reading = null === before ? `${pintor__rspack_import_8_default().gray('read back')} ${pintor__rspack_import_8_default().yellow(after ?? 'nothing')}` : `${pintor__rspack_import_8_default().gray('read')} ${pintor__rspack_import_8_default().yellow(before)} ${pintor__rspack_import_8_default().gray('→')} ${pintor__rspack_import_8_default().yellow(after ?? 'nothing')}`;
@@ -1013,9 +1049,6 @@ var __webpack_modules__ = {
1013
1049
  function safariBuildUpToDate() {
1014
1050
  return `${getLoggingPrefix('info')} Skipping xcodebuild, the Safari app is up to date with the build.`;
1015
1051
  }
1016
- function safariStorageReset(appName) {
1017
- return `${getLoggingPrefix('warn')} Safari reset the extension's storage: ${pintor__rspack_import_8_default().yellow(appName)} is signed ad hoc, and Safari keeps an extension's storage only for a build signed by a team, so each rebuild starts with an empty ${pintor__rspack_import_8_default().yellow('storage.local')}.\nPass ${pintor__rspack_import_8_default().blue('--development-team <TEAM_ID>')} to keep it across rebuilds.`;
1018
- }
1019
1052
  function safariSkippingConversion() {
1020
1053
  return `${getLoggingPrefix('info')} Skipping the conversion, the Xcode project is up to date with manifest.json.`;
1021
1054
  }
@@ -1206,6 +1239,7 @@ var __webpack_modules__ = {
1206
1239
  Cd: ()=>safariEnabled,
1207
1240
  Cn: ()=>chromeProcessError,
1208
1241
  Cs: ()=>safariToolchainMissing,
1242
+ D$: ()=>safariNoAccountForTeam,
1209
1243
  Dh: ()=>invalidGeckoBinaryPath,
1210
1244
  E8: ()=>chromiumDryRunFlags,
1211
1245
  EE: ()=>geckoAddonLoadRefused,
@@ -1229,6 +1263,7 @@ var __webpack_modules__ = {
1229
1263
  KP: ()=>safariBuildCalled,
1230
1264
  L: ()=>chromiumManifestLoadBlockers,
1231
1265
  LD: ()=>firefoxDryRunBinary,
1266
+ LE: ()=>browserUpNotAttached,
1232
1267
  LT: ()=>browserStderrTail,
1233
1268
  M3: ()=>cdpClientConnected,
1234
1269
  M6: ()=>chromiumExtensionLoadRefused,
@@ -1276,11 +1311,11 @@ var __webpack_modules__ = {
1276
1311
  dw: ()=>devFirefoxProfilePath,
1277
1312
  eK: ()=>copyFromProfileSourceMissing,
1278
1313
  e_: ()=>runningInDevelopment,
1314
+ ei: ()=>safariSigningChanged,
1279
1315
  fL: ()=>safariDryRunConverter,
1280
1316
  fO: ()=>safariNextSteps,
1281
1317
  fR: ()=>cdpClientConnectionError,
1282
1318
  fd: ()=>safariRegistered,
1283
- fl: ()=>safariStorageReset,
1284
1319
  fw: ()=>safariOpening,
1285
1320
  gE: ()=>firefoxProfileRemoteDebuggingOn,
1286
1321
  gX: ()=>firstRunInstallFailed,
@@ -1324,6 +1359,8 @@ var __webpack_modules__ = {
1324
1359
  y1: ()=>safariConverterWarnings,
1325
1360
  y7: ()=>skippingBrowserLaunchDueToCompileErrors,
1326
1361
  yc: ()=>safariDryRunNotBuilding
1362
+ }, {
1363
+ f5: SAFARI_DEVELOPMENT_TEAM_HELP
1327
1364
  });
1328
1365
  },
1329
1366
  "./browsers/browsers-lib/newtab-override.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
@@ -1801,10 +1838,12 @@ var __webpack_modules__ = {
1801
1838
  Jk: ()=>claimReadyPath,
1802
1839
  dT: ()=>describeLaunchFailure,
1803
1840
  NE: ()=>launchFailureCode,
1841
+ Lb: ()=>readReadyExecutorAttached,
1804
1842
  Uf: ()=>readReadyRunId,
1805
1843
  Wi: ()=>stampReadyBrowserExited,
1806
1844
  M: ()=>stampReadyBrowserLaunch,
1807
1845
  dz: ()=>stampReadyBrowserLaunchFailed,
1846
+ xG: ()=>stampReadyBrowserUpNotAttached,
1808
1847
  QP: ()=>stampReadyCdpFault,
1809
1848
  HI: ()=>stampReadyCdpPort,
1810
1849
  hg: ()=>stampReadyExtensionId,
@@ -1910,6 +1949,7 @@ var __webpack_modules__ = {
1910
1949
  if (isForeignRun(ready, runId)) return;
1911
1950
  const profilePath = String(details?.profilePath || '').trim();
1912
1951
  if (profilePath) ready.profilePath = profilePath;
1952
+ if ('boolean' == typeof details?.profileReused) ready.profileReused = details.profileReused;
1913
1953
  if ('number' == typeof details?.browserPid && Number.isFinite(details.browserPid)) ready.browserPid = details.browserPid;
1914
1954
  if ('number' == typeof details?.launcherPid && Number.isFinite(details.launcherPid)) ready.launcherPid = details.launcherPid;
1915
1955
  const extensionId = String(details?.extensionId || '').trim();
@@ -1933,6 +1973,31 @@ var __webpack_modules__ = {
1933
1973
  writeJsonAtomic(readyPath, ready);
1934
1974
  } catch {}
1935
1975
  }
1976
+ function readReadyExecutorAttached(extensionOutputPath, runId) {
1977
+ try {
1978
+ if (!extensionOutputPath) return false;
1979
+ const readyPath = readyPathFor(extensionOutputPath);
1980
+ if (!external_node_fs_.existsSync(readyPath)) return false;
1981
+ const ready = JSON.parse(external_node_fs_.readFileSync(readyPath, 'utf-8'));
1982
+ if (isForeignRun(ready, runId)) return false;
1983
+ return 'string' == typeof ready.executorAttachedAt || 'attached' === ready.runtime;
1984
+ } catch {
1985
+ return false;
1986
+ }
1987
+ }
1988
+ function stampReadyBrowserUpNotAttached(extensionOutputPath, details, runId) {
1989
+ try {
1990
+ if (!extensionOutputPath) return;
1991
+ const readyPath = readyPathFor(extensionOutputPath);
1992
+ if (!external_node_fs_.existsSync(readyPath)) return;
1993
+ const ready = JSON.parse(external_node_fs_.readFileSync(readyPath, 'utf-8'));
1994
+ if (isForeignRun(ready, runId)) return;
1995
+ ready.browserUpNotAttachedAt = new Date().toISOString();
1996
+ ready.browserUpNotAttachedWaitMs = details.waitedMs;
1997
+ ready.browserUpNotAttachedHint = String(details.hint || '').trim() || 'the browser is up, but the extension has not connected';
1998
+ writeJsonAtomic(readyPath, ready);
1999
+ } catch {}
2000
+ }
1936
2001
  function describeLaunchFailure(error) {
1937
2002
  const message = error instanceof Error ? error.message : 'string' == typeof error ? error : String(error?.message ?? error ?? '');
1938
2003
  return (0, messaging.UT)(message).replace(/\s+/g, ' ').trim();
@@ -3743,7 +3808,6 @@ var __webpack_modules__ = {
3743
3808
  '--disable-features=InterestFeedContentSuggestions',
3744
3809
  '--disable-features=Translate',
3745
3810
  '--hide-scrollbars',
3746
- '--mute-audio',
3747
3811
  '--no-default-browser-check',
3748
3812
  '--ash-no-nudges',
3749
3813
  '--disable-search-engine-choice-screen',
@@ -3761,6 +3825,48 @@ var __webpack_modules__ = {
3761
3825
  '--enable-unsafe-extension-debugging',
3762
3826
  '--silent-debugger-extension-api'
3763
3827
  ];
3828
+ const HEADLESS_ONLY_BROWSER_FLAGS = [
3829
+ '--mute-audio'
3830
+ ];
3831
+ const AUTOMATION_CONTROLLED = 'AutomationControlled';
3832
+ const DISABLE_BLINK_FEATURES = '--disable-blink-features=';
3833
+ function asksForAutomation(flags) {
3834
+ return flags.some((flag)=>'--enable-automation' === flag || flag.startsWith('--enable-blink-features=') && flag.slice(24).split(',').some((name)=>name.trim() === AUTOMATION_CONTROLLED));
3835
+ }
3836
+ function withBlinkFeatureDisabled(flags, feature) {
3837
+ const values = [];
3838
+ let at = -1;
3839
+ const rest = [];
3840
+ for (const flag of flags){
3841
+ if (!flag.startsWith(DISABLE_BLINK_FEATURES)) {
3842
+ rest.push(flag);
3843
+ continue;
3844
+ }
3845
+ if (at < 0) at = rest.length;
3846
+ for (const value of flag.slice(DISABLE_BLINK_FEATURES.length).split(',')){
3847
+ const trimmed = value.trim();
3848
+ if (trimmed && !values.includes(trimmed)) values.push(trimmed);
3849
+ }
3850
+ }
3851
+ if (!values.includes(feature)) values.push(feature);
3852
+ rest.splice(at < 0 ? rest.length : at, 0, DISABLE_BLINK_FEATURES + values.join(','));
3853
+ return rest;
3854
+ }
3855
+ function applyLaunchModeFlags(flags, excludeFlags = []) {
3856
+ if ((0, shared_utils.P1)(flags)) {
3857
+ const muted = (0, shared_utils.ov)(HEADLESS_ONLY_BROWSER_FLAGS, excludeFlags);
3858
+ return [
3859
+ ...flags,
3860
+ ...muted.filter((flag)=>!flags.includes(flag))
3861
+ ];
3862
+ }
3863
+ if (asksForAutomation(flags)) return flags;
3864
+ const clearWebdriver = `${DISABLE_BLINK_FEATURES}${AUTOMATION_CONTROLLED}`;
3865
+ if (!(0, shared_utils.ov)([
3866
+ clearWebdriver
3867
+ ], excludeFlags).length) return flags;
3868
+ return withBlinkFeatureDisabled(flags, AUTOMATION_CONTROLLED);
3869
+ }
3764
3870
  function isPlainObject(value) {
3765
3871
  return !!value && 'object' == typeof value && !Array.isArray(value);
3766
3872
  }
@@ -3913,7 +4019,7 @@ var __webpack_modules__ = {
3913
4019
  ...(0, shared_utils.W0)(process.env.EXTENSION_BROWSER_FLAGS)
3914
4020
  ];
3915
4021
  if ((0, shared_utils.ZO)() && !baseFlags.some((flag)=>flag.startsWith('--headless'))) baseFlags.push('--headless=new');
3916
- return (0, shared_utils.Py)(baseFlags);
4022
+ return (0, shared_utils.Py)(applyLaunchModeFlags(baseFlags, excludeFlags));
3917
4023
  }
3918
4024
  function logChromiumDryRun(browser, browserBinaryLocation, chromiumConfig) {
3919
4025
  if ((0, messaging._o)()) (0, messaging._w)(messages.xy(browser));
@@ -4172,6 +4278,24 @@ var __webpack_modules__ = {
4172
4278
  });
4173
4279
  }
4174
4280
  const STDERR_TAIL_LINES = 8;
4281
+ const ATTACH_GRACE_MS = 15000;
4282
+ const ATTACH_POLL_MS = 250;
4283
+ function profileWasRunBefore(profilePath) {
4284
+ if (!profilePath) return false;
4285
+ try {
4286
+ return external_node_fs_.existsSync(external_node_path_.join(profilePath, 'Local State'));
4287
+ } catch {
4288
+ return false;
4289
+ }
4290
+ }
4291
+ function hostsNoDevRuntime(extensionOutputPath) {
4292
+ try {
4293
+ const manifest = JSON.parse(external_node_fs_.readFileSync(external_node_path_.join(extensionOutputPath, 'manifest.json'), 'utf-8'));
4294
+ return Boolean(manifest.theme) && !manifest.background;
4295
+ } catch {
4296
+ return false;
4297
+ }
4298
+ }
4175
4299
  class ChromiumLaunchPlugin {
4176
4300
  getExtensionLoadRefusal() {
4177
4301
  return this.extensionLoadRefused || null;
@@ -4224,7 +4348,7 @@ var __webpack_modules__ = {
4224
4348
  if (hasErrors) return void this.logger.info(messages.y7());
4225
4349
  await this.launchChromium(stats.compilation);
4226
4350
  this.didLaunch = true;
4227
- if (!this.didReportReady && !this.extensionLoadRefused && !this.browserGone) (0, messaging._w)((0, ready_message.G)(stats.compilation.options.mode, this.options.browser));
4351
+ if (!this.didReportReady && !this.readyDeferred && !this.extensionLoadRefused && !this.browserGone) (0, messaging._w)((0, ready_message.G)(stats.compilation.options.mode, this.options.browser));
4228
4352
  } catch (error) {
4229
4353
  this.stampLaunchFailed(stats.compilation, error);
4230
4354
  try {
@@ -4628,8 +4752,11 @@ var __webpack_modules__ = {
4628
4752
  const child = await this.launchWithDirectSpawn(browserBinaryLocation, chromiumConfig, usePipe);
4629
4753
  this.didSpawn = true;
4630
4754
  const launchOutputPath = this.closeHandlerContext?.extensionOutputPath;
4755
+ const launchProfilePath = chromiumConfig.find((flag)=>flag.startsWith('--user-data-dir='))?.slice('--user-data-dir='.length).replace(/^"|"$/g, '');
4756
+ this.profileReused = profileWasRunBefore(launchProfilePath);
4631
4757
  (0, ready_stamp.M)(launchOutputPath, {
4632
- profilePath: chromiumConfig.find((flag)=>flag.startsWith('--user-data-dir='))?.slice('--user-data-dir='.length).replace(/^"|"$/g, ''),
4758
+ profilePath: launchProfilePath,
4759
+ profileReused: this.profileReused,
4633
4760
  browserPid: child?.pid,
4634
4761
  binary: browserBinaryLocation ?? void 0,
4635
4762
  binaryProvenance,
@@ -4695,7 +4822,13 @@ var __webpack_modules__ = {
4695
4822
  if (cdpConfig.extensionLoadRefused) this.extensionLoadRefused = cdpConfig.extensionLoadRefused;
4696
4823
  if (cdpConfig.cdpController) this.ctx.setController(cdpConfig.cdpController);
4697
4824
  }
4698
- reportReady();
4825
+ await this.reportReadyWhenAttached({
4826
+ compilation,
4827
+ enableCdp,
4828
+ reportReady,
4829
+ browserPid: child?.pid,
4830
+ profilePath: launchProfilePath
4831
+ });
4699
4832
  } catch (error) {
4700
4833
  const message = String(error && error.message);
4701
4834
  const hint = /timed out|did not complete/i.test(message) ? " Chrome likely rejected the extension at launch, open chrome://extensions in the dev browser window for the exact error. Common causes: MV3 content_security_policy with 'unsafe-inline', manifest keys Chrome does not support, or manifest references to missing files. Reload/HMR cannot attach until this is fixed." : '';
@@ -4706,9 +4839,49 @@ var __webpack_modules__ = {
4706
4839
  return;
4707
4840
  }
4708
4841
  this.stampCdpFault(compilation, error);
4709
- reportReady();
4842
+ await this.reportReadyWhenAttached({
4843
+ compilation,
4844
+ enableCdp,
4845
+ reportReady,
4846
+ browserPid: child?.pid,
4847
+ profilePath: launchProfilePath
4848
+ });
4710
4849
  }
4711
4850
  }
4851
+ async reportReadyWhenAttached(opts) {
4852
+ const outputPath = this.closeHandlerContext?.extensionOutputPath;
4853
+ const runId = this.closeHandlerContext?.runId;
4854
+ if ('development' !== opts.compilation.options.mode || !opts.enableCdp || !outputPath || this.extensionLoadRefused || hostsNoDevRuntime(outputPath)) return void opts.reportReady();
4855
+ const graceMs = opts.graceMs ?? ATTACH_GRACE_MS;
4856
+ const pollMs = opts.pollMs ?? ATTACH_POLL_MS;
4857
+ const attached = ()=>(0, ready_stamp.Lb)(outputPath, runId);
4858
+ const deadline = Date.now() + graceMs;
4859
+ while(!this.browserGone && !attached() && Date.now() < deadline)await new Promise((resolve)=>setTimeout(resolve, pollMs));
4860
+ if (this.browserGone) return;
4861
+ if (attached()) return void opts.reportReady();
4862
+ const waitedMs = graceMs;
4863
+ const message = messages.LE({
4864
+ browser: this.options.browser,
4865
+ browserPid: opts.browserPid,
4866
+ profilePath: opts.profilePath,
4867
+ profileReused: this.profileReused,
4868
+ waitedMs
4869
+ });
4870
+ (0, messaging.mR)(message);
4871
+ (0, ready_stamp.xG)(outputPath, {
4872
+ waitedMs,
4873
+ hint: (0, messaging.UT)(message)
4874
+ }, runId);
4875
+ this.readyDeferred = true;
4876
+ const watcher = setInterval(()=>{
4877
+ if (this.browserGone || this.didReportReady) return void clearInterval(watcher);
4878
+ if (attached()) {
4879
+ clearInterval(watcher);
4880
+ opts.reportReady();
4881
+ }
4882
+ }, pollMs);
4883
+ watcher.unref?.();
4884
+ }
4712
4885
  async waitForBrowserGone(child, graceMs) {
4713
4886
  if (!child) return;
4714
4887
  const deadline = Date.now() + graceMs;
@@ -4818,6 +4991,8 @@ var __webpack_modules__ = {
4818
4991
  _define_property(this, "ctx", void 0);
4819
4992
  _define_property(this, "didLaunch", void 0);
4820
4993
  _define_property(this, "didReportReady", void 0);
4994
+ _define_property(this, "readyDeferred", void 0);
4995
+ _define_property(this, "profileReused", void 0);
4821
4996
  _define_property(this, "browserGone", void 0);
4822
4997
  _define_property(this, "didSpawn", void 0);
4823
4998
  _define_property(this, "extensionLoadRefused", void 0);
@@ -4828,6 +5003,8 @@ var __webpack_modules__ = {
4828
5003
  this.ctx = ctx;
4829
5004
  this.didLaunch = false;
4830
5005
  this.didReportReady = false;
5006
+ this.readyDeferred = false;
5007
+ this.profileReused = false;
4831
5008
  this.browserGone = false;
4832
5009
  this.didSpawn = false;
4833
5010
  this.closeHandlerContext = null;
@@ -5339,6 +5516,7 @@ var __webpack_modules__ = {
5339
5516
  const extensionsToLoad = (0, companion_session.mO)({
5340
5517
  extensionPaths: configOptions.extension ? (0, runtime_options.fT)(configOptions.extension) : [],
5341
5518
  noOpen: configOptions.noOpen,
5519
+ startingUrl: Boolean((0, runtime_options.cP)(configOptions)),
5342
5520
  stageRoot: profilePath || void 0,
5343
5521
  provision
5344
5522
  });
@@ -8250,6 +8428,67 @@ var __webpack_modules__ = {
8250
8428
  (0, messaging._w)(messages.Aj(xcodebuildCmd));
8251
8429
  }
8252
8430
  var safari_config = __webpack_require__("./browsers/run-safari/safari-launch/safari-config.ts");
8431
+ var external_node_path_ = __webpack_require__("node:path");
8432
+ const ADHOC_SIGNATURE = 'adhoc';
8433
+ function parseCodeSignature(output) {
8434
+ const rows = new Map();
8435
+ for (const line of output.split(/\r?\n/)){
8436
+ const at = line.indexOf('=');
8437
+ if (!(at <= 0)) rows.set(line.slice(0, at).trim(), line.slice(at + 1).trim());
8438
+ }
8439
+ const team = rows.get('TeamIdentifier') || '';
8440
+ const adhoc = 'adhoc' === rows.get('Signature') || !team || /^not set$/i.test(team);
8441
+ if (adhoc) return {
8442
+ signed: false,
8443
+ team: null
8444
+ };
8445
+ return {
8446
+ signed: true,
8447
+ team
8448
+ };
8449
+ }
8450
+ function signatureKey(signature) {
8451
+ return signature.signed && signature.team ? signature.team : ADHOC_SIGNATURE;
8452
+ }
8453
+ function describeSignature(key) {
8454
+ return key && key !== ADHOC_SIGNATURE ? `team ${key}` : 'ad-hoc';
8455
+ }
8456
+ function noAccountForTeam(output) {
8457
+ const hit = /No Account for Team\s+"?([A-Za-z0-9]+)"?/i.exec(output);
8458
+ return hit ? hit[1] : null;
8459
+ }
8460
+ function parseXcodeTeams(output) {
8461
+ const teams = new Map();
8462
+ for (const block of output.split('{')){
8463
+ const id = /teamID\s*=\s*"?([A-Za-z0-9]+)"?\s*;/.exec(block);
8464
+ if (!id || teams.has(id[1])) continue;
8465
+ const name = /teamName\s*=\s*"?([^";]*)"?\s*;/.exec(block);
8466
+ teams.set(id[1], {
8467
+ id: id[1],
8468
+ name: name?.[1].trim() || null
8469
+ });
8470
+ }
8471
+ return [
8472
+ ...teams.values()
8473
+ ];
8474
+ }
8475
+ function signatureRecordPath(config) {
8476
+ return external_node_path_.join(config.projectLocation, '.signature');
8477
+ }
8478
+ function readSignatureRecord(config) {
8479
+ try {
8480
+ const stored = external_node_fs_.readFileSync(signatureRecordPath(config), 'utf8').trim();
8481
+ return stored || null;
8482
+ } catch {
8483
+ return null;
8484
+ }
8485
+ }
8486
+ function saveSignatureRecord(config, signature) {
8487
+ external_node_fs_.mkdirSync(external_node_path_.dirname(signatureRecordPath(config)), {
8488
+ recursive: true
8489
+ });
8490
+ external_node_fs_.writeFileSync(signatureRecordPath(config), signatureKey(signature), 'utf8');
8491
+ }
8253
8492
  var external_node_child_process_ = __webpack_require__("node:child_process");
8254
8493
  function isMacOS() {
8255
8494
  return 'darwin' === process.platform;
@@ -8454,7 +8693,24 @@ var __webpack_modules__ = {
8454
8693
  String(port)
8455
8694
  ]),
8456
8695
  listAutomationPids: ()=>listPidsWhere(isAutomationSafariArgs),
8457
- listAppPids: (appPath)=>listPidsWhere((args)=>isContainerAppArgs(appPath, args))
8696
+ listAppPids: (appPath)=>listPidsWhere((args)=>isContainerAppArgs(appPath, args)),
8697
+ readCodeSignature: (appPath)=>runTool('codesign', [
8698
+ '-dv',
8699
+ '--verbose=2',
8700
+ appPath
8701
+ ], {
8702
+ quiet: true
8703
+ }),
8704
+ readXcodeTeams: async ()=>{
8705
+ const { ok, output } = await runTool('defaults', [
8706
+ 'read',
8707
+ 'com.apple.dt.Xcode',
8708
+ 'IDEProvisioningTeams'
8709
+ ], {
8710
+ quiet: true
8711
+ });
8712
+ return ok ? output : '';
8713
+ }
8458
8714
  };
8459
8715
  }
8460
8716
  var external_node_http_ = __webpack_require__("node:http");
@@ -8464,6 +8720,8 @@ var __webpack_modules__ = {
8464
8720
  const SESSION_CREATE_MS = 30000;
8465
8721
  const SESSION_CLOSE_MS = 5000;
8466
8722
  const AUTOMATION_QUIT_MS = 3000;
8723
+ const WEBDRIVER_NOT_ASKED_YET = 'the launcher has not asked safaridriver for a session yet: it opens the app and enables the extension first, then asks, and this line is replaced by the session or by the reason it got none';
8724
+ const WEBDRIVER_SESSION_PENDING = `the launcher is asking safaridriver for a session now: the request alone waits up to ${SESSION_CREATE_MS / 1000} s, and this line is replaced by the session or by the reason it got none`;
8467
8725
  const activeSessions = new Set();
8468
8726
  const activeDrivers = new Set();
8469
8727
  let webdriver_handlersInstalled = false;
@@ -8697,7 +8955,7 @@ var __webpack_modules__ = {
8697
8955
  if ('0' === value) return 'off';
8698
8956
  return value;
8699
8957
  }
8700
- async function enableThroughSafariUi(host, config, appPath, logger) {
8958
+ async function enableThroughSafariUi(host, config, appPath, logger, signedTeam) {
8701
8959
  const uiTools = host.uiTools || (0, safari_ui.Uw)();
8702
8960
  const access = await (0, safari_ui.d8)(uiTools);
8703
8961
  if (!access.granted) {
@@ -8708,7 +8966,7 @@ var __webpack_modules__ = {
8708
8966
  const report = await (0, safari_ui.Hm)({
8709
8967
  target: {
8710
8968
  bundleId: config.bundleIdentifier,
8711
- developmentTeam: config.developmentTeam
8969
+ developmentTeam: signedTeam ?? void 0
8712
8970
  },
8713
8971
  appPath,
8714
8972
  tools: uiTools,
@@ -8726,6 +8984,24 @@ var __webpack_modules__ = {
8726
8984
  return false;
8727
8985
  }
8728
8986
  }
8987
+ async function readAppSignature(tools, appPath) {
8988
+ try {
8989
+ const { output } = await tools.readCodeSignature(appPath);
8990
+ return parseCodeSignature(output);
8991
+ } catch {
8992
+ return {
8993
+ signed: false,
8994
+ team: null
8995
+ };
8996
+ }
8997
+ }
8998
+ async function listXcodeTeams(tools) {
8999
+ try {
9000
+ return parseXcodeTeams(await tools.readXcodeTeams());
9001
+ } catch {
9002
+ return [];
9003
+ }
9004
+ }
8729
9005
  function describePackage(config) {
8730
9006
  return {
8731
9007
  appName: config.appName,
@@ -8778,8 +9054,11 @@ var __webpack_modules__ = {
8778
9054
  } catch {}
8779
9055
  }
8780
9056
  async function holdWebDriverSession(tools, config, logger) {
8781
- await closeSafariWebDriverSessions();
8782
9057
  const runId = (0, ready_stamp.Uf)(config.extensionDir);
9058
+ (0, ready_stamp.ZC)(config.extensionDir, {
9059
+ unavailableReason: WEBDRIVER_SESSION_PENDING
9060
+ }, runId);
9061
+ await closeSafariWebDriverSessions();
8783
9062
  const outcome = await openSafariWebDriverSession(tools);
8784
9063
  if (outcome.session) {
8785
9064
  const { port, sessionId } = outcome.session;
@@ -8800,7 +9079,6 @@ var __webpack_modules__ = {
8800
9079
  const config = (0, safari_config.F7)(compilation, host);
8801
9080
  const converterArgs = (0, safari_config.w7)(config);
8802
9081
  const xcodebuildArgs = (0, safari_config.vx)(config);
8803
- const isSigned = Boolean(config.developmentTeam);
8804
9082
  if (host.dryRun) {
8805
9083
  logSafariDryRun(`xcrun ${converterArgs.join(' ')}`, `xcodebuild ${xcodebuildArgs.join(' ')}`);
8806
9084
  return completePackage(config, logger, mode);
@@ -8847,6 +9125,7 @@ var __webpack_modules__ = {
8847
9125
  } else if ('full' === mode) logger.info?.(messages.oM());
8848
9126
  const buildFingerprint = (0, safari_config.XE)(config, xcodebuildArgs);
8849
9127
  const reuseBuild = !needsConversion && (0, safari_config.uO)(config, buildFingerprint);
9128
+ let buildOutput = '';
8850
9129
  if (reuseBuild) {
8851
9130
  if ('full' === mode) logger.info?.(messages.xx());
8852
9131
  } else {
@@ -8854,13 +9133,30 @@ var __webpack_modules__ = {
8854
9133
  const built = await tools.runXcodebuild(xcodebuildArgs);
8855
9134
  if (!built.ok) {
8856
9135
  const tail = toolOutputTail(built.output);
8857
- logger.error?.(messages.A('xcodebuild', built.code, tail));
8858
- throw new Error(`xcodebuild failed (exit ${built.code})\n${tail}`);
9136
+ const missingTeam = noAccountForTeam(built.output);
9137
+ const cause = missingTeam ? messages.D$(missingTeam, await listXcodeTeams(tools)) : void 0;
9138
+ logger.error?.(messages.A('xcodebuild', built.code, tail, cause));
9139
+ throw new Error(`xcodebuild failed (exit ${built.code})\n${cause ? `${cause}\n` : ''}${tail}`);
8859
9140
  }
9141
+ buildOutput = built.output;
8860
9142
  (0, safari_config.q_)(config, buildFingerprint);
8861
- if (host.announceDevReady && !isSigned) logger.warn?.(messages.fl(config.appName));
8862
9143
  }
8863
9144
  const appPath = (0, safari_config.fd)(config);
9145
+ const signature = await readAppSignature(tools, appPath);
9146
+ const isSigned = signature.signed;
9147
+ const previousSignature = readSignatureRecord(config);
9148
+ const requestedTeam = String(config.developmentTeam || '').trim();
9149
+ const noAccount = Boolean(noAccountForTeam(buildOutput));
9150
+ const signingNote = {
9151
+ team: signature.team,
9152
+ requestedTeam: requestedTeam || void 0,
9153
+ noAccount,
9154
+ knownTeams: !isSigned && requestedTeam ? await listXcodeTeams(tools) : []
9155
+ };
9156
+ if (!reuseBuild) {
9157
+ saveSignatureRecord(config, signature);
9158
+ if (null !== previousSignature && previousSignature !== signatureKey(signature)) logger.info?.(messages.ei(config.appName, describeSignature(previousSignature), describeSignature(signatureKey(signature))));
9159
+ }
8864
9160
  if ('resync' === mode) {
8865
9161
  if (!reuseBuild) logger.info?.(messages.cF(config.appName));
8866
9162
  return describePackage(config);
@@ -8885,13 +9181,16 @@ var __webpack_modules__ = {
8885
9181
  binaryProvenance: config.safariBinary ? 'pinned' : 'system',
8886
9182
  extensionId: `${config.bundleIdentifier}.Extension`
8887
9183
  }, (0, ready_stamp.Uf)(config.extensionDir));
9184
+ if (host.announceDevReady) (0, ready_stamp.ZC)(config.extensionDir, {
9185
+ unavailableReason: WEBDRIVER_NOT_ASKED_YET
9186
+ }, (0, ready_stamp.Uf)(config.extensionDir));
8888
9187
  if (!browserPid) logger.warn?.(messages.jn(config.appName));
8889
- if (!host.enableExtension) logger.info?.(messages.fO(config.appName, isSigned));
9188
+ if (!host.enableExtension) logger.info?.(messages.fO(config.appName, isSigned, signingNote));
8890
9189
  if (await confirmRegisteredWithSafari(tools, config.bundleIdentifier)) logger.info?.(messages.fd(config.appName));
8891
9190
  else logger.info?.(messages.qY(config.appName));
8892
9191
  if (host.enableExtension) {
8893
- const enabled = await enableThroughSafariUi(host, config, appPath, logger);
8894
- if (!enabled) logger.info?.(messages.fO(config.appName, isSigned));
9192
+ const enabled = await enableThroughSafariUi(host, config, appPath, logger, signature.team);
9193
+ if (!enabled) logger.info?.(messages.fO(config.appName, isSigned, signingNote));
8895
9194
  }
8896
9195
  if (host.announceDevReady) {
8897
9196
  await holdWebDriverSession(tools, config, logger);
@@ -10234,6 +10533,7 @@ function describeButton(b) {
10234
10533
  E_LOCALES_LAYOUT: 'E_LOCALES_LAYOUT',
10235
10534
  E_WAR_INVALID: 'E_WAR_INVALID',
10236
10535
  E_DEV_SESSION_DIST_SHARED: 'E_DEV_SESSION_DIST_SHARED',
10536
+ E_PROD_LOOPBACK_ORIGIN: 'E_PROD_LOOPBACK_ORIGIN',
10237
10537
  E_BACKGROUND_REQUIRED: 'E_BACKGROUND_REQUIRED',
10238
10538
  E_CONTENT_SCRIPT_SYNTAX: 'E_CONTENT_SCRIPT_SYNTAX',
10239
10539
  E_NO_ENTRYPOINTS: 'E_NO_ENTRYPOINTS',
@@ -11166,7 +11466,7 @@ function describeButton(b) {
11166
11466
  }
11167
11467
  var messaging = __webpack_require__("./helpers/messaging.ts");
11168
11468
  const TEMPLATE_CORPUS_REPO = 'extension-js/examples';
11169
- const TEMPLATE_CORPUS_REF = '4753cbd121dac8784f4cb5c515b773f87ebff3b4';
11469
+ const TEMPLATE_CORPUS_REF = '6443985200d0a27526662fc7be5d13fe66a0fa2b';
11170
11470
  const TEMPLATE_CORPUS_SLUGS = [
11171
11471
  'action',
11172
11472
  'action-locales',
@@ -13716,6 +14016,7 @@ Cross-browser compatibility
13716
14016
  });
13717
14017
  });
13718
14018
  }
14019
+ var messages = __webpack_require__("./browsers/browsers-lib/messages.ts");
13719
14020
  var safari_launch = __webpack_require__("./browsers/run-safari/safari-launch/index.ts");
13720
14021
  var safari_config = __webpack_require__("./browsers/run-safari/safari-launch/safari-config.ts");
13721
14022
  var safari_packager = __webpack_require__("./browsers/run-safari/safari-packager.ts");
@@ -13956,7 +14257,7 @@ Cross-browser compatibility
13956
14257
  exitWithFailure(error.code);
13957
14258
  }
13958
14259
  function registerBuildCommand(program) {
13959
- program.command('build').arguments('[project-name]').usage('[path-to-remote-extension] [options]').description(commandDescriptions.build).option(`--browser <${vendors.I9}>`, 'specify a browser/engine to run. Defaults to `chromium`. `safari` builds a Safari app via Xcode (macOS only)').option('--polyfill [boolean]', 'whether or not to apply the cross-browser polyfill. Defaults to `false` (`dev` and `start` default to `true`)', vendors.sJ).option('--no-polyfill', 'disable the cross-browser polyfill').option('--zip [boolean]', 'whether or not to compress the extension into a ZIP file. Defaults to `false`', vendors.sJ).option('--zip-source [boolean]', 'whether or not to include the source files in the ZIP file. Defaults to `false`', vendors.sJ).option('--zip-filename <string>', 'specify the name of the ZIP file, the browser name is appended. Defaults to the extension name and version').option('--out-dir <path>', 'write the build to `<path>/<browser>` instead of `dist/<browser>`, relative to the project root, so it can run beside a dev session that serves `dist`').option('--silent [boolean]', 'suppress the build summary output. Defaults to `false`', vendors.sJ).option('--addon-lint [boolean]', 'check Firefox builds against addons.mozilla.org rules with addons-linter when it is installed. Findings print as warnings. Defaults to `true`', vendors.sJ).option('--no-addon-lint', 'skip the addons.mozilla.org lint of Firefox builds').option('--minify [boolean]', 'minify first-party code in production builds. Defaults to `true`, and to `false` for `opera`, whose store rejects minified code', vendors.sJ).option('--no-minify', 'ship readable first-party code, the Opera Add-ons review requirement').option('--install [boolean]', '[internal] install project dependencies when missing', vendors.sJ).option('--extensions <list>', 'comma-separated list of companion extensions or store URLs to load').option('--mode <development|production|none>', 'bundler mode override (also sets NODE_ENV). Defaults to `production`').option('--open [boolean]', 'open the built Safari app after packaging (safari targets only). Defaults to `false`', vendors.sJ).option('--app-name <name>', 'override the Safari app name (safari targets only). Defaults to the manifest `name`').option('--bundle-id <reverse.dns>', 'set a user-owned Safari bundle identifier (safari targets only). Defaults to a generated dev.extensionjs.* id shared by every build of the same source, so set your own before the first submission').option('--development-team <id>', 'sign the Safari app with an Apple Developer team id (safari targets only). Without it the build is ad-hoc signed, which Safari loads locally with no per-launch toggle. Use a team id for a stable identity you can distribute').option('--macos-only [boolean]', 'generate a macOS-only Safari Xcode project (safari targets only). Pass `false` for a universal macOS + iOS project. Defaults to `true`', vendors.sJ).option('--force-regenerate', 'regenerate the Safari Xcode project even when up to date (safari targets only)').option('--output <pretty|json>', 'result format. Use json for a schema-1 envelope on stdout').addOption(new external_commander_namespaceObject.Option('--debug', 'print maintainer diagnostics alongside normal output')).addOption(new external_commander_namespaceObject.Option('--author, --author-mode', 'deprecated alias for --debug').hideHelp()).action(async (pathOrRemoteUrl, { browser: cliBrowser, ...buildOptions })=>{
14260
+ program.command('build').arguments('[project-name]').usage('[path-to-remote-extension] [options]').description(commandDescriptions.build).option(`--browser <${vendors.I9}>`, 'specify a browser/engine to run. Defaults to `chromium`. `safari` builds a Safari app via Xcode (macOS only)').option('--polyfill [boolean]', 'whether or not to apply the cross-browser polyfill. Defaults to `false` (`dev` and `start` default to `true`)', vendors.sJ).option('--no-polyfill', 'disable the cross-browser polyfill').option('--zip [boolean]', 'whether or not to compress the extension into a ZIP file. Defaults to `false`', vendors.sJ).option('--zip-source [boolean]', 'whether or not to include the source files in the ZIP file. Defaults to `false`', vendors.sJ).option('--zip-filename <string>', 'specify the name of the ZIP file, the browser name is appended. Defaults to the extension name and version').option('--out-dir <path>', 'write the build to `<path>/<browser>` instead of `dist/<browser>`, relative to the project root, so it can run beside a dev session that serves `dist`').option('--silent [boolean]', 'suppress the build summary output. Defaults to `false`', vendors.sJ).option('--addon-lint [boolean]', 'check Firefox builds against addons.mozilla.org rules with addons-linter when it is installed. Findings print as warnings. Defaults to `true`', vendors.sJ).option('--no-addon-lint', 'skip the addons.mozilla.org lint of Firefox builds').option('--minify [boolean]', 'minify first-party code in production builds. Defaults to `true`, and to `false` for `opera`, whose store rejects minified code', vendors.sJ).option('--no-minify', 'ship readable first-party code, the Opera Add-ons review requirement').option('--install [boolean]', '[internal] install project dependencies when missing', vendors.sJ).option('--extensions <list>', 'comma-separated list of companion extensions or store URLs to load').option('--mode <development|production|none>', 'bundler mode override (also sets NODE_ENV). Defaults to `production`').option('--open [boolean]', 'open the built Safari app after packaging (safari targets only). Defaults to `false`', vendors.sJ).option('--app-name <name>', 'override the Safari app name (safari targets only). Defaults to the manifest `name`').option('--bundle-id <reverse.dns>', 'set a user-owned Safari bundle identifier (safari targets only). Defaults to a generated dev.extensionjs.* id shared by every build of the same source, so set your own before the first submission').option('--development-team <id>', messages.f5).option('--macos-only [boolean]', 'generate a macOS-only Safari Xcode project (safari targets only). Pass `false` for a universal macOS + iOS project. Defaults to `true`', vendors.sJ).option('--force-regenerate', 'regenerate the Safari Xcode project even when up to date (safari targets only)').option('--output <pretty|json>', 'result format. Use json for a schema-1 envelope on stdout').addOption(new external_commander_namespaceObject.Option('--debug', 'print maintainer diagnostics alongside normal output')).addOption(new external_commander_namespaceObject.Option('--author, --author-mode', 'deprecated alias for --debug').hideHelp()).action(async (pathOrRemoteUrl, { browser: cliBrowser, ...buildOptions })=>{
13960
14261
  const browser = cliBrowser ?? await resolveConfigBrowser(pathOrRemoteUrl || process.cwd(), 'build') ?? 'chromium';
13961
14262
  if (buildOptions.debug || buildOptions.author || buildOptions.authorMode) {
13962
14263
  process.env.EXTENSION_DEBUG = '1';
@@ -14638,7 +14939,7 @@ Cross-browser compatibility
14638
14939
  return Number.isFinite(parsed) && parsed >= 0 ? Math.floor(parsed) : 8080;
14639
14940
  }
14640
14941
  function registerDevCommand(program) {
14641
- program.command('dev').arguments('[project-path|remote-url]').usage('[project-path|remote-url] [options]').description(commandDescriptions.dev).addHelpText('after', "\nAdditional options:\n --no-browser stop the browser launch, the dev server still starts\n --no-reload emit a dev-mode dist without the content-script reload runtime, tabs need a manual reload to see changes\n --wait wait for ready contract and exit, pair with --output json for machine output\n" + BROWSER_LAUNCH_HELP_FOOTER).option('--profile <path-to-file | boolean>', 'what path to use for the browser profile. A boolean value of false sets the profile to the default user profile. Defaults to a fresh profile').option(`-b, --browser <${vendors.I9}>`, 'specify a browser/engine to run. Defaults to `chromium`. `safari` builds and opens a Safari app via Xcode (macOS only)').option('--chromium-binary <path-to-binary>', 'specify a path to the Chromium binary. This option overrides the --browser setting. Defaults to the system default').addOption(geckoBinaryOption()).addOption(firefoxBinaryAliasOption()).option('--safari-binary <path-to-binary>', 'specify the Safari binary to open after packaging (safari targets only)').option('--app-name <name>', 'override the Safari app name (safari targets only). Defaults to the manifest `name`').option('--bundle-id <reverse.dns>', 'set a user-owned Safari bundle identifier (safari targets only). Defaults to a generated dev.extensionjs.* id shared by every build of the same source, so set your own before the first submission').option('--development-team <id>', 'sign the Safari app with an Apple Developer team id (safari targets only). Without it the build is ad-hoc signed, which Safari loads locally with no per-launch toggle. Use a team id for a stable identity you can distribute').option('--macos-only [boolean]', 'generate a macOS-only Safari Xcode project (safari targets only). Pass `false` for a universal macOS + iOS project. Defaults to `true`', vendors.sJ).option('--force-regenerate', 'regenerate the Safari Xcode project even when up to date (safari targets only)').option('--enable-extension', 'turn the extension on in Safari Settings and allow it on other websites through macOS Accessibility, after the one-time grant for your terminal app (safari targets only)').option('--polyfill [boolean]', 'whether or not to apply the cross-browser polyfill. Defaults to `true` (`build` defaults to `false`)', vendors.sJ).option('--no-polyfill', 'disable the cross-browser polyfill').option('--no-open', NO_OPEN_FLAG_DESCRIPTION).option('--starting-url <url>', 'specify the starting URL for the browser. Defaults to `undefined`').option('--port <port>', 'specify the port to use for the development server. Defaults to `8080`').option('--host <host>', 'specify the host to bind the dev server to. Use 0.0.0.0 for Docker/devcontainers, and --allowed-hosts for a name other than localhost. Defaults to `127.0.0.1`').option('--public-host <host>', 'connectable host the browser (HMR + reload bridge) dials when it differs from the bind host (e.g. a remote/devcontainer). Defaults to the bind host, or 127.0.0.1 when bound to 0.0.0.0').option('--allowed-hosts <list>', 'comma-separated host names the dev server answers besides localhost, IP addresses and --public-host (docker service names, tunnels, *.local). A leading dot allows every subdomain').option('--log-context <list>', `[experimental] comma-separated contexts to include (${LOG_CONTEXTS.join(',')}). Use \`all\` to include all contexts (default)`).option('--logs <off|error|warn|info|debug|trace|all>', '[experimental] minimum centralized logger level to display in terminal (default: off)').option('--log-format <pretty|json|ndjson>', '[experimental] output format for logger events. Defaults to `pretty`').option('--no-log-timestamps', 'disable ISO timestamps in pretty output').option('--no-log-color', 'disable color in pretty output').option('--log-url <pattern>', '[experimental] only show logs where event.url matches this substring or regex (/re/i)').option('--log-tab <id>', 'only show logs for a specific tabId (number)').option('--extensions <list>', 'comma-separated list of companion extensions or store URLs to load').option('--install [boolean]', '[internal] install project dependencies when missing', vendors.sJ).option('--wait [boolean]', 'wait for dist/extension-js/<browser>/ready.json and exit', vendors.sJ).option('--wait-timeout <ms>', 'timeout in milliseconds when using --wait (default: 60000)').option('--output <pretty|json>', 'result format. Use json for a schema-1 envelope on stdout').addOption(new external_commander_namespaceObject.Option('--wait-format <pretty|json>').hideHelp()).addOption(new external_commander_namespaceObject.Option('--debug', 'print maintainer diagnostics alongside normal output')).addOption(new external_commander_namespaceObject.Option('--author, --author-mode', 'deprecated alias for --debug').hideHelp()).option('--allow-control', 'enable the agent-bridge control channel for bounded act (storage/reload/open): see `extension reload|storage|open`').option('--allow-eval', 'additionally enable `extension eval` (implies --allow-control, runs arbitrary code in a context, writes a 0600 session token)').option('--parent-pid <pid>', 'exit when the given process dies. For wrappers that spawn `extension dev`, so a leaked dev server can never outlive its owner').action(async (pathOrRemoteUrl, options, command)=>{
14942
+ program.command('dev').arguments('[project-path|remote-url]').usage('[project-path|remote-url] [options]').description(commandDescriptions.dev).addHelpText('after', "\nAdditional options:\n --no-browser stop the browser launch, the dev server still starts\n --no-reload emit a dev-mode dist without the content-script reload runtime, tabs need a manual reload to see changes\n --wait wait for ready contract and exit, pair with --output json for machine output\n" + BROWSER_LAUNCH_HELP_FOOTER).option('--profile <path-to-file | boolean>', 'what path to use for the browser profile. A boolean value of false sets the profile to the default user profile. Defaults to a fresh profile').option(`-b, --browser <${vendors.I9}>`, 'specify a browser/engine to run. Defaults to `chromium`. `safari` builds and opens a Safari app via Xcode (macOS only)').option('--chromium-binary <path-to-binary>', 'specify a path to the Chromium binary. This option overrides the --browser setting. Defaults to the system default').addOption(geckoBinaryOption()).addOption(firefoxBinaryAliasOption()).option('--safari-binary <path-to-binary>', 'specify the Safari binary to open after packaging (safari targets only)').option('--app-name <name>', 'override the Safari app name (safari targets only). Defaults to the manifest `name`').option('--bundle-id <reverse.dns>', 'set a user-owned Safari bundle identifier (safari targets only). Defaults to a generated dev.extensionjs.* id shared by every build of the same source, so set your own before the first submission').option('--development-team <id>', messages.f5).option('--macos-only [boolean]', 'generate a macOS-only Safari Xcode project (safari targets only). Pass `false` for a universal macOS + iOS project. Defaults to `true`', vendors.sJ).option('--force-regenerate', 'regenerate the Safari Xcode project even when up to date (safari targets only)').option('--enable-extension', 'turn the extension on in Safari Settings and allow it on other websites through macOS Accessibility, after the one-time grant for your terminal app (safari targets only)').option('--polyfill [boolean]', 'whether or not to apply the cross-browser polyfill. Defaults to `true` (`build` defaults to `false`)', vendors.sJ).option('--no-polyfill', 'disable the cross-browser polyfill').option('--no-open', NO_OPEN_FLAG_DESCRIPTION).option('--starting-url <url>', 'specify the starting URL for the browser. Defaults to `undefined`').option('--port <port>', 'specify the port to use for the development server. Defaults to `8080`').option('--host <host>', 'specify the host to bind the dev server to. Use 0.0.0.0 for Docker/devcontainers, and --allowed-hosts for a name other than localhost. Defaults to `127.0.0.1`').option('--public-host <host>', 'connectable host the browser (HMR + reload bridge) dials when it differs from the bind host (e.g. a remote/devcontainer). Defaults to the bind host, or 127.0.0.1 when bound to 0.0.0.0').option('--allowed-hosts <list>', 'comma-separated host names the dev server answers besides localhost, IP addresses and --public-host (docker service names, tunnels, *.local). A leading dot allows every subdomain').option('--log-context <list>', `[experimental] comma-separated contexts to include (${LOG_CONTEXTS.join(',')}). Use \`all\` to include all contexts (default)`).option('--logs <off|error|warn|info|debug|trace|all>', '[experimental] minimum centralized logger level to display in terminal (default: off)').option('--log-format <pretty|json|ndjson>', '[experimental] output format for logger events. Defaults to `pretty`').option('--no-log-timestamps', 'disable ISO timestamps in pretty output').option('--no-log-color', 'disable color in pretty output').option('--log-url <pattern>', '[experimental] only show logs where event.url matches this substring or regex (/re/i)').option('--log-tab <id>', 'only show logs for a specific tabId (number)').option('--extensions <list>', 'comma-separated list of companion extensions or store URLs to load').option('--install [boolean]', '[internal] install project dependencies when missing', vendors.sJ).option('--wait [boolean]', 'wait for dist/extension-js/<browser>/ready.json and exit', vendors.sJ).option('--wait-timeout <ms>', 'timeout in milliseconds when using --wait (default: 60000)').option('--output <pretty|json>', 'result format. Use json for a schema-1 envelope on stdout').addOption(new external_commander_namespaceObject.Option('--wait-format <pretty|json>').hideHelp()).addOption(new external_commander_namespaceObject.Option('--debug', 'print maintainer diagnostics alongside normal output')).addOption(new external_commander_namespaceObject.Option('--author, --author-mode', 'deprecated alias for --debug').hideHelp()).option('--allow-control', 'enable the agent-bridge control channel for bounded act (storage/reload/open): see `extension reload|storage|open`').option('--allow-eval', 'additionally enable `extension eval` (implies --allow-control, runs arbitrary code in a context, writes a 0600 session token)').option('--parent-pid <pid>', 'exit when the given process dies. For wrappers that spawn `extension dev`, so a leaked dev server can never outlive its owner').action(async (pathOrRemoteUrl, options, command)=>{
14642
14943
  const { browser: cliBrowser, ...devOptions } = options;
14643
14944
  const browser = cliBrowser ?? await resolveConfigBrowser(pathOrRemoteUrl || process.cwd(), 'dev') ?? 'chromium';
14644
14945
  if (devOptions.debug || devOptions.author || devOptions.authorMode) {
@@ -16021,7 +16322,6 @@ Cross-browser compatibility
16021
16322
  await exitAfterDrain(0);
16022
16323
  });
16023
16324
  }
16024
- var messages = __webpack_require__("./browsers/browsers-lib/messages.ts");
16025
16325
  var safari_ui = __webpack_require__("./browsers/run-safari/safari-ui/index.ts");
16026
16326
  const COMMAND = 'safari';
16027
16327
  let injectedTools;