@monoes/monobrowse 1.0.27 → 1.0.28
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/src/__tests__/disconnect-session.test.d.ts +13 -0
- package/dist/src/__tests__/disconnect-session.test.d.ts.map +1 -0
- package/dist/src/__tests__/disconnect-session.test.js +37 -0
- package/dist/src/__tests__/disconnect-session.test.js.map +1 -0
- package/dist/src/__tests__/profile-cleanup-close.test.d.ts +16 -0
- package/dist/src/__tests__/profile-cleanup-close.test.d.ts.map +1 -0
- package/dist/src/__tests__/profile-cleanup-close.test.js +250 -0
- package/dist/src/__tests__/profile-cleanup-close.test.js.map +1 -0
- package/dist/src/__tests__/profile-dir.test.d.ts +10 -0
- package/dist/src/__tests__/profile-dir.test.d.ts.map +1 -0
- package/dist/src/__tests__/profile-dir.test.js +160 -0
- package/dist/src/__tests__/profile-dir.test.js.map +1 -0
- package/dist/src/__tests__/setup/isolated-tmpdir.global.d.ts +2 -0
- package/dist/src/__tests__/setup/isolated-tmpdir.global.d.ts.map +1 -0
- package/dist/src/__tests__/setup/isolated-tmpdir.global.js +30 -0
- package/dist/src/__tests__/setup/isolated-tmpdir.global.js.map +1 -0
- package/dist/src/browser/browser-launch.d.ts.map +1 -1
- package/dist/src/browser/browser-launch.js +21 -4
- package/dist/src/browser/browser-launch.js.map +1 -1
- package/dist/src/browser/browser-lifecycle.d.ts +5 -0
- package/dist/src/browser/browser-lifecycle.d.ts.map +1 -1
- package/dist/src/browser/browser-lifecycle.js +23 -11
- package/dist/src/browser/browser-lifecycle.js.map +1 -1
- package/dist/src/browser/browser-state.d.ts +4 -0
- package/dist/src/browser/browser-state.d.ts.map +1 -1
- package/dist/src/browser/browser-state.js +10 -2
- package/dist/src/browser/browser-state.js.map +1 -1
- package/dist/src/browser/browser.d.ts +1 -1
- package/dist/src/browser/browser.d.ts.map +1 -1
- package/dist/src/browser/browser.js +1 -1
- package/dist/src/browser/browser.js.map +1 -1
- package/dist/src/browser/profile-dir.d.ts +88 -0
- package/dist/src/browser/profile-dir.d.ts.map +1 -0
- package/dist/src/browser/profile-dir.js +242 -0
- package/dist/src/browser/profile-dir.js.map +1 -0
- package/dist/src/browser/ref-cache.d.ts +4 -0
- package/dist/src/browser/ref-cache.d.ts.map +1 -1
- package/dist/src/browser/ref-cache.js +2 -0
- package/dist/src/browser/ref-cache.js.map +1 -1
- package/dist/src/browser/types.d.ts +6 -0
- package/dist/src/browser/types.d.ts.map +1 -1
- package/dist/src/browser/types.js.map +1 -1
- package/dist/src/cli/commands.d.ts +1 -0
- package/dist/src/cli/commands.d.ts.map +1 -1
- package/dist/src/cli/commands.js +2 -0
- package/dist/src/cli/commands.js.map +1 -1
- package/dist/src/cli/session.d.ts +9 -0
- package/dist/src/cli/session.d.ts.map +1 -1
- package/dist/src/cli/session.js +21 -4
- package/dist/src/cli/session.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/__tests__/disconnect-session.test.ts +42 -0
- package/src/__tests__/profile-cleanup-close.test.ts +285 -0
- package/src/__tests__/profile-dir.test.ts +196 -0
- package/src/__tests__/setup/isolated-tmpdir.global.ts +28 -0
- package/src/browser/browser-launch.ts +22 -5
- package/src/browser/browser-lifecycle.ts +20 -10
- package/src/browser/browser-state.ts +11 -2
- package/src/browser/browser.ts +5 -1
- package/src/browser/profile-dir.ts +249 -0
- package/src/browser/ref-cache.ts +7 -0
- package/src/browser/types.ts +6 -0
- package/src/cli/commands.ts +2 -0
- package/src/cli/session.ts +22 -4
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
import { spawn } from 'node:child_process';
|
|
3
3
|
import { randomUUID } from 'node:crypto';
|
|
4
4
|
import { rmSync } from 'node:fs';
|
|
5
|
-
import { tmpdir } from 'node:os';
|
|
6
5
|
import { join } from 'node:path';
|
|
7
6
|
import { browserIdOf, chromeIdentity, fetchBrowserWebSocketUrl, findChrome, isChromeIdentity, isPortOpen, isTcpPortOpen, readDevToolsActivePort, } from './browser-discovery.js';
|
|
8
7
|
import { reapIdleLaunchedBrowser } from './browser-lifecycle.js';
|
|
9
|
-
import { launchedPids, launchedUserDataDirs } from './browser-state.js';
|
|
8
|
+
import { launchedPids, launchedUserDataDirs, ownedUserDataDirPorts } from './browser-state.js';
|
|
9
|
+
import { launchProfileDirPath, removeOwnedProfileDir, sweepStaleProfileDirs, } from './profile-dir.js';
|
|
10
10
|
const DEFAULT_PORT = 9222;
|
|
11
11
|
const LAUNCH_TIMEOUT = 10_000;
|
|
12
12
|
const POLL_INTERVAL = 200;
|
|
@@ -36,6 +36,10 @@ export async function launchBrowser(config = {}) {
|
|
|
36
36
|
// is no daemon to do it on a timer. Bounded and non-throwing; a stale
|
|
37
37
|
// instance on the port we are about to use is freed before we probe it.
|
|
38
38
|
await reapIdleLaunchedBrowser();
|
|
39
|
+
// Same reasoning for temp profile dirs (#395): a process that crashed or
|
|
40
|
+
// was killed never deleted the one its browser used. Only dead, idle,
|
|
41
|
+
// unused dirs of our own naming go — see sweepStaleProfileDirs.
|
|
42
|
+
await sweepStaleProfileDirs();
|
|
39
43
|
if (rawPort === 0)
|
|
40
44
|
return launchOnFreePort(config, 0);
|
|
41
45
|
// strictPort: fail fast on the exact requested port, matching the old
|
|
@@ -137,8 +141,10 @@ async function launchOnFreePort(config, port) {
|
|
|
137
141
|
// otherwise share one profile directory (lock files, preferences, the
|
|
138
142
|
// DevToolsActivePort file itself) — including two launches from the same
|
|
139
143
|
// process, where a pid suffix alone is identical.
|
|
140
|
-
const userDataDir = config.userDataDir ??
|
|
141
|
-
|
|
144
|
+
const userDataDir = config.userDataDir ?? launchProfileDirPath(port, randomUUID().slice(0, 8));
|
|
145
|
+
// A dir we created is deleted once its browser is gone (#395); a
|
|
146
|
+
// caller-supplied one only when the caller says it made it for us.
|
|
147
|
+
const ownsUserDataDir = config.userDataDir === undefined || config.ownsUserDataDir === true;
|
|
142
148
|
const activePortFile = join(userDataDir, 'DevToolsActivePort');
|
|
143
149
|
// A reused profile dir may hold a previous run's file naming a port some
|
|
144
150
|
// other process now owns.
|
|
@@ -229,6 +235,10 @@ async function launchOnFreePort(config, port) {
|
|
|
229
235
|
return;
|
|
230
236
|
launchedPids.set(boundPort, child.pid);
|
|
231
237
|
launchedUserDataDirs.set(boundPort, userDataDir);
|
|
238
|
+
if (ownsUserDataDir)
|
|
239
|
+
ownedUserDataDirPorts.add(boundPort);
|
|
240
|
+
else
|
|
241
|
+
ownedUserDataDirPorts.delete(boundPort);
|
|
232
242
|
};
|
|
233
243
|
// Tracked only once Chrome is CONFIRMED up on `boundPort`, not right after
|
|
234
244
|
// spawn(). For port !== 0 this used to track(port) unconditionally the
|
|
@@ -264,6 +274,7 @@ async function launchOnFreePort(config, port) {
|
|
|
264
274
|
};
|
|
265
275
|
const launchTimeout = config.launchTimeoutMs ?? LAUNCH_TIMEOUT;
|
|
266
276
|
const deadline = Date.now() + launchTimeout;
|
|
277
|
+
let launched = false;
|
|
267
278
|
try {
|
|
268
279
|
while (Date.now() < deadline) {
|
|
269
280
|
if (earlyFailure)
|
|
@@ -277,6 +288,7 @@ async function launchOnFreePort(config, port) {
|
|
|
277
288
|
if (identity === 'chrome') {
|
|
278
289
|
if (await isOwnEndpoint(boundPort)) {
|
|
279
290
|
track(boundPort);
|
|
291
|
+
launched = true;
|
|
280
292
|
return boundPort;
|
|
281
293
|
}
|
|
282
294
|
// Some Chrome answers on the port, but not the one we started: a
|
|
@@ -316,6 +328,11 @@ async function launchOnFreePort(config, port) {
|
|
|
316
328
|
}
|
|
317
329
|
finally {
|
|
318
330
|
child.stderr?.destroy();
|
|
331
|
+
// A failed launch (lost port race, refusal, timeout) is never tracked,
|
|
332
|
+
// so no close will ever clean its profile — and the port-scan retry in
|
|
333
|
+
// launchBrowser can make several of these per call.
|
|
334
|
+
if (!launched && ownsUserDataDir)
|
|
335
|
+
await removeOwnedProfileDir(userDataDir, { pid: child.pid });
|
|
319
336
|
}
|
|
320
337
|
}
|
|
321
338
|
function sleep(ms) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-launch.js","sourceRoot":"","sources":["../../../src/browser/browser-launch.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAE7E,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"browser-launch.js","sourceRoot":"","sources":["../../../src/browser/browser-launch.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,6 +16,11 @@ import { CdpClient } from './cdp.js';
|
|
|
16
16
|
* singleton lock, and if the caller's process exited first the kill never
|
|
17
17
|
* happened at all. Callers reasonably read a resolved close() as "that
|
|
18
18
|
* browser is gone"; on the graceful path it now means that.
|
|
19
|
+
*
|
|
20
|
+
* A profile directory monobrowse created for that browser (the default temp
|
|
21
|
+
* profile, or a CLI session's — never a caller-supplied one) is deleted once
|
|
22
|
+
* the process is gone, on both paths (#395). In a fresh process the dir and
|
|
23
|
+
* its ownership come from the persisted session record.
|
|
19
24
|
*/
|
|
20
25
|
export declare function closeBrowser(client: CdpClient, port: number): Promise<void>;
|
|
21
26
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-lifecycle.d.ts","sourceRoot":"","sources":["../../../src/browser/browser-lifecycle.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,SAAS,EAAgB,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"browser-lifecycle.d.ts","sourceRoot":"","sources":["../../../src/browser/browser-lifecycle.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,SAAS,EAAgB,MAAM,UAAU,CAAC;AAuBnD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkFjF;AAgCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAOtE"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// Split out of browser.ts (file-size sweep). Pure move: no behaviour change.
|
|
2
2
|
import { fetchBrowserWebSocketUrl } from './browser-discovery.js';
|
|
3
|
-
import { launchedPids, launchedUserDataDirs } from './browser-state.js';
|
|
3
|
+
import { launchedPids, launchedUserDataDirs, ownedUserDataDirPorts } from './browser-state.js';
|
|
4
4
|
import { CdpClient, fetchTargets } from './cdp.js';
|
|
5
|
+
import { removeOwnedProfileDir } from './profile-dir.js';
|
|
5
6
|
import { listSessionRecords, loadSessionRecord, removeSessionRecord, } from './ref-cache.js';
|
|
6
7
|
const BROWSER_CLOSE_TIMEOUT_MS = 3000;
|
|
7
8
|
// How long closeBrowser() waits for the process to actually disappear before
|
|
@@ -33,6 +34,11 @@ const REAP_CONNECT_TIMEOUT_MS = 3000;
|
|
|
33
34
|
* singleton lock, and if the caller's process exited first the kill never
|
|
34
35
|
* happened at all. Callers reasonably read a resolved close() as "that
|
|
35
36
|
* browser is gone"; on the graceful path it now means that.
|
|
37
|
+
*
|
|
38
|
+
* A profile directory monobrowse created for that browser (the default temp
|
|
39
|
+
* profile, or a CLI session's — never a caller-supplied one) is deleted once
|
|
40
|
+
* the process is gone, on both paths (#395). In a fresh process the dir and
|
|
41
|
+
* its ownership come from the persisted session record.
|
|
36
42
|
*/
|
|
37
43
|
export async function closeBrowser(client, port) {
|
|
38
44
|
let gracefullyClosed = false;
|
|
@@ -61,6 +67,7 @@ export async function closeBrowser(client, port) {
|
|
|
61
67
|
clearTimeout(closeTimer);
|
|
62
68
|
}
|
|
63
69
|
let pid = launchedPids.get(port);
|
|
70
|
+
let profileDir = ownedUserDataDirPorts.has(port) ? launchedUserDataDirs.get(port) : undefined;
|
|
64
71
|
if (pid === undefined) {
|
|
65
72
|
// Fresh process (each CLI invocation is its own node process — see
|
|
66
73
|
// module header) — launchedPids is per-process and empty here even
|
|
@@ -79,6 +86,8 @@ export async function closeBrowser(client, port) {
|
|
|
79
86
|
const age = persisted.savedAt !== undefined ? Date.now() - persisted.savedAt : undefined;
|
|
80
87
|
if (age === undefined || age <= PERSISTED_PID_MAX_AGE_MS) {
|
|
81
88
|
pid = persisted.pid;
|
|
89
|
+
if (persisted.ownsUserDataDir)
|
|
90
|
+
profileDir = persisted.userDataDir;
|
|
82
91
|
}
|
|
83
92
|
}
|
|
84
93
|
}
|
|
@@ -89,6 +98,7 @@ export async function closeBrowser(client, port) {
|
|
|
89
98
|
if (pid === undefined)
|
|
90
99
|
return; // not a process we launched, or too stale to trust — nothing to kill
|
|
91
100
|
launchedPids.delete(port);
|
|
101
|
+
ownedUserDataDirPorts.delete(port);
|
|
92
102
|
// Liveness-check before every SIGKILL (not just the safety-net path below)
|
|
93
103
|
// — process.kill(pid, 0) throws ESRCH if the PID is no longer running,
|
|
94
104
|
// which also catches the case where the PID has already been recycled by
|
|
@@ -101,18 +111,20 @@ export async function closeBrowser(client, port) {
|
|
|
101
111
|
catch {
|
|
102
112
|
/* already exited, or never was — nothing to do */
|
|
103
113
|
}
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
// Browser.close was acknowledged — wait for the process to actually go away,
|
|
107
|
-
// then force-kill as a safety net in case it hung.
|
|
108
|
-
if (await waitForProcessExit(pid))
|
|
109
|
-
return;
|
|
110
|
-
try {
|
|
111
|
-
process.kill(pid, 'SIGKILL');
|
|
112
114
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
+
else if (!(await waitForProcessExit(pid))) {
|
|
116
|
+
// Browser.close was acknowledged — wait for the process to actually go
|
|
117
|
+
// away, then force-kill as a safety net in case it hung.
|
|
118
|
+
try {
|
|
119
|
+
process.kill(pid, 'SIGKILL');
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
/* raced us to exit — expected */
|
|
123
|
+
}
|
|
115
124
|
}
|
|
125
|
+
// Waits (bounded) for the killed process to be gone before deleting.
|
|
126
|
+
if (profileDir)
|
|
127
|
+
await removeOwnedProfileDir(profileDir, { pid });
|
|
116
128
|
}
|
|
117
129
|
/** Poll until `pid` is gone or PROCESS_EXIT_TIMEOUT_MS elapses. Returns
|
|
118
130
|
* whether it exited. `process.kill(pid, 0)` throws once the process is no
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-lifecycle.js","sourceRoot":"","sources":["../../../src/browser/browser-lifecycle.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAE7E,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"browser-lifecycle.js","sourceRoot":"","sources":["../../../src/browser/browser-lifecycle.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
export declare const launchedPids: Map<number, number>;
|
|
2
2
|
export declare const launchedUserDataDirs: Map<number, string>;
|
|
3
|
+
export declare const ownedUserDataDirPorts: Set<number>;
|
|
3
4
|
/** PID of the Chrome instance *this process* launched on `port`, if any. */
|
|
4
5
|
export declare function getLaunchedPid(port: number): number | undefined;
|
|
5
6
|
/** userDataDir of the Chrome instance *this process* launched on `port`, if any. */
|
|
6
7
|
export declare function getLaunchedUserDataDir(port: number): string | undefined;
|
|
8
|
+
/** Whether the userDataDir of the Chrome *this process* launched on `port`
|
|
9
|
+
* was created by monobrowse, and so is deleted when that browser closes. */
|
|
10
|
+
export declare function ownsLaunchedUserDataDir(port: number): boolean;
|
|
7
11
|
//# sourceMappingURL=browser-state.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-state.d.ts","sourceRoot":"","sources":["../../../src/browser/browser-state.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,YAAY,qBAA4B,CAAC;AAGtD,eAAO,MAAM,oBAAoB,qBAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"browser-state.d.ts","sourceRoot":"","sources":["../../../src/browser/browser-state.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,YAAY,qBAA4B,CAAC;AAGtD,eAAO,MAAM,oBAAoB,qBAA4B,CAAC;AAG9D,eAAO,MAAM,qBAAqB,aAAoB,CAAC;AAEvD,4EAA4E;AAC5E,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE/D;AAED,oFAAoF;AACpF,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEvE;AAED;6EAC6E;AAC7E,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7D"}
|
|
@@ -5,9 +5,12 @@
|
|
|
5
5
|
// to (already-running browser) are never recorded here — we only ever kill
|
|
6
6
|
// processes we launched ourselves.
|
|
7
7
|
export const launchedPids = new Map();
|
|
8
|
-
// userDataDir per launched port
|
|
9
|
-
//
|
|
8
|
+
// userDataDir per launched port, persisted alongside the pid so a later
|
|
9
|
+
// process can clean up the temp profile dir too (#395).
|
|
10
10
|
export const launchedUserDataDirs = new Map();
|
|
11
|
+
// Launched ports whose userDataDir monobrowse created itself (not one the
|
|
12
|
+
// caller supplied). Only these profile dirs are ever deleted on close.
|
|
13
|
+
export const ownedUserDataDirPorts = new Set();
|
|
11
14
|
/** PID of the Chrome instance *this process* launched on `port`, if any. */
|
|
12
15
|
export function getLaunchedPid(port) {
|
|
13
16
|
return launchedPids.get(port);
|
|
@@ -16,4 +19,9 @@ export function getLaunchedPid(port) {
|
|
|
16
19
|
export function getLaunchedUserDataDir(port) {
|
|
17
20
|
return launchedUserDataDirs.get(port);
|
|
18
21
|
}
|
|
22
|
+
/** Whether the userDataDir of the Chrome *this process* launched on `port`
|
|
23
|
+
* was created by monobrowse, and so is deleted when that browser closes. */
|
|
24
|
+
export function ownsLaunchedUserDataDir(port) {
|
|
25
|
+
return ownedUserDataDirPorts.has(port);
|
|
26
|
+
}
|
|
19
27
|
//# sourceMappingURL=browser-state.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-state.js","sourceRoot":"","sources":["../../../src/browser/browser-state.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAE7E,yEAAyE;AACzE,2EAA2E;AAC3E,8EAA8E;AAC9E,2EAA2E;AAC3E,mCAAmC;AACnC,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAC;AACtD,
|
|
1
|
+
{"version":3,"file":"browser-state.js","sourceRoot":"","sources":["../../../src/browser/browser-state.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAE7E,yEAAyE;AACzE,2EAA2E;AAC3E,8EAA8E;AAC9E,2EAA2E;AAC3E,mCAAmC;AACnC,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAC;AACtD,wEAAwE;AACxE,wDAAwD;AACxD,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,GAAG,EAAkB,CAAC;AAC9D,0EAA0E;AAC1E,uEAAuE;AACvE,MAAM,CAAC,MAAM,qBAAqB,GAAG,IAAI,GAAG,EAAU,CAAC;AAEvD,4EAA4E;AAC5E,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAChC,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,sBAAsB,CAAC,IAAY;IACjD,OAAO,oBAAoB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACxC,CAAC;AAED;6EAC6E;AAC7E,MAAM,UAAU,uBAAuB,CAAC,IAAY;IAClD,OAAO,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACzC,CAAC"}
|
|
@@ -2,5 +2,5 @@ export { isPortOpen } from './browser-discovery.js';
|
|
|
2
2
|
export { launchBrowser } from './browser-launch.js';
|
|
3
3
|
export { closeBrowser, reapIdleLaunchedBrowser } from './browser-lifecycle.js';
|
|
4
4
|
export { connectToTarget, enableSessionDomains, getCurrentTitle, getCurrentUrl, openUrl, waitForLoad, } from './browser-page.js';
|
|
5
|
-
export { getLaunchedPid, getLaunchedUserDataDir } from './browser-state.js';
|
|
5
|
+
export { getLaunchedPid, getLaunchedUserDataDir, ownsLaunchedUserDataDir, } from './browser-state.js';
|
|
6
6
|
//# sourceMappingURL=browser.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../../src/browser/browser.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,eAAe,EACf,aAAa,EACb,OAAO,EACP,WAAW,GACZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,
|
|
1
|
+
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../../src/browser/browser.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,eAAe,EACf,aAAa,EACb,OAAO,EACP,WAAW,GACZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,cAAc,EACd,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,oBAAoB,CAAC"}
|
|
@@ -6,5 +6,5 @@ export { isPortOpen } from './browser-discovery.js';
|
|
|
6
6
|
export { launchBrowser } from './browser-launch.js';
|
|
7
7
|
export { closeBrowser, reapIdleLaunchedBrowser } from './browser-lifecycle.js';
|
|
8
8
|
export { connectToTarget, enableSessionDomains, getCurrentTitle, getCurrentUrl, openUrl, waitForLoad, } from './browser-page.js';
|
|
9
|
-
export { getLaunchedPid, getLaunchedUserDataDir } from './browser-state.js';
|
|
9
|
+
export { getLaunchedPid, getLaunchedUserDataDir, ownsLaunchedUserDataDir, } from './browser-state.js';
|
|
10
10
|
//# sourceMappingURL=browser.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../../../src/browser/browser.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,8EAA8E;AAC9E,yEAAyE;AACzE,iBAAiB;AAEjB,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,eAAe,EACf,aAAa,EACb,OAAO,EACP,WAAW,GACZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,
|
|
1
|
+
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../../../src/browser/browser.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,8EAA8E;AAC9E,yEAAyE;AACzE,iBAAiB;AAEjB,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,eAAe,EACf,aAAa,EACb,OAAO,EACP,WAAW,GACZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,cAAc,EACd,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Temporary Chrome profile directories monobrowse creates, and their removal
|
|
3
|
+
* (#395).
|
|
4
|
+
*
|
|
5
|
+
* Every launch without a caller-supplied `userDataDir` (and every CLI
|
|
6
|
+
* session) gets a fresh `--user-data-dir` directly under `os.tmpdir()`.
|
|
7
|
+
* Nothing used to delete them, so they piled up until /tmp ran out of space
|
|
8
|
+
* (81 profiles, 4.4 GB on one machine). Two paths remove them now:
|
|
9
|
+
*
|
|
10
|
+
* - removeOwnedProfileDir(): when monobrowse closes or kills a browser it
|
|
11
|
+
* launched in a directory it created — after Chrome has exited, since
|
|
12
|
+
* Chrome writes into its profile until then.
|
|
13
|
+
* - sweepStaleProfileDirs(): at the next launch, for directories whose
|
|
14
|
+
* owner crashed or was killed before it could close its browser.
|
|
15
|
+
*
|
|
16
|
+
* Both touch only real directories directly inside the tmp root whose name
|
|
17
|
+
* matches one of the exact patterns below. A caller-supplied `userDataDir`
|
|
18
|
+
* never matches them unless the caller copied our naming, and even then the
|
|
19
|
+
* close path also needs the explicit ownership flag launchBrowser records.
|
|
20
|
+
*/
|
|
21
|
+
/** A directory younger than this is never swept: its launch may still be
|
|
22
|
+
* starting (Chrome has not yet put its pid anywhere we can see). */
|
|
23
|
+
export declare const PROFILE_SWEEP_GRACE_MS: number;
|
|
24
|
+
/** Name for a new default launch profile, directly under `root`. */
|
|
25
|
+
export declare function launchProfileDirPath(port: number, id: string, root?: string): string;
|
|
26
|
+
/** Name for a new CLI session profile, directly under `root`. */
|
|
27
|
+
export declare function sessionProfileDirPath(id: string, root?: string): string;
|
|
28
|
+
/** The pid encoded in a profile directory name we create, or null when
|
|
29
|
+
* `name` is not one of ours. */
|
|
30
|
+
export declare function profileDirOwnerPid(name: string): number | null;
|
|
31
|
+
/**
|
|
32
|
+
* Whether `dir` is a directory monobrowse created: its name matches our
|
|
33
|
+
* pattern, it is a real directory (not a symlink), and its resolved parent
|
|
34
|
+
* is `root`. Anything else is never deleted.
|
|
35
|
+
*/
|
|
36
|
+
export declare function isOwnedProfileDir(dir: string, root?: string): Promise<boolean>;
|
|
37
|
+
/** Whether `pid` is a live process. EPERM means it exists but is not ours. */
|
|
38
|
+
export declare function isPidAlive(pid: number): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Pids of live processes whose command line passes `--user-data-dir=<dir>`,
|
|
41
|
+
* read from `procDir` (Linux /proc). Null when it cannot be read at all, so
|
|
42
|
+
* the caller falls back to other evidence instead of reading "nobody".
|
|
43
|
+
*/
|
|
44
|
+
export declare function profileDirHolders(dir: string, procDir?: string): Promise<number[] | null>;
|
|
45
|
+
/** Whether any live process still uses `dir` as its Chrome profile. `procDir`
|
|
46
|
+
* null skips the /proc scan (non-Linux), leaving only the SingletonLock. */
|
|
47
|
+
export declare function isProfileDirInUse(dir: string, opts?: {
|
|
48
|
+
procDir?: string | null;
|
|
49
|
+
}): Promise<boolean>;
|
|
50
|
+
/**
|
|
51
|
+
* Delete a profile directory monobrowse created, once the browser `pid` that
|
|
52
|
+
* used it has exited (bounded wait) and no other process still holds it.
|
|
53
|
+
* Removal is retried once — Chrome's helpers can still be flushing a file
|
|
54
|
+
* as the first attempt runs. Returns whether the directory is gone. Never
|
|
55
|
+
* throws: a directory left behind is swept at a later launch.
|
|
56
|
+
*/
|
|
57
|
+
export declare function removeOwnedProfileDir(dir: string, opts?: {
|
|
58
|
+
pid?: number;
|
|
59
|
+
root?: string;
|
|
60
|
+
procDir?: string | null;
|
|
61
|
+
}): Promise<boolean>;
|
|
62
|
+
export interface ProfileSweepOptions {
|
|
63
|
+
/** Directory to sweep. Default os.tmpdir(); tests inject their own. */
|
|
64
|
+
root?: string;
|
|
65
|
+
/** Minimum age (by mtime) before a directory may be swept. */
|
|
66
|
+
graceMs?: number;
|
|
67
|
+
/** See isProfileDirInUse. */
|
|
68
|
+
procDir?: string | null;
|
|
69
|
+
now?: number;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Delete profile directories left behind by a monobrowse process that died
|
|
73
|
+
* without closing its browser. A directory directly in `root` is removed
|
|
74
|
+
* only when ALL of these hold:
|
|
75
|
+
* - its name matches one of our exact patterns and it is a real directory
|
|
76
|
+
* (symlinks, files and anything else are never touched);
|
|
77
|
+
* - its mtime is older than the grace period, so a concurrent launch that
|
|
78
|
+
* is still starting is left alone;
|
|
79
|
+
* - the pid in its name is not a live process;
|
|
80
|
+
* - no live Chrome uses it (/proc command lines on Linux, plus the
|
|
81
|
+
* profile's SingletonLock everywhere). A CLI `open` process exits right
|
|
82
|
+
* after launching, so this check is what keeps a live session's profile.
|
|
83
|
+
*
|
|
84
|
+
* Best-effort: any error skips that entry, and the sweep never throws.
|
|
85
|
+
* Returns the directories removed.
|
|
86
|
+
*/
|
|
87
|
+
export declare function sweepStaleProfileDirs(opts?: ProfileSweepOptions): Promise<string[]>;
|
|
88
|
+
//# sourceMappingURL=profile-dir.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile-dir.d.ts","sourceRoot":"","sources":["../../../src/browser/profile-dir.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAWH;qEACqE;AACrE,eAAO,MAAM,sBAAsB,QAAiB,CAAC;AAQrD,oEAAoE;AACpE,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,SAAW,GAAG,MAAM,CAEtF;AAED,iEAAiE;AACjE,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,SAAW,GAAG,MAAM,CAEzE;AAED;iCACiC;AACjC,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAG9D;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,SAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAStF;AAED,8EAA8E;AAC9E,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAQ/C;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,SAAU,GAAG,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAwBhG;AAcD;6EAC6E;AAC7E,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,MAAM,EACX,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAO,GACrC,OAAO,CAAC,OAAO,CAAC,CAOlB;AAMD;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,MAAM,EACX,IAAI,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAO,GAClE,OAAO,CAAC,OAAO,CAAC,CAqBlB;AAED,MAAM,WAAW,mBAAmB;IAClC,uEAAuE;IACvE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6BAA6B;IAC7B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,GAAE,mBAAwB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CA2B7F"}
|