@monoes/monobrowse 1.0.27 → 1.0.30

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.
Files changed (80) hide show
  1. package/dist/src/__tests__/browser-launch-double-loss.test.d.ts +16 -0
  2. package/dist/src/__tests__/browser-launch-double-loss.test.d.ts.map +1 -0
  3. package/dist/src/__tests__/browser-launch-double-loss.test.js +119 -0
  4. package/dist/src/__tests__/browser-launch-double-loss.test.js.map +1 -0
  5. package/dist/src/__tests__/chrome-fallback.test.d.ts +2 -0
  6. package/dist/src/__tests__/chrome-fallback.test.d.ts.map +1 -0
  7. package/dist/src/__tests__/chrome-fallback.test.js +63 -0
  8. package/dist/src/__tests__/chrome-fallback.test.js.map +1 -0
  9. package/dist/src/__tests__/disconnect-session.test.d.ts +13 -0
  10. package/dist/src/__tests__/disconnect-session.test.d.ts.map +1 -0
  11. package/dist/src/__tests__/disconnect-session.test.js +37 -0
  12. package/dist/src/__tests__/disconnect-session.test.js.map +1 -0
  13. package/dist/src/__tests__/profile-cleanup-close.test.d.ts +16 -0
  14. package/dist/src/__tests__/profile-cleanup-close.test.d.ts.map +1 -0
  15. package/dist/src/__tests__/profile-cleanup-close.test.js +250 -0
  16. package/dist/src/__tests__/profile-cleanup-close.test.js.map +1 -0
  17. package/dist/src/__tests__/profile-dir.test.d.ts +10 -0
  18. package/dist/src/__tests__/profile-dir.test.d.ts.map +1 -0
  19. package/dist/src/__tests__/profile-dir.test.js +160 -0
  20. package/dist/src/__tests__/profile-dir.test.js.map +1 -0
  21. package/dist/src/__tests__/setup/isolated-tmpdir.global.d.ts +2 -0
  22. package/dist/src/__tests__/setup/isolated-tmpdir.global.d.ts.map +1 -0
  23. package/dist/src/__tests__/setup/isolated-tmpdir.global.js +30 -0
  24. package/dist/src/__tests__/setup/isolated-tmpdir.global.js.map +1 -0
  25. package/dist/src/browser/browser-discovery.d.ts +8 -0
  26. package/dist/src/browser/browser-discovery.d.ts.map +1 -1
  27. package/dist/src/browser/browser-discovery.js +25 -0
  28. package/dist/src/browser/browser-discovery.js.map +1 -1
  29. package/dist/src/browser/browser-launch.d.ts.map +1 -1
  30. package/dist/src/browser/browser-launch.js +48 -10
  31. package/dist/src/browser/browser-launch.js.map +1 -1
  32. package/dist/src/browser/browser-lifecycle.d.ts +5 -0
  33. package/dist/src/browser/browser-lifecycle.d.ts.map +1 -1
  34. package/dist/src/browser/browser-lifecycle.js +23 -11
  35. package/dist/src/browser/browser-lifecycle.js.map +1 -1
  36. package/dist/src/browser/browser-state.d.ts +4 -0
  37. package/dist/src/browser/browser-state.d.ts.map +1 -1
  38. package/dist/src/browser/browser-state.js +10 -2
  39. package/dist/src/browser/browser-state.js.map +1 -1
  40. package/dist/src/browser/browser.d.ts +2 -2
  41. package/dist/src/browser/browser.d.ts.map +1 -1
  42. package/dist/src/browser/browser.js +2 -2
  43. package/dist/src/browser/browser.js.map +1 -1
  44. package/dist/src/browser/profile-dir.d.ts +88 -0
  45. package/dist/src/browser/profile-dir.d.ts.map +1 -0
  46. package/dist/src/browser/profile-dir.js +242 -0
  47. package/dist/src/browser/profile-dir.js.map +1 -0
  48. package/dist/src/browser/ref-cache.d.ts +4 -0
  49. package/dist/src/browser/ref-cache.d.ts.map +1 -1
  50. package/dist/src/browser/ref-cache.js +2 -0
  51. package/dist/src/browser/ref-cache.js.map +1 -1
  52. package/dist/src/browser/types.d.ts +6 -0
  53. package/dist/src/browser/types.d.ts.map +1 -1
  54. package/dist/src/browser/types.js.map +1 -1
  55. package/dist/src/cli/commands.d.ts +1 -0
  56. package/dist/src/cli/commands.d.ts.map +1 -1
  57. package/dist/src/cli/commands.js +2 -0
  58. package/dist/src/cli/commands.js.map +1 -1
  59. package/dist/src/cli/session.d.ts +9 -0
  60. package/dist/src/cli/session.d.ts.map +1 -1
  61. package/dist/src/cli/session.js +21 -4
  62. package/dist/src/cli/session.js.map +1 -1
  63. package/dist/tsconfig.tsbuildinfo +1 -1
  64. package/package.json +1 -1
  65. package/src/__tests__/browser-launch-double-loss.test.ts +128 -0
  66. package/src/__tests__/chrome-fallback.test.ts +74 -0
  67. package/src/__tests__/disconnect-session.test.ts +42 -0
  68. package/src/__tests__/profile-cleanup-close.test.ts +285 -0
  69. package/src/__tests__/profile-dir.test.ts +196 -0
  70. package/src/__tests__/setup/isolated-tmpdir.global.ts +28 -0
  71. package/src/browser/browser-discovery.ts +25 -0
  72. package/src/browser/browser-launch.ts +49 -11
  73. package/src/browser/browser-lifecycle.ts +20 -10
  74. package/src/browser/browser-state.ts +11 -2
  75. package/src/browser/browser.ts +6 -2
  76. package/src/browser/profile-dir.ts +249 -0
  77. package/src/browser/ref-cache.ts +7 -0
  78. package/src/browser/types.ts +6 -0
  79. package/src/cli/commands.ts +2 -0
  80. package/src/cli/session.ts +22 -4
@@ -0,0 +1,16 @@
1
+ /**
2
+ * #491: two launches that call listen() on the same free port at the same
3
+ * instant can BOTH lose it on Linux (each socket is marked LISTEN before the
4
+ * port conflict check, so each sees the other and gets EADDRINUSE). Both
5
+ * Chromes exit before their CDP endpoint opens and the port is free again
6
+ * afterwards, so the lost race looks exactly like a Chrome that cannot start.
7
+ *
8
+ * The double loss is a kernel timing window (about 1 in 600 races locally),
9
+ * so these tests reproduce its outcome deterministically instead: a fake
10
+ * Chrome that exits early without binding on its first start.
11
+ *
12
+ * Fixed ports 23440-23449, clear of browser-launch.test.ts (23460-23489) and
13
+ * reap-idle-browser.test.ts (23490-23499), which run in parallel workers.
14
+ */
15
+ export {};
16
+ //# sourceMappingURL=browser-launch-double-loss.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-launch-double-loss.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/browser-launch-double-loss.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG"}
@@ -0,0 +1,119 @@
1
+ /**
2
+ * #491: two launches that call listen() on the same free port at the same
3
+ * instant can BOTH lose it on Linux (each socket is marked LISTEN before the
4
+ * port conflict check, so each sees the other and gets EADDRINUSE). Both
5
+ * Chromes exit before their CDP endpoint opens and the port is free again
6
+ * afterwards, so the lost race looks exactly like a Chrome that cannot start.
7
+ *
8
+ * The double loss is a kernel timing window (about 1 in 600 races locally),
9
+ * so these tests reproduce its outcome deterministically instead: a fake
10
+ * Chrome that exits early without binding on its first start.
11
+ *
12
+ * Fixed ports 23440-23449, clear of browser-launch.test.ts (23460-23489) and
13
+ * reap-idle-browser.test.ts (23490-23499), which run in parallel workers.
14
+ */
15
+ import { execFileSync } from 'node:child_process';
16
+ import { chmodSync, existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
17
+ import { tmpdir } from 'node:os';
18
+ import { join } from 'node:path';
19
+ import { afterEach, describe, expect, it } from 'vitest';
20
+ import { getLaunchedPid, launchBrowser } from '../browser/browser.js';
21
+ const BASE = 23440;
22
+ const dirs = [];
23
+ afterEach(() => {
24
+ for (const dir of dirs.splice(0)) {
25
+ try {
26
+ execFileSync('pkill', ['-KILL', '-f', dir]);
27
+ }
28
+ catch {
29
+ /* nothing left running */
30
+ }
31
+ rmSync(dir, { recursive: true, force: true });
32
+ }
33
+ });
34
+ /**
35
+ * A fixed-port fake Chrome. It exits with code 21 before binding anything
36
+ * on each of its first `lostStarts` starts (counted in a file next to it),
37
+ * and on every start for `lostPort`, which is what a Chrome that lost the
38
+ * double-EADDRINUSE race looks like. Otherwise it binds the port and
39
+ * announces itself like real Chrome.
40
+ */
41
+ function fakeChrome(lostStarts, lostPort = 0) {
42
+ const dir = mkdtempSync(join(tmpdir(), 'monobrowse-491-'));
43
+ dirs.push(dir);
44
+ const exe = join(dir, 'fake-chrome.cjs');
45
+ writeFileSync(exe, `#!/usr/bin/env node
46
+ const { createServer } = require('node:http');
47
+ const { existsSync, readFileSync, writeFileSync } = require('node:fs');
48
+ const port = Number(
49
+ process.argv.find((a) => a.startsWith('--remote-debugging-port=')).slice('--remote-debugging-port='.length),
50
+ );
51
+ const counter = ${JSON.stringify(join(dir, 'starts'))};
52
+ const starts = existsSync(counter) ? Number(readFileSync(counter, 'utf8')) : 0;
53
+ writeFileSync(counter, String(starts + 1));
54
+ if (starts < ${lostStarts} || port === ${lostPort}) process.exit(21);
55
+ setTimeout(() => process.exit(0), 30000).unref();
56
+ const ws = 'ws://127.0.0.1:' + port + '/devtools/browser/fake-' + process.pid;
57
+ const server = createServer((req, res) => {
58
+ res.writeHead(200, { 'Content-Type': 'application/json' });
59
+ res.end(
60
+ req.url === '/json/version'
61
+ ? JSON.stringify({ Browser: 'Chrome/999.0.0.0', webSocketDebuggerUrl: ws })
62
+ : '[]',
63
+ );
64
+ });
65
+ server.listen(port, '127.0.0.1', () => {
66
+ process.stderr.write('\\nDevTools listening on ' + ws + '\\n');
67
+ });
68
+ `);
69
+ chmodSync(exe, 0o755);
70
+ return exe;
71
+ }
72
+ function startsOf(exe) {
73
+ const counter = join(exe, '..', 'starts');
74
+ return existsSync(counter) ? Number(readFileSync(counter, 'utf8')) : 0;
75
+ }
76
+ describe.skipIf(process.platform === 'win32')('launchBrowser — a Chrome that lost the port race with nothing left listening (#491)', () => {
77
+ it('moves on to the next candidate instead of failing the launch', async () => {
78
+ const exe = fakeChrome(1);
79
+ const port = await launchBrowser({ port: BASE, executablePath: exe, launchTimeoutMs: 5000 });
80
+ try {
81
+ expect(port).toBe(BASE + 1);
82
+ expect(startsOf(exe)).toBe(2);
83
+ }
84
+ finally {
85
+ process.kill(getLaunchedPid(port), 'SIGKILL');
86
+ }
87
+ }, 15000);
88
+ it('two concurrent launches that both lost the same candidate both succeed, on different ports', async () => {
89
+ // The CI failure's shape: both racers' Chromes exited early on the
90
+ // first candidate and neither found anything listening there.
91
+ const exe = fakeChrome(0, BASE + 2);
92
+ let results = [];
93
+ try {
94
+ results = await Promise.allSettled([
95
+ launchBrowser({ port: BASE + 2, executablePath: exe, launchTimeoutMs: 5000 }),
96
+ launchBrowser({ port: BASE + 2, executablePath: exe, launchTimeoutMs: 5000 }),
97
+ ]);
98
+ }
99
+ finally {
100
+ for (const r of results) {
101
+ const pid = r.status === 'fulfilled' ? getLaunchedPid(r.value) : undefined;
102
+ if (pid)
103
+ process.kill(pid, 'SIGKILL');
104
+ }
105
+ }
106
+ for (const r of results)
107
+ if (r.status === 'rejected')
108
+ throw r.reason;
109
+ const ports = results.map((r) => r.value);
110
+ expect(ports[0]).not.toBe(ports[1]);
111
+ expect(ports).not.toContain(BASE + 2);
112
+ }, 15000);
113
+ it('still surfaces a Chrome that cannot start, after one more attempt', async () => {
114
+ const exe = fakeChrome(Number.POSITIVE_INFINITY);
115
+ await expect(launchBrowser({ port: BASE + 5, executablePath: exe, launchTimeoutMs: 5000 })).rejects.toThrow(/exited before the CDP endpoint opened on port 23445 \(code=21/);
116
+ expect(startsOf(exe)).toBe(2);
117
+ }, 15000);
118
+ });
119
+ //# sourceMappingURL=browser-launch-double-loss.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-launch-double-loss.test.js","sourceRoot":"","sources":["../../../src/__tests__/browser-launch-double-loss.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=chrome-fallback.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chrome-fallback.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/chrome-fallback.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * #428: an installed browser always wins; monomind's downloaded Chrome (the
3
+ * registered fallback, or MONOBROWSE_CHROME_PATH for a child process) is used
4
+ * only when there is none.
5
+ */
6
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
7
+ const present = new Set();
8
+ vi.mock('node:fs', async (orig) => ({
9
+ ...(await orig()),
10
+ existsSync: (p) => present.has(p),
11
+ }));
12
+ vi.mock('node:child_process', async (orig) => ({
13
+ ...(await orig()),
14
+ execSync: () => {
15
+ throw new Error('which: nothing found');
16
+ },
17
+ }));
18
+ const { findChrome, resolveChrome, setChromeFallback } = await import('../browser/browser-discovery.js');
19
+ const { CHROME_EXECUTABLES } = await import('../browser/types.js');
20
+ const SYSTEM = CHROME_EXECUTABLES.find((p) => p.startsWith('/usr/bin/'));
21
+ beforeEach(() => {
22
+ present.clear();
23
+ delete process.env.MONOBROWSE_CHROME_PATH;
24
+ });
25
+ afterEach(() => {
26
+ setChromeFallback(undefined);
27
+ delete process.env.MONOBROWSE_CHROME_PATH;
28
+ });
29
+ describe('resolveChrome', () => {
30
+ it('throws the usual error when there is no browser and no fallback', async () => {
31
+ await expect(resolveChrome()).rejects.toThrow('No supported browser found');
32
+ });
33
+ it('asks the fallback only when no browser is installed', async () => {
34
+ const fallback = vi.fn(async () => '/deps/chrome');
35
+ setChromeFallback(fallback);
36
+ await expect(resolveChrome()).resolves.toBe('/deps/chrome');
37
+ expect(fallback).toHaveBeenCalledOnce();
38
+ present.add(SYSTEM);
39
+ fallback.mockClear();
40
+ await expect(resolveChrome()).resolves.toBe(SYSTEM);
41
+ expect(fallback).not.toHaveBeenCalled();
42
+ });
43
+ it('never falls back for an explicit executablePath', async () => {
44
+ const fallback = vi.fn(async () => '/deps/chrome');
45
+ setChromeFallback(fallback);
46
+ await expect(resolveChrome('/nope/chrome')).rejects.toThrow('Chrome executable not found');
47
+ expect(fallback).not.toHaveBeenCalled();
48
+ });
49
+ });
50
+ describe('findChrome and MONOBROWSE_CHROME_PATH', () => {
51
+ it('uses the variable only when no browser is installed', () => {
52
+ process.env.MONOBROWSE_CHROME_PATH = '/deps/chrome';
53
+ present.add('/deps/chrome');
54
+ expect(findChrome()).toBe('/deps/chrome');
55
+ present.add(SYSTEM);
56
+ expect(findChrome()).toBe(SYSTEM);
57
+ });
58
+ it('ignores a variable that points at nothing', () => {
59
+ process.env.MONOBROWSE_CHROME_PATH = '/deps/missing';
60
+ expect(() => findChrome()).toThrow('No supported browser found');
61
+ });
62
+ });
63
+ //# sourceMappingURL=chrome-fallback.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chrome-fallback.test.js","sourceRoot":"","sources":["../../../src/__tests__/chrome-fallback.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * disconnectSession() — drops this process's CDP connection without touching
3
+ * the browser (#408).
4
+ *
5
+ * `monomind browse` runs inside a CLI that lets the event loop drain instead
6
+ * of calling process.exit() (ADR-R001). A CDP websocket left open after the
7
+ * subcommand printed its output kept every `monomind browse …` alive until the
8
+ * 5 s force-exit watchdog. The embedder calls disconnectSession() once the
9
+ * subcommand is done; the browser must survive it, because the next command
10
+ * (a new process) reconnects to that same session.
11
+ */
12
+ export {};
13
+ //# sourceMappingURL=disconnect-session.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"disconnect-session.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/disconnect-session.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * disconnectSession() — drops this process's CDP connection without touching
3
+ * the browser (#408).
4
+ *
5
+ * `monomind browse` runs inside a CLI that lets the event loop drain instead
6
+ * of calling process.exit() (ADR-R001). A CDP websocket left open after the
7
+ * subcommand printed its output kept every `monomind browse …` alive until the
8
+ * 5 s force-exit watchdog. The embedder calls disconnectSession() once the
9
+ * subcommand is done; the browser must survive it, because the next command
10
+ * (a new process) reconnects to that same session.
11
+ */
12
+ import { describe, expect, it, vi } from 'vitest';
13
+ import { disconnectSession } from '../cli/commands.js';
14
+ import { session } from '../cli/session.js';
15
+ describe('disconnectSession', () => {
16
+ it('closes the CDP client and clears it, leaving the session record alone', () => {
17
+ const close = vi.fn();
18
+ const send = vi.fn();
19
+ session.client = { close, send };
20
+ session.sessionId = 'sid-1';
21
+ session.port = 9333;
22
+ disconnectSession();
23
+ expect(close).toHaveBeenCalledTimes(1);
24
+ // No CDP command either: Browser.close would end the session others reuse.
25
+ expect(send).not.toHaveBeenCalled();
26
+ expect(session.client).toBeNull();
27
+ expect(session.sessionId).toBe('');
28
+ // The port pin survives so a later in-process command resolves the same session.
29
+ expect(session.port).toBe(9333);
30
+ });
31
+ it('is a no-op when no client was ever connected', () => {
32
+ session.client = null;
33
+ expect(() => disconnectSession()).not.toThrow();
34
+ expect(session.client).toBeNull();
35
+ });
36
+ });
37
+ //# sourceMappingURL=disconnect-session.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"disconnect-session.test.js","sourceRoot":"","sources":["../../../src/__tests__/disconnect-session.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAElD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAE5C,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,EAAE,CAAC,uEAAuE,EAAE,GAAG,EAAE;QAC/E,MAAM,KAAK,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QACtB,MAAM,IAAI,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QACrB,OAAO,CAAC,MAAM,GAAG,EAAE,KAAK,EAAE,IAAI,EAA0B,CAAC;QACzD,OAAO,CAAC,SAAS,GAAG,OAAO,CAAC;QAC5B,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;QAEpB,iBAAiB,EAAE,CAAC;QAEpB,MAAM,CAAC,KAAK,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QACvC,2EAA2E;QAC3E,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QACpC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC;QAClC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACnC,iFAAiF;QACjF,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;QACtB,MAAM,CAAC,GAAG,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QAChD,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC;IACpC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * #395: closing (or killing) a browser monobrowse launched deletes the temp
3
+ * profile dir monobrowse created for it — and never a caller-supplied one.
4
+ *
5
+ * No real Chrome: launchBrowser spawns a fake-chrome script that behaves
6
+ * like Chrome where it matters here (creates and writes into its
7
+ * --user-data-dir, serves /json/version, announces its browser id on stderr,
8
+ * writes DevToolsActivePort for port 0). Browser.close goes over a fake `ws`
9
+ * socket that kills the fixture, as a real Chrome exits on it. A client that
10
+ * never connected drives the kill fallback (its Browser.close fails at once).
11
+ *
12
+ * TMPDIR is pointed at a root of each test's own, so both the launch-time
13
+ * sweep and the default profile dir live there — never the real /tmp.
14
+ */
15
+ export {};
16
+ //# sourceMappingURL=profile-cleanup-close.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile-cleanup-close.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/profile-cleanup-close.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG"}
@@ -0,0 +1,250 @@
1
+ /**
2
+ * #395: closing (or killing) a browser monobrowse launched deletes the temp
3
+ * profile dir monobrowse created for it — and never a caller-supplied one.
4
+ *
5
+ * No real Chrome: launchBrowser spawns a fake-chrome script that behaves
6
+ * like Chrome where it matters here (creates and writes into its
7
+ * --user-data-dir, serves /json/version, announces its browser id on stderr,
8
+ * writes DevToolsActivePort for port 0). Browser.close goes over a fake `ws`
9
+ * socket that kills the fixture, as a real Chrome exits on it. A client that
10
+ * never connected drives the kill fallback (its Browser.close fails at once).
11
+ *
12
+ * TMPDIR is pointed at a root of each test's own, so both the launch-time
13
+ * sweep and the default profile dir live there — never the real /tmp.
14
+ */
15
+ import { spawn } from 'node:child_process';
16
+ import { chmodSync, existsSync, mkdirSync, readdirSync, writeFileSync } from 'node:fs';
17
+ import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises';
18
+ import { createServer } from 'node:net';
19
+ import { tmpdir } from 'node:os';
20
+ import { join } from 'node:path';
21
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
22
+ let onBrowserClose = null;
23
+ let lastSocket = null;
24
+ /** Acknowledges every command; `Browser.close` also runs onBrowserClose. */
25
+ class FakeWs {
26
+ url;
27
+ handlers = new Map();
28
+ constructor(url) {
29
+ this.url = url;
30
+ lastSocket = this;
31
+ }
32
+ on(event, fn) {
33
+ if (!this.handlers.has(event))
34
+ this.handlers.set(event, []);
35
+ this.handlers.get(event).push(fn);
36
+ }
37
+ emit(event, ...args) {
38
+ for (const fn of [...(this.handlers.get(event) ?? [])])
39
+ fn(...args);
40
+ }
41
+ send(data) {
42
+ const { id, method } = JSON.parse(data);
43
+ if (method === 'Browser.close')
44
+ onBrowserClose?.();
45
+ queueMicrotask(() => this.emit('message', Buffer.from(JSON.stringify({ id, result: {} }))));
46
+ }
47
+ close() { }
48
+ }
49
+ vi.mock('ws', () => ({ WebSocket: FakeWs }));
50
+ // Exits once the test process is gone, and within a minute regardless, so a
51
+ // fixture never outlives the run.
52
+ const FAKE_CHROME = `#!/usr/bin/env node
53
+ const parent = process.ppid;
54
+ setInterval(() => {
55
+ try { if (process.ppid !== parent) process.exit(0); process.kill(parent, 0); } catch { process.exit(0); }
56
+ }, 1000).unref();
57
+ setTimeout(() => process.exit(0), 60000).unref();
58
+ const { createServer } = require('node:http');
59
+ const { mkdirSync, writeFileSync } = require('node:fs');
60
+ const { join } = require('node:path');
61
+ const arg = (k) => process.argv.find((a) => a.startsWith(k + '=')).slice(k.length + 1);
62
+ const dir = arg('--user-data-dir');
63
+ const wanted = Number(arg('--remote-debugging-port'));
64
+ mkdirSync(join(dir, 'Default'), { recursive: true });
65
+ writeFileSync(join(dir, 'Default', 'Preferences'), '{}');
66
+ const server = createServer((req, res) => {
67
+ const port = server.address().port;
68
+ const ws = 'ws://127.0.0.1:' + port + '/devtools/browser/fake-' + process.pid;
69
+ res.writeHead(200, { 'Content-Type': 'application/json' });
70
+ res.end(req.url === '/json/version'
71
+ ? JSON.stringify({ Browser: 'Chrome/999.0.0.0', webSocketDebuggerUrl: ws })
72
+ : '[]');
73
+ });
74
+ server.listen(wanted, '127.0.0.1', () => {
75
+ const port = server.address().port;
76
+ if (wanted === 0) writeFileSync(join(dir, 'DevToolsActivePort'), port + '\\n/devtools/browser/fake');
77
+ process.stderr.write('DevTools listening on ws://127.0.0.1:' + port + '/devtools/browser/fake-' + process.pid + '\\n');
78
+ });
79
+ `;
80
+ let root;
81
+ let fixtures;
82
+ let cwd;
83
+ let exe;
84
+ const children = [];
85
+ const launchedPids = [];
86
+ beforeEach(async () => {
87
+ root = await mkdtemp(join(tmpdir(), 'monobrowse-395-root-'));
88
+ fixtures = await mkdtemp(join(tmpdir(), 'monobrowse-395-fixture-'));
89
+ cwd = await mkdtemp(join(tmpdir(), 'monobrowse-395-cwd-'));
90
+ vi.stubEnv('TMPDIR', root);
91
+ vi.spyOn(process, 'cwd').mockReturnValue(cwd);
92
+ exe = join(fixtures, 'fake-chrome.cjs');
93
+ writeFileSync(exe, FAKE_CHROME);
94
+ chmodSync(exe, 0o755);
95
+ onBrowserClose = null;
96
+ lastSocket = null;
97
+ vi.resetModules();
98
+ });
99
+ afterEach(async () => {
100
+ vi.unstubAllEnvs();
101
+ vi.restoreAllMocks();
102
+ for (const pid of launchedPids.splice(0)) {
103
+ try {
104
+ process.kill(pid, 'SIGKILL');
105
+ }
106
+ catch {
107
+ /* already gone */
108
+ }
109
+ }
110
+ for (const child of children.splice(0))
111
+ child.kill('SIGKILL');
112
+ for (const dir of [root, fixtures, cwd])
113
+ await rm(dir, { recursive: true, force: true });
114
+ });
115
+ function freePort() {
116
+ return new Promise((resolve, reject) => {
117
+ const server = createServer();
118
+ server.once('error', reject);
119
+ server.listen(0, '127.0.0.1', () => {
120
+ const { port } = server.address();
121
+ server.close(() => resolve(port));
122
+ });
123
+ });
124
+ }
125
+ /** A client whose Browser.close is acknowledged, and makes `pid` exit the
126
+ * way Chrome does on it. */
127
+ async function gracefulClient(pid) {
128
+ const { CdpClient } = await import('../browser/cdp.js');
129
+ const client = new CdpClient();
130
+ const p = client.connect('ws://127.0.0.1:1/devtools/browser/fake');
131
+ lastSocket.emit('open');
132
+ await p;
133
+ onBrowserClose = () => process.kill(pid, 'SIGTERM');
134
+ return client;
135
+ }
136
+ /** A client that never connected: Browser.close fails at once, so
137
+ * closeBrowser takes its kill fallback. */
138
+ async function deadClient() {
139
+ const { CdpClient } = await import('../browser/cdp.js');
140
+ return new CdpClient();
141
+ }
142
+ async function launch(config) {
143
+ const browser = await import('../browser/browser.js');
144
+ const port = await browser.launchBrowser({ executablePath: exe, ...config });
145
+ const pid = browser.getLaunchedPid(port);
146
+ launchedPids.push(pid);
147
+ return { browser, port, pid, dir: browser.getLaunchedUserDataDir(port) };
148
+ }
149
+ describe.skipIf(process.platform === 'win32')('#395 profile dir cleanup on close', () => {
150
+ it('launch then graceful close removes the default profile dir it created', async () => {
151
+ const { browser, port, pid, dir } = await launch({ port: await freePort() });
152
+ expect(dir.startsWith(root)).toBe(true);
153
+ expect(existsSync(join(dir, 'Default', 'Preferences'))).toBe(true);
154
+ expect(browser.ownsLaunchedUserDataDir(port)).toBe(true);
155
+ await browser.closeBrowser(await gracefulClient(pid), port);
156
+ expect(existsSync(dir)).toBe(false);
157
+ }, 20_000);
158
+ it('removes a CLI session profile (port 0, ownsUserDataDir) on close', async () => {
159
+ const browser = await import('../browser/browser.js');
160
+ const { sessionProfileDirPath } = await import('../browser/profile-dir.js');
161
+ const own = sessionProfileDirPath('abcdef12');
162
+ expect(own.startsWith(root)).toBe(true);
163
+ const { port, pid, dir } = await launch({ port: 0, userDataDir: own, ownsUserDataDir: true });
164
+ expect(dir).toBe(own);
165
+ await browser.closeBrowser(await gracefulClient(pid), port);
166
+ expect(existsSync(own)).toBe(false);
167
+ }, 20_000);
168
+ it('never deletes a caller-supplied userDataDir, even one named like ours', async () => {
169
+ const mine = join(root, 'my-profile');
170
+ const lookalike = join(root, `monomind-browse-${process.pid}-0badc0de`);
171
+ for (const userDataDir of [mine, lookalike]) {
172
+ mkdirSync(userDataDir);
173
+ const { browser, port, pid } = await launch({ port: 0, userDataDir });
174
+ expect(browser.ownsLaunchedUserDataDir(port)).toBe(false);
175
+ await browser.closeBrowser(await gracefulClient(pid), port);
176
+ expect(existsSync(join(userDataDir, 'Default', 'Preferences')), userDataDir).toBe(true);
177
+ }
178
+ }, 30_000);
179
+ it('the kill fallback removes the created dir once the process is gone', async () => {
180
+ const { browser, port, pid, dir } = await launch({ port: await freePort() });
181
+ expect(existsSync(dir)).toBe(true);
182
+ await browser.closeBrowser(await deadClient(), port);
183
+ expect(() => process.kill(pid, 0)).toThrow();
184
+ expect(existsSync(dir)).toBe(false);
185
+ }, 20_000);
186
+ it('a failed launch removes the profile dir it created', async () => {
187
+ const dying = join(fixtures, 'dying-chrome.cjs');
188
+ writeFileSync(dying, `#!/usr/bin/env node
189
+ const dir = process.argv.find((a) => a.startsWith('--user-data-dir=')).slice(16);
190
+ require('node:fs').mkdirSync(dir, { recursive: true });
191
+ process.exit(1);
192
+ `);
193
+ chmodSync(dying, 0o755);
194
+ const browser = await import('../browser/browser.js');
195
+ const port = await freePort();
196
+ await expect(browser.launchBrowser({ port, strictPort: true, executablePath: dying })).rejects.toThrow(/exited before the CDP endpoint opened/);
197
+ expect(readdirSync(root)).toEqual([]);
198
+ }, 20_000);
199
+ });
200
+ describe.skipIf(process.platform === 'win32')('#395 fresh-process close via the persisted session', () => {
201
+ /** A live stand-in for a Chrome some earlier CLI process launched, its
202
+ * profile dir, and the session record that process left behind. */
203
+ async function persistedSession(ownsUserDataDir) {
204
+ const dir = join(root, `monomind-browse-${process.pid}-5e55107${ownsUserDataDir ? 'a' : 'b'}`);
205
+ await mkdir(join(dir, 'Default'), { recursive: true });
206
+ await writeFile(join(dir, 'Default', 'Preferences'), '{}');
207
+ const child = spawn(process.execPath, ['-e', 'setInterval(() => {}, 1000)'], {
208
+ stdio: 'ignore',
209
+ });
210
+ children.push(child);
211
+ await new Promise((resolve) => child.once('spawn', resolve));
212
+ const port = await freePort();
213
+ const sessions = join(cwd, '.monomind', 'monobrowse', 'sessions');
214
+ await mkdir(sessions, { recursive: true });
215
+ await writeFile(join(sessions, `${port}.json`), JSON.stringify({
216
+ port,
217
+ launched: true,
218
+ pid: child.pid,
219
+ userDataDir: dir,
220
+ ownsUserDataDir,
221
+ savedAt: Date.now(),
222
+ }));
223
+ return { dir, pid: child.pid, port };
224
+ }
225
+ it('removes the dir when the record says monobrowse owns it', async () => {
226
+ const { dir, port } = await persistedSession(true);
227
+ const browser = await import('../browser/browser.js');
228
+ const { loadSessionRecord } = await import('../browser/ref-cache.js');
229
+ expect((await loadSessionRecord(port))?.ownsUserDataDir).toBe(true);
230
+ await browser.closeBrowser(await deadClient(), port);
231
+ expect(existsSync(dir)).toBe(false);
232
+ }, 20_000);
233
+ it('keeps the dir (still killing the browser) when the record has no ownership flag', async () => {
234
+ const { dir, pid, port } = await persistedSession(undefined);
235
+ const browser = await import('../browser/browser.js');
236
+ await browser.closeBrowser(await deadClient(), port);
237
+ for (let i = 0; i < 40; i++) {
238
+ try {
239
+ process.kill(pid, 0);
240
+ }
241
+ catch {
242
+ break;
243
+ }
244
+ await new Promise((resolve) => setTimeout(resolve, 50));
245
+ }
246
+ expect(() => process.kill(pid, 0)).toThrow();
247
+ expect(existsSync(join(dir, 'Default', 'Preferences'))).toBe(true);
248
+ }, 20_000);
249
+ });
250
+ //# sourceMappingURL=profile-cleanup-close.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile-cleanup-close.test.js","sourceRoot":"","sources":["../../../src/__tests__/profile-cleanup-close.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * #395: the crash sweep and ownership checks for the temp Chrome profiles
3
+ * monobrowse creates (profile-dir.ts).
4
+ *
5
+ * Every test sweeps a root of its own made with mkdtemp — never the real
6
+ * /tmp, where other sessions' live Chrome profiles live. (The whole package
7
+ * run also gets a throwaway TMPDIR, see setup/isolated-tmpdir.global.ts.)
8
+ */
9
+ export {};
10
+ //# sourceMappingURL=profile-dir.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile-dir.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/profile-dir.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}