extension 4.1.21 → 4.1.23
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/{84.cjs → 597.cjs} +78 -1
- package/dist/browsers.cjs +294 -33
- package/dist/cli.cjs +410 -37
- package/dist/extension/browsers/browsers-lib/messages.d.ts +1 -1
- package/dist/extension/browsers/browsers-lib/process-teardown.d.ts +3 -0
- package/dist/extension/browsers/browsers-lib/ready-stamp.d.ts +1 -0
- package/dist/extension/browsers/browsers-lib/resolve-live-pid.d.ts +25 -0
- package/dist/extension/browsers/browsers-types.d.ts +1 -1
- package/dist/extension/browsers/run-chromium/cdp/cdp-extension-controller/index.d.ts +2 -0
- package/dist/extension/browsers/run-chromium/cdp/ensure-developer-mode.d.ts +12 -0
- package/dist/extension/browsers/run-firefox/firefox-launch/index.d.ts +9 -0
- package/dist/extension/browsers/run-firefox/firefox-launch/process-handlers.d.ts +1 -1
- package/dist/extension/helpers/messages.d.ts +1 -0
- package/dist/extension/helpers/messaging.d.ts +1 -0
- package/dist/extension/helpers/project-cli-version.d.ts +26 -0
- package/dist/extension/helpers/template-catalog.d.ts +1 -1
- package/dist/extension/helpers/template-corpus.generated.d.ts +1 -1
- package/package.json +5 -5
package/dist/cli.cjs
CHANGED
|
@@ -230,7 +230,7 @@ var __webpack_modules__ = {
|
|
|
230
230
|
(0, _helpers_messaging__rspack_import_3._w)(_messages__rspack_import_5.io());
|
|
231
231
|
}
|
|
232
232
|
} catch {
|
|
233
|
-
const provenanceNote = _messages__rspack_import_5.xX(opts.binaryProvenance);
|
|
233
|
+
const provenanceNote = _messages__rspack_import_5.xX(opts.binaryProvenance, opts.browser);
|
|
234
234
|
(0, _helpers_messaging__rspack_import_3._w)(_messages__rspack_import_5.io());
|
|
235
235
|
(0, _helpers_messaging__rspack_import_3._w)((0, _helpers_messaging__rspack_import_3.Nr)({
|
|
236
236
|
rows: [
|
|
@@ -421,6 +421,7 @@ var __webpack_modules__ = {
|
|
|
421
421
|
var pintor__rspack_import_8 = __webpack_require__("pintor");
|
|
422
422
|
var pintor__rspack_import_8_default = /*#__PURE__*/ __webpack_require__.n(pintor__rspack_import_8);
|
|
423
423
|
var _helpers_messaging__rspack_import_9 = __webpack_require__("./helpers/messaging.ts");
|
|
424
|
+
var _browser_family__rspack_import_10 = __webpack_require__("./browsers/browsers-lib/browser-family.ts");
|
|
424
425
|
const require1 = (0, node_module__rspack_import_1.createRequire)(__rslib_import_meta_url__);
|
|
425
426
|
function getLoggingPrefix(type) {
|
|
426
427
|
return (0, _helpers_messaging__rspack_import_9.Pl)(type);
|
|
@@ -829,9 +830,15 @@ var __webpack_modules__ = {
|
|
|
829
830
|
if (rest.startsWith(node_path__rspack_import_3.sep) || rest.startsWith('/')) return `~${rest}`;
|
|
830
831
|
return raw;
|
|
831
832
|
}
|
|
832
|
-
function binaryProvenanceNote(provenance) {
|
|
833
|
-
if ('pinned'
|
|
834
|
-
return
|
|
833
|
+
function binaryProvenanceNote(provenance, browser) {
|
|
834
|
+
if ('pinned' !== provenance) return '';
|
|
835
|
+
return `(pinned with ${pinnedBinaryFlag(browser)})`;
|
|
836
|
+
}
|
|
837
|
+
function pinnedBinaryFlag(browser) {
|
|
838
|
+
const name = String(browser || '');
|
|
839
|
+
if ((0, _browser_family__rspack_import_10.M_)(name)) return '--gecko-binary';
|
|
840
|
+
if ('safari' === name || 'webkit-based' === name) return '--safari-binary';
|
|
841
|
+
return '--chromium-binary';
|
|
835
842
|
}
|
|
836
843
|
function runningInDevelopment(manifest, browser, message, browserVersionLine, updateSuffix, opts) {
|
|
837
844
|
const capitalize = (str)=>str.charAt(0).toUpperCase() + str.slice(1);
|
|
@@ -867,7 +874,7 @@ var __webpack_modules__ = {
|
|
|
867
874
|
const baseBrowserLabel = (0, _helpers_messaging__rspack_import_9.A6)(String(browser || 'unknown'), resolveBrowserVersionLine(browser, browserVersionLine, {
|
|
868
875
|
pinned: opts?.binaryProvenance === 'pinned'
|
|
869
876
|
}));
|
|
870
|
-
const provenanceNote = binaryProvenanceNote(opts?.binaryProvenance);
|
|
877
|
+
const provenanceNote = binaryProvenanceNote(opts?.binaryProvenance, browser);
|
|
871
878
|
const browserLabel = provenanceNote ? `${baseBrowserLabel} ${provenanceNote}` : baseBrowserLabel;
|
|
872
879
|
const cleanId = String(id || '').trim();
|
|
873
880
|
const includeExtensionId = opts?.includeExtensionId !== false;
|
|
@@ -1326,17 +1333,21 @@ var __webpack_modules__ = {
|
|
|
1326
1333
|
var _messages__rspack_import_2 = __webpack_require__("./browsers/browsers-lib/messages.ts");
|
|
1327
1334
|
const FORCE_KILL_GRACE_MS = 5000;
|
|
1328
1335
|
const terminatedByUs = new WeakSet();
|
|
1336
|
+
const terminatedPids = new Set();
|
|
1329
1337
|
function wasTerminatedByUs(child) {
|
|
1330
1338
|
return !!child && terminatedByUs.has(child);
|
|
1331
1339
|
}
|
|
1340
|
+
function wasPidTerminatedByUs(pid) {
|
|
1341
|
+
return 'number' == typeof pid && terminatedPids.has(pid);
|
|
1342
|
+
}
|
|
1332
1343
|
function authorLog(line) {
|
|
1333
1344
|
if (line && (0, _helpers_messaging__rspack_import_1._o)()) (0, _helpers_messaging__rspack_import_1._w)(line);
|
|
1334
1345
|
}
|
|
1335
|
-
function killWindowsTree(
|
|
1336
|
-
if ('win32' !== process.platform) return;
|
|
1346
|
+
function killWindowsTree(pid, sync) {
|
|
1347
|
+
if ('win32' !== process.platform || !pid) return;
|
|
1337
1348
|
const args = [
|
|
1338
1349
|
'/PID',
|
|
1339
|
-
String(
|
|
1350
|
+
String(pid),
|
|
1340
1351
|
'/T',
|
|
1341
1352
|
'/F'
|
|
1342
1353
|
];
|
|
@@ -1351,10 +1362,37 @@ var __webpack_modules__ = {
|
|
|
1351
1362
|
}).on('error', ()=>{});
|
|
1352
1363
|
} catch {}
|
|
1353
1364
|
}
|
|
1365
|
+
function signalPid(pid, signal) {
|
|
1366
|
+
try {
|
|
1367
|
+
process.kill(pid, signal);
|
|
1368
|
+
return true;
|
|
1369
|
+
} catch {
|
|
1370
|
+
return false;
|
|
1371
|
+
}
|
|
1372
|
+
}
|
|
1373
|
+
function gracefulTerminatePid(pid, browser) {
|
|
1374
|
+
if (!pid || terminatedPids.has(pid)) return;
|
|
1375
|
+
terminatedPids.add(pid);
|
|
1376
|
+
killWindowsTree(pid, false);
|
|
1377
|
+
authorLog(_messages__rspack_import_2.XH(browser));
|
|
1378
|
+
signalPid(pid, 'SIGTERM');
|
|
1379
|
+
const killTimer = setTimeout(()=>{
|
|
1380
|
+
authorLog(_messages__rspack_import_2.AG(browser));
|
|
1381
|
+
signalPid(pid, 'SIGKILL');
|
|
1382
|
+
}, FORCE_KILL_GRACE_MS);
|
|
1383
|
+
killTimer.unref?.();
|
|
1384
|
+
}
|
|
1385
|
+
function forceKillPidOnExit(pid, browser) {
|
|
1386
|
+
if (!pid) return;
|
|
1387
|
+
terminatedPids.add(pid);
|
|
1388
|
+
killWindowsTree(pid, true);
|
|
1389
|
+
authorLog(_messages__rspack_import_2.AG(browser));
|
|
1390
|
+
signalPid(pid, 'SIGKILL');
|
|
1391
|
+
}
|
|
1354
1392
|
function gracefulTerminateChild(child, browser) {
|
|
1355
1393
|
if (!child || child.killed) return;
|
|
1356
1394
|
terminatedByUs.add(child);
|
|
1357
|
-
killWindowsTree(child, false);
|
|
1395
|
+
killWindowsTree(child.pid, false);
|
|
1358
1396
|
authorLog(_messages__rspack_import_2.XH(browser));
|
|
1359
1397
|
child.kill('SIGTERM');
|
|
1360
1398
|
const killTimer = setTimeout(()=>{
|
|
@@ -1368,7 +1406,7 @@ var __webpack_modules__ = {
|
|
|
1368
1406
|
function forceKillChildOnExit(child, browser) {
|
|
1369
1407
|
if (!child) return;
|
|
1370
1408
|
terminatedByUs.add(child);
|
|
1371
|
-
killWindowsTree(child, true);
|
|
1409
|
+
killWindowsTree(child.pid, true);
|
|
1372
1410
|
try {
|
|
1373
1411
|
authorLog(_messages__rspack_import_2.AG(browser));
|
|
1374
1412
|
child.kill('SIGKILL');
|
|
@@ -1389,7 +1427,10 @@ var __webpack_modules__ = {
|
|
|
1389
1427
|
$Y: ()=>forceKillChildOnExit,
|
|
1390
1428
|
Df: ()=>gracefulTerminateChild,
|
|
1391
1429
|
FA: ()=>isBenignSocketTeardown,
|
|
1392
|
-
Op: ()=>wasTerminatedByUs
|
|
1430
|
+
Op: ()=>wasTerminatedByUs,
|
|
1431
|
+
PU: ()=>wasPidTerminatedByUs,
|
|
1432
|
+
Qx: ()=>forceKillPidOnExit,
|
|
1433
|
+
_T: ()=>gracefulTerminatePid
|
|
1393
1434
|
});
|
|
1394
1435
|
},
|
|
1395
1436
|
"./browsers/browsers-lib/ready-message.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
@@ -1433,6 +1474,7 @@ var __webpack_modules__ = {
|
|
|
1433
1474
|
const profilePath = String(details?.profilePath || '').trim();
|
|
1434
1475
|
if (profilePath) ready.profilePath = profilePath;
|
|
1435
1476
|
if ('number' == typeof details?.browserPid && Number.isFinite(details.browserPid)) ready.browserPid = details.browserPid;
|
|
1477
|
+
if ('number' == typeof details?.launcherPid && Number.isFinite(details.launcherPid)) ready.launcherPid = details.launcherPid;
|
|
1436
1478
|
const extensionId = String(details?.extensionId || '').trim();
|
|
1437
1479
|
if (extensionId) ready.extensionId = extensionId;
|
|
1438
1480
|
const binary = String(details?.binary || '').trim();
|
|
@@ -2686,6 +2728,7 @@ var __webpack_modules__ = {
|
|
|
2686
2728
|
'--enable-features=SidePanelUpdates',
|
|
2687
2729
|
'--disable-features=DisableLoadExtensionCommandLineSwitch',
|
|
2688
2730
|
'--disable-features=ExtensionDisableUnsupportedDeveloper',
|
|
2731
|
+
'--disable-features=SafetyHubExtensionsOffStoreTrigger',
|
|
2689
2732
|
'--enable-unsafe-extension-debugging',
|
|
2690
2733
|
'--silent-debugger-extension-api'
|
|
2691
2734
|
];
|
|
@@ -3514,7 +3557,7 @@ var __webpack_modules__ = {
|
|
|
3514
3557
|
binaryProvenance
|
|
3515
3558
|
};
|
|
3516
3559
|
if (enableCdp) {
|
|
3517
|
-
const mod = await __webpack_require__.e(
|
|
3560
|
+
const mod = await __webpack_require__.e(597).then(__webpack_require__.bind(__webpack_require__, "./browsers/run-chromium/chromium-launch/setup-cdp-after-launch.ts"));
|
|
3518
3561
|
const CDP_SETUP_TIMEOUT_MS = 45000;
|
|
3519
3562
|
await Promise.race([
|
|
3520
3563
|
mod.setupCdpAfterLaunch(compilation, cdpConfig, chromiumConfig, pipeStreams),
|
|
@@ -3805,6 +3848,150 @@ var __webpack_modules__ = {
|
|
|
3805
3848
|
var process_teardown = __webpack_require__("./browsers/browsers-lib/process-teardown.ts");
|
|
3806
3849
|
var ready_message = __webpack_require__("./browsers/browsers-lib/ready-message.ts");
|
|
3807
3850
|
var ready_stamp = __webpack_require__("./browsers/browsers-lib/ready-stamp.ts");
|
|
3851
|
+
var external_node_child_process_ = __webpack_require__("node:child_process");
|
|
3852
|
+
const PS_ROW = /^\s*(\d+)\s+(\d+)\s+(.*)$/;
|
|
3853
|
+
const HELPER_PROCESS = /plugin-container|(^|\s)-contentproc(\s|$)|(^|\s)-childID(\s|$)|--type=/;
|
|
3854
|
+
function runQuiet(bin, args) {
|
|
3855
|
+
try {
|
|
3856
|
+
const result = (0, external_node_child_process_.spawnSync)(bin, args, {
|
|
3857
|
+
encoding: 'utf-8',
|
|
3858
|
+
stdio: [
|
|
3859
|
+
'ignore',
|
|
3860
|
+
'pipe',
|
|
3861
|
+
'ignore'
|
|
3862
|
+
],
|
|
3863
|
+
windowsHide: true,
|
|
3864
|
+
maxBuffer: 67108864
|
|
3865
|
+
});
|
|
3866
|
+
if (result.error || 0 !== result.status) return null;
|
|
3867
|
+
return String(result.stdout || '');
|
|
3868
|
+
} catch {
|
|
3869
|
+
return null;
|
|
3870
|
+
}
|
|
3871
|
+
}
|
|
3872
|
+
function parseProcessRows(output) {
|
|
3873
|
+
const rows = [];
|
|
3874
|
+
for (const line of String(output || '').split(/\r?\n/)){
|
|
3875
|
+
const match = PS_ROW.exec(line.replace(/\r$/, ''));
|
|
3876
|
+
if (!match) continue;
|
|
3877
|
+
const pid = Number(match[1]);
|
|
3878
|
+
const ppid = Number(match[2]);
|
|
3879
|
+
if (Number.isFinite(pid) && Number.isFinite(ppid)) rows.push({
|
|
3880
|
+
pid,
|
|
3881
|
+
ppid,
|
|
3882
|
+
command: match[3].trim()
|
|
3883
|
+
});
|
|
3884
|
+
}
|
|
3885
|
+
return rows;
|
|
3886
|
+
}
|
|
3887
|
+
function appendLinuxProfileEnv(rows) {
|
|
3888
|
+
return rows.map((row)=>{
|
|
3889
|
+
try {
|
|
3890
|
+
const environ = external_node_fs_.readFileSync(`/proc/${row.pid}/environ`, 'utf-8');
|
|
3891
|
+
const entry = environ.split('\0').find((pair)=>pair.startsWith('XRE_PROFILE_PATH='));
|
|
3892
|
+
return entry ? {
|
|
3893
|
+
...row,
|
|
3894
|
+
command: `${row.command} ${entry}`
|
|
3895
|
+
} : row;
|
|
3896
|
+
} catch {
|
|
3897
|
+
return row;
|
|
3898
|
+
}
|
|
3899
|
+
});
|
|
3900
|
+
}
|
|
3901
|
+
function listProcesses(platform = process.platform) {
|
|
3902
|
+
if ('win32' === platform) {
|
|
3903
|
+
const script = 'Get-CimInstance Win32_Process | ForEach-Object { "$($_.ProcessId) $($_.ParentProcessId) $($_.CommandLine)" }';
|
|
3904
|
+
const output = runQuiet('powershell.exe', [
|
|
3905
|
+
'-NoProfile',
|
|
3906
|
+
'-NonInteractive',
|
|
3907
|
+
'-Command',
|
|
3908
|
+
script
|
|
3909
|
+
]);
|
|
3910
|
+
return output ? parseProcessRows(output) : [];
|
|
3911
|
+
}
|
|
3912
|
+
if ('darwin' === platform) {
|
|
3913
|
+
const output = runQuiet('ps', [
|
|
3914
|
+
'-axEo',
|
|
3915
|
+
'pid=,ppid=,command='
|
|
3916
|
+
]);
|
|
3917
|
+
return output ? parseProcessRows(output) : [];
|
|
3918
|
+
}
|
|
3919
|
+
const output = runQuiet('ps', [
|
|
3920
|
+
'-axo',
|
|
3921
|
+
'pid=,ppid=,command='
|
|
3922
|
+
]);
|
|
3923
|
+
const rows = output ? parseProcessRows(output) : [];
|
|
3924
|
+
return 'linux' === platform ? appendLinuxProfileEnv(rows) : rows;
|
|
3925
|
+
}
|
|
3926
|
+
function resolve_live_pid_normalizePath(value) {
|
|
3927
|
+
return String(value || '').replace(/\\/g, '/').toLowerCase();
|
|
3928
|
+
}
|
|
3929
|
+
function carriesProfile(command, profilePath) {
|
|
3930
|
+
const haystack = resolve_live_pid_normalizePath(command);
|
|
3931
|
+
const needle = resolve_live_pid_normalizePath(profilePath);
|
|
3932
|
+
let from = 0;
|
|
3933
|
+
for(;;){
|
|
3934
|
+
const at = haystack.indexOf(needle, from);
|
|
3935
|
+
if (at < 0) return false;
|
|
3936
|
+
const before = 0 === at ? ' ' : haystack[at - 1];
|
|
3937
|
+
const after = haystack[at + needle.length] ?? ' ';
|
|
3938
|
+
if (/[\s="']/.test(before) && /[\s"']/.test(after)) return true;
|
|
3939
|
+
from = at + 1;
|
|
3940
|
+
}
|
|
3941
|
+
}
|
|
3942
|
+
function executableOf(command) {
|
|
3943
|
+
const trimmed = resolve_live_pid_normalizePath(command).trim();
|
|
3944
|
+
if (trimmed.startsWith('"')) {
|
|
3945
|
+
const end = trimmed.indexOf('"', 1);
|
|
3946
|
+
return end > 0 ? trimmed.slice(1, end) : trimmed;
|
|
3947
|
+
}
|
|
3948
|
+
const cut = trimmed.search(/\s(-|[a-z_][a-z0-9_]*=)/);
|
|
3949
|
+
return cut > 0 ? trimmed.slice(0, cut) : trimmed;
|
|
3950
|
+
}
|
|
3951
|
+
function findLiveBrowserPid(input) {
|
|
3952
|
+
const profilePath = String(input.profilePath || '').trim();
|
|
3953
|
+
const binary = resolve_live_pid_normalizePath(input.binary).trim();
|
|
3954
|
+
if (!profilePath || !binary) return null;
|
|
3955
|
+
const candidates = input.rows.filter((row)=>executableOf(row.command) === binary && carriesProfile(row.command, profilePath) && !HELPER_PROCESS.test(row.command));
|
|
3956
|
+
if (0 === candidates.length) return null;
|
|
3957
|
+
const launcher = input.launcherPid ? candidates.find((row)=>row.pid === input.launcherPid) : void 0;
|
|
3958
|
+
if (launcher) {
|
|
3959
|
+
const twin = candidates.find((row)=>row.pid !== launcher.pid);
|
|
3960
|
+
return twin ? twin.pid : launcher.pid;
|
|
3961
|
+
}
|
|
3962
|
+
const pids = new Set(candidates.map((row)=>row.pid));
|
|
3963
|
+
const roots = candidates.filter((row)=>!pids.has(row.ppid));
|
|
3964
|
+
return (roots[0] || candidates[0]).pid;
|
|
3965
|
+
}
|
|
3966
|
+
function isPidAlive(pid) {
|
|
3967
|
+
if (!pid || !Number.isFinite(pid)) return false;
|
|
3968
|
+
try {
|
|
3969
|
+
process.kill(pid, 0);
|
|
3970
|
+
return true;
|
|
3971
|
+
} catch (error) {
|
|
3972
|
+
return error?.code === 'EPERM';
|
|
3973
|
+
}
|
|
3974
|
+
}
|
|
3975
|
+
async function resolveLiveBrowserPid(input) {
|
|
3976
|
+
const list = input.list || listProcesses;
|
|
3977
|
+
const attempts = Math.max(1, input.attempts ?? 6);
|
|
3978
|
+
const intervalMs = input.intervalMs ?? 500;
|
|
3979
|
+
const sleep = input.sleep || ((ms)=>new Promise((r)=>{
|
|
3980
|
+
setTimeout(r, ms).unref?.();
|
|
3981
|
+
}));
|
|
3982
|
+
let last = null;
|
|
3983
|
+
for(let attempt = 0; attempt < attempts; attempt += 1){
|
|
3984
|
+
last = findLiveBrowserPid({
|
|
3985
|
+
profilePath: input.profilePath,
|
|
3986
|
+
binary: input.binary,
|
|
3987
|
+
launcherPid: input.launcherPid,
|
|
3988
|
+
rows: list()
|
|
3989
|
+
});
|
|
3990
|
+
if (last && last !== input.launcherPid) break;
|
|
3991
|
+
if (attempt < attempts - 1) await sleep(intervalMs);
|
|
3992
|
+
}
|
|
3993
|
+
return last;
|
|
3994
|
+
}
|
|
3808
3995
|
var runtime_options = __webpack_require__("./browsers/browsers-lib/runtime-options.ts");
|
|
3809
3996
|
var shared_utils = __webpack_require__("./browsers/browsers-lib/shared-utils.ts");
|
|
3810
3997
|
function parseFlatpakBinary(binary) {
|
|
@@ -4082,7 +4269,12 @@ var __webpack_modules__ = {
|
|
|
4082
4269
|
for (const instance of activeInstances)attemptCleanup(instance);
|
|
4083
4270
|
}
|
|
4084
4271
|
function forceKillAllOnExit() {
|
|
4085
|
-
for (const instance of activeInstances)
|
|
4272
|
+
for (const instance of activeInstances){
|
|
4273
|
+
const child = instance.childRef();
|
|
4274
|
+
const livePid = instance.livePidRef();
|
|
4275
|
+
(0, process_teardown.$Y)(child, instance.browser);
|
|
4276
|
+
if (livePid && livePid !== child?.pid) (0, process_teardown.Qx)(livePid, instance.browser);
|
|
4277
|
+
}
|
|
4086
4278
|
}
|
|
4087
4279
|
function firstBrowserLabel() {
|
|
4088
4280
|
for (const instance of activeInstances)return instance.browser;
|
|
@@ -4114,10 +4306,11 @@ var __webpack_modules__ = {
|
|
|
4114
4306
|
process.exit(1);
|
|
4115
4307
|
});
|
|
4116
4308
|
}
|
|
4117
|
-
function setupFirefoxProcessHandlers(browser, childRef, cleanupInstance) {
|
|
4309
|
+
function setupFirefoxProcessHandlers(browser, childRef, cleanupInstance, livePidRef = ()=>null) {
|
|
4118
4310
|
const instance = {
|
|
4119
4311
|
browser,
|
|
4120
4312
|
childRef,
|
|
4313
|
+
livePidRef,
|
|
4121
4314
|
cleanupInstance,
|
|
4122
4315
|
isCleaningUp: false
|
|
4123
4316
|
};
|
|
@@ -5203,7 +5396,6 @@ var __webpack_modules__ = {
|
|
|
5203
5396
|
} catch {}
|
|
5204
5397
|
return controller;
|
|
5205
5398
|
}
|
|
5206
|
-
var external_node_child_process_ = __webpack_require__("node:child_process");
|
|
5207
5399
|
var wsl_support = __webpack_require__("./browsers/browsers-lib/wsl-support.ts");
|
|
5208
5400
|
const LINUX_FIREFOX_PATHS = [
|
|
5209
5401
|
'/usr/bin/firefox',
|
|
@@ -5473,13 +5665,12 @@ var __webpack_modules__ = {
|
|
|
5473
5665
|
browserPid: this.child?.pid,
|
|
5474
5666
|
extensionId: this.extensionOutputPath ? (0, banner.MT)(this.extensionOutputPath) : void 0
|
|
5475
5667
|
});
|
|
5476
|
-
this.child.on('close', ()=>{
|
|
5477
|
-
(0, shared_utils.sW)(profilePath);
|
|
5478
|
-
});
|
|
5479
5668
|
this.wireChildLifecycle();
|
|
5669
|
+
this.trackLiveBrowserPid();
|
|
5480
5670
|
let ctrl;
|
|
5481
5671
|
try {
|
|
5482
5672
|
ctrl = await setupRdpAfterLaunch(this.host, compilation, debugPort);
|
|
5673
|
+
this.trackLiveBrowserPid(1);
|
|
5483
5674
|
} catch (error) {
|
|
5484
5675
|
const reason = error?.extensionLoadRefusedReason;
|
|
5485
5676
|
if (!reason) {
|
|
@@ -5574,24 +5765,89 @@ var __webpack_modules__ = {
|
|
|
5574
5765
|
if (process.env.VITEST || process.env.VITEST_WORKER_ID) throw new Error('Firefox startup timed out');
|
|
5575
5766
|
process.exit(1);
|
|
5576
5767
|
});
|
|
5577
|
-
let disposeProcessHandlers;
|
|
5578
5768
|
child.on('close', (code)=>{
|
|
5579
|
-
|
|
5580
|
-
|
|
5581
|
-
|
|
5582
|
-
}
|
|
5583
|
-
if ((0, messaging._o)()) this.ctx.logger?.info?.(messages.Th(this.host.browser));
|
|
5584
|
-
if (!(0, process_teardown.Op)(child)) {
|
|
5585
|
-
this.ctx.logger?.error?.(`[browser] ${this.host.browser} exited (code ${code ?? 'unknown'}) without being asked to. The add-on may have been rejected or the browser crashed; the session cannot be driven.`);
|
|
5586
|
-
(0, ready_stamp.Wi)(this.extensionOutputPath, code);
|
|
5587
|
-
}
|
|
5588
|
-
this.cleanupInstance().catch((err)=>{
|
|
5589
|
-
if ((0, messaging._o)()) this.ctx.logger?.error?.(`[browser] Cleanup error on child close: ${err?.message || err}`);
|
|
5590
|
-
});
|
|
5591
|
-
disposeProcessHandlers?.();
|
|
5769
|
+
const expected = (0, process_teardown.Op)(child);
|
|
5770
|
+
if (!expected && this.adoptHandedOffBrowser()) return;
|
|
5771
|
+
this.onBrowserGone(code, expected);
|
|
5592
5772
|
});
|
|
5593
5773
|
this.pipeChildOutput(child);
|
|
5594
|
-
disposeProcessHandlers = setupFirefoxProcessHandlers(this.host.browser, ()=>this.child, ()=>this.cleanupInstance());
|
|
5774
|
+
this.disposeProcessHandlers = setupFirefoxProcessHandlers(this.host.browser, ()=>this.child, ()=>this.cleanupInstance(), ()=>this.livePid);
|
|
5775
|
+
}
|
|
5776
|
+
onBrowserGone(code, expected) {
|
|
5777
|
+
if (this.browserGone) return;
|
|
5778
|
+
this.browserGone = true;
|
|
5779
|
+
if (this.watchTimeout) {
|
|
5780
|
+
clearTimeout(this.watchTimeout);
|
|
5781
|
+
this.watchTimeout = void 0;
|
|
5782
|
+
}
|
|
5783
|
+
if (this.liveExitWatcher) {
|
|
5784
|
+
clearInterval(this.liveExitWatcher);
|
|
5785
|
+
this.liveExitWatcher = void 0;
|
|
5786
|
+
}
|
|
5787
|
+
if (this.host.launchProfilePath) (0, shared_utils.sW)(this.host.launchProfilePath);
|
|
5788
|
+
if ((0, messaging._o)()) this.ctx.logger?.info?.(messages.Th(this.host.browser));
|
|
5789
|
+
if (!expected) {
|
|
5790
|
+
this.ctx.logger?.error?.(`[browser] ${this.host.browser} exited (code ${code ?? 'unknown'}) without being asked to. The add-on may have been rejected or the browser crashed; the session cannot be driven.`);
|
|
5791
|
+
(0, ready_stamp.Wi)(this.extensionOutputPath, code);
|
|
5792
|
+
}
|
|
5793
|
+
this.cleanupInstance().catch((err)=>{
|
|
5794
|
+
if ((0, messaging._o)()) this.ctx.logger?.error?.(`[browser] Cleanup error on child close: ${err?.message || err}`);
|
|
5795
|
+
});
|
|
5796
|
+
this.disposeProcessHandlers?.();
|
|
5797
|
+
this.disposeProcessHandlers = void 0;
|
|
5798
|
+
}
|
|
5799
|
+
async trackLiveBrowserPid(attempts) {
|
|
5800
|
+
const child = this.child;
|
|
5801
|
+
const profilePath = this.host.launchProfilePath;
|
|
5802
|
+
if (!child?.pid || !profilePath || this.browserGone) return;
|
|
5803
|
+
try {
|
|
5804
|
+
const pid = await resolveLiveBrowserPid({
|
|
5805
|
+
profilePath,
|
|
5806
|
+
binary: child.spawnfile,
|
|
5807
|
+
launcherPid: child.pid,
|
|
5808
|
+
attempts
|
|
5809
|
+
});
|
|
5810
|
+
if (pid && pid !== child.pid && this.child === child) this.adoptLivePid(pid);
|
|
5811
|
+
} catch {}
|
|
5812
|
+
}
|
|
5813
|
+
adoptHandedOffBrowser() {
|
|
5814
|
+
const profilePath = this.host.launchProfilePath;
|
|
5815
|
+
const child = this.child;
|
|
5816
|
+
if (!profilePath || !child || this.browserGone) return false;
|
|
5817
|
+
try {
|
|
5818
|
+
const pid = this.livePid || findLiveBrowserPid({
|
|
5819
|
+
profilePath,
|
|
5820
|
+
binary: child.spawnfile,
|
|
5821
|
+
launcherPid: child.pid,
|
|
5822
|
+
rows: listProcesses()
|
|
5823
|
+
});
|
|
5824
|
+
if (!pid || pid === this.child?.pid || !isPidAlive(pid)) return false;
|
|
5825
|
+
this.adoptLivePid(pid);
|
|
5826
|
+
return true;
|
|
5827
|
+
} catch {
|
|
5828
|
+
return false;
|
|
5829
|
+
}
|
|
5830
|
+
}
|
|
5831
|
+
adoptLivePid(pid) {
|
|
5832
|
+
if (this.livePid === pid) return;
|
|
5833
|
+
this.livePid = pid;
|
|
5834
|
+
(0, ready_stamp.M)(this.extensionOutputPath, {
|
|
5835
|
+
browserPid: pid,
|
|
5836
|
+
launcherPid: this.child?.pid
|
|
5837
|
+
});
|
|
5838
|
+
if ((0, messaging._o)()) this.ctx.logger?.info?.(`[browser] ${this.host.browser} handed the session to pid ${pid} (launcher pid ${this.child?.pid}).`);
|
|
5839
|
+
this.watchLivePidExit();
|
|
5840
|
+
}
|
|
5841
|
+
watchLivePidExit() {
|
|
5842
|
+
if (this.liveExitWatcher) clearInterval(this.liveExitWatcher);
|
|
5843
|
+
this.liveExitWatcher = setInterval(()=>{
|
|
5844
|
+
const pid = this.livePid;
|
|
5845
|
+
if (!pid || isPidAlive(pid)) return;
|
|
5846
|
+
clearInterval(this.liveExitWatcher);
|
|
5847
|
+
this.liveExitWatcher = void 0;
|
|
5848
|
+
this.onBrowserGone(null, (0, process_teardown.PU)(pid));
|
|
5849
|
+
}, 1000);
|
|
5850
|
+
this.liveExitWatcher.unref?.();
|
|
5595
5851
|
}
|
|
5596
5852
|
async retryAddonInstall(compilation, debugPort) {
|
|
5597
5853
|
try {
|
|
@@ -5626,6 +5882,7 @@ var __webpack_modules__ = {
|
|
|
5626
5882
|
}
|
|
5627
5883
|
async cleanupInstance() {
|
|
5628
5884
|
(0, process_teardown.Df)(this.child, this.host.browser);
|
|
5885
|
+
if (this.livePid && this.livePid !== this.child?.pid) (0, process_teardown._T)(this.livePid, this.host.browser);
|
|
5629
5886
|
}
|
|
5630
5887
|
scheduleWatchTimeout() {
|
|
5631
5888
|
if (this.watchTimeout) return;
|
|
@@ -5660,6 +5917,10 @@ var __webpack_modules__ = {
|
|
|
5660
5917
|
firefox_launch_define_property(this, "child", null);
|
|
5661
5918
|
firefox_launch_define_property(this, "watchTimeout", void 0);
|
|
5662
5919
|
firefox_launch_define_property(this, "extensionOutputPath", void 0);
|
|
5920
|
+
firefox_launch_define_property(this, "livePid", null);
|
|
5921
|
+
firefox_launch_define_property(this, "liveExitWatcher", void 0);
|
|
5922
|
+
firefox_launch_define_property(this, "browserGone", false);
|
|
5923
|
+
firefox_launch_define_property(this, "disposeProcessHandlers", void 0);
|
|
5663
5924
|
this.host = host;
|
|
5664
5925
|
this.ctx = ctx;
|
|
5665
5926
|
}
|
|
@@ -6474,6 +6735,10 @@ var __webpack_modules__ = {
|
|
|
6474
6735
|
if ('debug' === type) return pintor__rspack_import_0_default().dim(pintor__rspack_import_0_default().gray(DEBUG_GLYPH));
|
|
6475
6736
|
return pintor__rspack_import_0_default().gray(GLYPH);
|
|
6476
6737
|
}
|
|
6738
|
+
const ANSI_PATTERN = /\[[0-9;]*m/g;
|
|
6739
|
+
function hasChannelPrefix(text) {
|
|
6740
|
+
return String(text || '').replace(ANSI_PATTERN, '').trimStart().startsWith(GLYPH);
|
|
6741
|
+
}
|
|
6477
6742
|
const MACHINE_OUTPUT_VALUES = new Set([
|
|
6478
6743
|
'json',
|
|
6479
6744
|
'ndjson'
|
|
@@ -6506,7 +6771,8 @@ var __webpack_modules__ = {
|
|
|
6506
6771
|
truncate (input, max = 800) {
|
|
6507
6772
|
const s = (()=>{
|
|
6508
6773
|
try {
|
|
6509
|
-
|
|
6774
|
+
if ('string' == typeof input) return input;
|
|
6775
|
+
return JSON.stringify(input) ?? String(input);
|
|
6510
6776
|
} catch {
|
|
6511
6777
|
return String(input);
|
|
6512
6778
|
}
|
|
@@ -6732,6 +6998,7 @@ var __webpack_modules__ = {
|
|
|
6732
6998
|
Gg: ()=>humanError,
|
|
6733
6999
|
Nr: ()=>card,
|
|
6734
7000
|
Pl: ()=>prefix,
|
|
7001
|
+
Qi: ()=>hasChannelPrefix,
|
|
6735
7002
|
T_: ()=>artifactNoun,
|
|
6736
7003
|
VR: ()=>isCardKeyClaimed,
|
|
6737
7004
|
_o: ()=>isDebug,
|
|
@@ -7198,7 +7465,7 @@ var __webpack_modules__ = {
|
|
|
7198
7465
|
return Math.min(Math.max(n, min), max);
|
|
7199
7466
|
}
|
|
7200
7467
|
const TEMPLATE_CORPUS_REPO = 'extension-js/examples';
|
|
7201
|
-
const TEMPLATE_CORPUS_REF = '
|
|
7468
|
+
const TEMPLATE_CORPUS_REF = 'f8087f012cf195cba9aa2e3c32fd5a6729da33f0';
|
|
7202
7469
|
const TEMPLATE_CORPUS_SLUGS = [
|
|
7203
7470
|
'action',
|
|
7204
7471
|
'action-locales',
|
|
@@ -8077,8 +8344,13 @@ var __webpack_modules__ = {
|
|
|
8077
8344
|
function availableCommandsBlock() {
|
|
8078
8345
|
return COMMANDS.map(commandHelpEntry).join('\n\n');
|
|
8079
8346
|
}
|
|
8347
|
+
function projectCliVersionMismatch(running, declared, range, installCommand) {
|
|
8348
|
+
return `${getLoggingPrefix('warn')} Running ${messages_code(`extension ${running}`)}, this project declares ${messages_code(`${declared}@${range}`)}.\nRun ${messages_code(installCommand)} so the project's own version runs.`;
|
|
8349
|
+
}
|
|
8080
8350
|
function unhandledError(err) {
|
|
8081
|
-
const
|
|
8351
|
+
const rendered = err instanceof Error ? err.message : '';
|
|
8352
|
+
if ((0, messaging.Qi)(rendered)) return rendered;
|
|
8353
|
+
const message = err instanceof Error ? err.stack || err.message : 'string' == typeof err ? err : null == err ? '' : messaging.Sc.truncate(err);
|
|
8082
8354
|
return `${getLoggingPrefix('error')} ${external_pintor_default().red(String(message || 'Unknown error'))}`;
|
|
8083
8355
|
}
|
|
8084
8356
|
function updateFailed(err) {
|
|
@@ -9404,6 +9676,102 @@ Cross-browser compatibility
|
|
|
9404
9676
|
const values = String(raw).split(',').map((value)=>value.trim()).filter((value)=>value.length > 0);
|
|
9405
9677
|
return values.length > 0 ? values : void 0;
|
|
9406
9678
|
}
|
|
9679
|
+
const external_semver_namespaceObject = require("semver");
|
|
9680
|
+
var external_semver_default = /*#__PURE__*/ __webpack_require__.n(external_semver_namespaceObject);
|
|
9681
|
+
const CLI_PACKAGES = [
|
|
9682
|
+
'extension',
|
|
9683
|
+
'extension-develop'
|
|
9684
|
+
];
|
|
9685
|
+
const LOCKFILE_COMMANDS = [
|
|
9686
|
+
[
|
|
9687
|
+
'pnpm-lock.yaml',
|
|
9688
|
+
'pnpm install'
|
|
9689
|
+
],
|
|
9690
|
+
[
|
|
9691
|
+
'yarn.lock',
|
|
9692
|
+
'yarn install'
|
|
9693
|
+
],
|
|
9694
|
+
[
|
|
9695
|
+
'bun.lock',
|
|
9696
|
+
'bun install'
|
|
9697
|
+
],
|
|
9698
|
+
[
|
|
9699
|
+
'bun.lockb',
|
|
9700
|
+
'bun install'
|
|
9701
|
+
],
|
|
9702
|
+
[
|
|
9703
|
+
'deno.lock',
|
|
9704
|
+
'deno install'
|
|
9705
|
+
],
|
|
9706
|
+
[
|
|
9707
|
+
'package-lock.json',
|
|
9708
|
+
'npm install'
|
|
9709
|
+
]
|
|
9710
|
+
];
|
|
9711
|
+
function installCommandFor(files) {
|
|
9712
|
+
for (const [lockfile, command] of LOCKFILE_COMMANDS)if (files.includes(lockfile)) return command;
|
|
9713
|
+
return 'npm install';
|
|
9714
|
+
}
|
|
9715
|
+
function declaredCliDependency(manifest) {
|
|
9716
|
+
for (const field of [
|
|
9717
|
+
manifest?.dependencies,
|
|
9718
|
+
manifest?.devDependencies
|
|
9719
|
+
])for (const name of CLI_PACKAGES){
|
|
9720
|
+
const range = field?.[name];
|
|
9721
|
+
if ('string' == typeof range && range.length > 0) return {
|
|
9722
|
+
name,
|
|
9723
|
+
range
|
|
9724
|
+
};
|
|
9725
|
+
}
|
|
9726
|
+
return null;
|
|
9727
|
+
}
|
|
9728
|
+
function isComparableRange(range) {
|
|
9729
|
+
const trimmed = range.trim();
|
|
9730
|
+
if (!trimmed || '*' === trimmed || 'latest' === trimmed) return false;
|
|
9731
|
+
if (/^(workspace|file|link|git|github|npm):/i.test(trimmed)) return false;
|
|
9732
|
+
if (/^[./]/.test(trimmed)) return false;
|
|
9733
|
+
return null !== external_semver_default().validRange(trimmed);
|
|
9734
|
+
}
|
|
9735
|
+
function versionMismatch(input) {
|
|
9736
|
+
const declared = declaredCliDependency(input.manifest);
|
|
9737
|
+
if (!declared) return null;
|
|
9738
|
+
if (!isComparableRange(declared.range)) return null;
|
|
9739
|
+
if (!external_semver_default().valid(input.running)) return null;
|
|
9740
|
+
const comparable = external_semver_default().prerelease(input.running) ? external_semver_default().coerce(input.running)?.version ?? input.running : input.running;
|
|
9741
|
+
if (external_semver_default().satisfies(comparable, declared.range, {
|
|
9742
|
+
includePrerelease: true
|
|
9743
|
+
})) return null;
|
|
9744
|
+
return {
|
|
9745
|
+
declared: declared.name,
|
|
9746
|
+
range: declared.range,
|
|
9747
|
+
running: input.running
|
|
9748
|
+
};
|
|
9749
|
+
}
|
|
9750
|
+
function readProjectManifest(projectPath) {
|
|
9751
|
+
try {
|
|
9752
|
+
return JSON.parse(external_node_fs_.readFileSync(external_node_path_.join(projectPath, 'package.json'), 'utf-8'));
|
|
9753
|
+
} catch {
|
|
9754
|
+
return null;
|
|
9755
|
+
}
|
|
9756
|
+
}
|
|
9757
|
+
function checkProjectCliVersion(projectPath, running) {
|
|
9758
|
+
let files = [];
|
|
9759
|
+
try {
|
|
9760
|
+
files = external_node_fs_.readdirSync(projectPath);
|
|
9761
|
+
} catch {
|
|
9762
|
+
return null;
|
|
9763
|
+
}
|
|
9764
|
+
if (!files.includes('package.json')) return null;
|
|
9765
|
+
const mismatch = versionMismatch({
|
|
9766
|
+
manifest: readProjectManifest(projectPath),
|
|
9767
|
+
running
|
|
9768
|
+
});
|
|
9769
|
+
if (!mismatch) return null;
|
|
9770
|
+
return {
|
|
9771
|
+
...mismatch,
|
|
9772
|
+
command: installCommandFor(files)
|
|
9773
|
+
};
|
|
9774
|
+
}
|
|
9407
9775
|
function registerBuildCommand(program) {
|
|
9408
9776
|
program.command('build').arguments('[project-name]').usage('[path-to-remote-extension] [options]').description(commandDescriptions.build).option(`--browser <${BROWSER_TARGETS_HELP}>`, '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`', parseOptionalBoolean).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`', parseOptionalBoolean).option('--zip-source [boolean]', 'whether or not to include the source files in the ZIP file. Defaults to `false`', parseOptionalBoolean).option('--zip-filename <string>', 'specify the name of the ZIP file. Defaults to the extension name and version').option('--silent [boolean]', 'suppress the build summary output. Defaults to `false`', parseOptionalBoolean).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`', parseOptionalBoolean).option('--no-addon-lint', 'skip the addons.mozilla.org lint of Firefox builds').option('--install [boolean]', '[internal] install project dependencies when missing', parseOptionalBoolean).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`', parseOptionalBoolean).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`', parseOptionalBoolean).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 })=>{
|
|
9409
9777
|
const browser = cliBrowser ?? await resolveConfigBrowser(pathOrRemoteUrl || process.cwd(), 'build') ?? 'chromium';
|
|
@@ -9471,6 +9839,8 @@ Cross-browser compatibility
|
|
|
9471
9839
|
}
|
|
9472
9840
|
const { extensionBuild } = await loadExtensionDevelopModule();
|
|
9473
9841
|
const asJson = isJsonOutput(buildOptions);
|
|
9842
|
+
const cliVersion = checkProjectCliVersion(external_node_path_.resolve(pathOrRemoteUrl || process.cwd()), getCliPackageJson().version);
|
|
9843
|
+
if (cliVersion) console.warn(projectCliVersionMismatch(cliVersion.running, cliVersion.declared, cliVersion.range, cliVersion.command));
|
|
9474
9844
|
if (asJson) process.env.EXTENSION_OUTPUT = 'json';
|
|
9475
9845
|
const built = [];
|
|
9476
9846
|
const summaries = [];
|
|
@@ -10058,6 +10428,8 @@ Cross-browser compatibility
|
|
|
10058
10428
|
if (!process.env.EXTENSION_VERBOSE) process.env.EXTENSION_VERBOSE = '1';
|
|
10059
10429
|
}
|
|
10060
10430
|
const asJson = 'json' === resolveOutputFormat(devOptions);
|
|
10431
|
+
const cliVersion = checkProjectCliVersion(external_node_path_.resolve(pathOrRemoteUrl || process.cwd()), getCliPackageJson().version);
|
|
10432
|
+
if (cliVersion) console.warn(projectCliVersionMismatch(cliVersion.running, cliVersion.declared, cliVersion.range, cliVersion.command));
|
|
10061
10433
|
if (void 0 !== devOptions.parentPid) {
|
|
10062
10434
|
const parentPid = parseParentPid(devOptions.parentPid);
|
|
10063
10435
|
if (void 0 === parentPid) {
|
|
@@ -10998,6 +11370,8 @@ Cross-browser compatibility
|
|
|
10998
11370
|
if (!process.env.EXTENSION_VERBOSE) process.env.EXTENSION_VERBOSE = '1';
|
|
10999
11371
|
}
|
|
11000
11372
|
const asJson = 'json' === resolveOutputFormat(startOptions);
|
|
11373
|
+
const cliVersion = checkProjectCliVersion(external_node_path_.resolve(pathOrRemoteUrl || process.cwd()), getCliPackageJson().version);
|
|
11374
|
+
if (cliVersion) console.warn(projectCliVersionMismatch(cliVersion.running, cliVersion.declared, cliVersion.range, cliVersion.command));
|
|
11001
11375
|
if (asJson) process.env.EXTENSION_OUTPUT = 'json';
|
|
11002
11376
|
const list = vendors(browser);
|
|
11003
11377
|
let unsupportedBrowser = '';
|
|
@@ -11171,7 +11545,6 @@ Cross-browser compatibility
|
|
|
11171
11545
|
await exitAfterDrain(1);
|
|
11172
11546
|
});
|
|
11173
11547
|
}
|
|
11174
|
-
const external_semver_namespaceObject = require("semver");
|
|
11175
11548
|
const external_update_check_namespaceObject = require("update-check");
|
|
11176
11549
|
var external_update_check_default = /*#__PURE__*/ __webpack_require__.n(external_update_check_namespaceObject);
|
|
11177
11550
|
function isStableVersion(version) {
|