@ultimat3/testing 22.3.4 → 22.3.6
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/package.json +12 -12
- package/src/index.ts +1 -0
- package/src/isolated-plugins.ts +37 -0
- package/src/preload.ts +5 -0
- package/src/registry-leak-guard.ts +4 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ultimat3/testing",
|
|
3
|
-
"version": "22.3.
|
|
3
|
+
"version": "22.3.6",
|
|
4
4
|
"description": "Test harness: cloned template DBs per worker, frozen clock, sealed network, 6 test types",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -35,16 +35,16 @@
|
|
|
35
35
|
"test": "bun test"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@ultimat3/cache": "22.3.
|
|
39
|
-
"@ultimat3/core": "22.3.
|
|
40
|
-
"@ultimat3/db": "22.3.
|
|
41
|
-
"@ultimat3/entity": "22.3.
|
|
42
|
-
"@ultimat3/i18n": "22.3.
|
|
43
|
-
"@ultimat3/jobs": "22.3.
|
|
44
|
-
"@ultimat3/mail": "22.3.
|
|
45
|
-
"@ultimat3/policy": "22.3.
|
|
46
|
-
"@ultimat3/query": "22.3.
|
|
47
|
-
"@ultimat3/realtime": "22.3.
|
|
48
|
-
"@ultimat3/time": "22.3.
|
|
38
|
+
"@ultimat3/cache": "22.3.6",
|
|
39
|
+
"@ultimat3/core": "22.3.6",
|
|
40
|
+
"@ultimat3/db": "22.3.6",
|
|
41
|
+
"@ultimat3/entity": "22.3.6",
|
|
42
|
+
"@ultimat3/i18n": "22.3.6",
|
|
43
|
+
"@ultimat3/jobs": "22.3.6",
|
|
44
|
+
"@ultimat3/mail": "22.3.6",
|
|
45
|
+
"@ultimat3/policy": "22.3.6",
|
|
46
|
+
"@ultimat3/query": "22.3.6",
|
|
47
|
+
"@ultimat3/realtime": "22.3.6",
|
|
48
|
+
"@ultimat3/time": "22.3.6"
|
|
49
49
|
}
|
|
50
50
|
}
|
package/src/index.ts
CHANGED
|
@@ -250,6 +250,7 @@ export {
|
|
|
250
250
|
missingIslandFiles,
|
|
251
251
|
normalizeIslandName,
|
|
252
252
|
} from './island-states-resolve';
|
|
253
|
+
export { ISOLATED_ENV, releasePluginsAfterIsolatedFile } from './isolated-plugins';
|
|
253
254
|
export type { LiveConnection, LiveNodeHandle, LiveNodeOptions } from './live-node';
|
|
254
255
|
export { createLiveNode } from './live-node';
|
|
255
256
|
/**
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Frees each finished test file in an ISOLATED run. Bun 1.4.0 keeps every finished file's global
|
|
2
|
+
// object — its module graph, PGlite heap and fakes — alive under `--isolate` (implied by
|
|
3
|
+
// `--parallel`) once any `Bun.plugin` load/resolve handler is registered, and the framework
|
|
4
|
+
// registers two in every file. `isolated-plugins.test.ts` measures it with real `bun test` runs.
|
|
5
|
+
|
|
6
|
+
import { afterAll } from 'bun:test';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Set by `x test` (`@ultimat3/cli`'s `test-shards.ts`) on every `bun test` it spawns in isolated
|
|
10
|
+
* mode. A preload cannot tell for itself: an isolated file sees the same argv, and a fresh process
|
|
11
|
+
* and env are exactly what isolation looks like from inside.
|
|
12
|
+
*/
|
|
13
|
+
export const ISOLATED_ENV = 'ULTIMATE_TEST_ISOLATED';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* `Bun.plugin.clearAll()` after each file, isolated runs only. Measured on notificado.co's unit
|
|
17
|
+
* suite (652 files, 18 workers): per-worker peak 2.1–2.3 GB → 1.0–1.5 GB, total ~30 GB → 18 GB. The
|
|
18
|
+
* next file's preload registers the plugins again, so every file still gets them.
|
|
19
|
+
*
|
|
20
|
+
* NEVER in a shared process: render's loader keeps an `installed` flag, so a cleared plugin is
|
|
21
|
+
* never re-registered and the next `.tsx` compiles with Bun's classic factory — `__xh is not
|
|
22
|
+
* defined`.
|
|
23
|
+
*/
|
|
24
|
+
export function releasePluginsAfterIsolatedFile(
|
|
25
|
+
env: Readonly<Record<string, string | undefined>> = Bun.env,
|
|
26
|
+
after: (hook: () => void) => void = afterAll,
|
|
27
|
+
plugin: { clearAll(): void } = Bun.plugin,
|
|
28
|
+
): boolean {
|
|
29
|
+
if (env[ISOLATED_ENV] !== '1') return false;
|
|
30
|
+
after(() => clearPlugins(plugin));
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Every `Bun.plugin` handler this process registered. The next file's preload registers them again. */
|
|
35
|
+
export const clearPlugins = (plugin: { clearAll(): void } = Bun.plugin): void => {
|
|
36
|
+
plugin.clearAll();
|
|
37
|
+
};
|
package/src/preload.ts
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
import { installDeterminism } from './determinism';
|
|
9
9
|
import { registerFrameworkFixtures } from './framework-fixtures';
|
|
10
10
|
import './matchers';
|
|
11
|
+
import { releasePluginsAfterIsolatedFile } from './isolated-plugins';
|
|
11
12
|
import { installRegistryLeakGuard } from './registry-leak-guard';
|
|
12
13
|
import { sealNetwork } from './sealed-network';
|
|
13
14
|
|
|
@@ -25,6 +26,10 @@ registerFrameworkFixtures();
|
|
|
25
26
|
// fails a later file in another package, for a reason nothing in that file explains.
|
|
26
27
|
installRegistryLeakGuard();
|
|
27
28
|
|
|
29
|
+
// Isolated runs only (`x test` says so): Bun 1.4.0 keeps every finished file alive while a plugin
|
|
30
|
+
// is registered. See `isolated-plugins.ts`.
|
|
31
|
+
releasePluginsAfterIsolatedFile();
|
|
32
|
+
|
|
28
33
|
// Opt-out exists for one case: a test that deliberately exercises a real integration in a job the
|
|
29
34
|
// team runs on purpose. It is an env var, not an API, so it cannot be set from inside a test file.
|
|
30
35
|
if (Bun.env['ULTIMATE_TEST_ALLOW_NET'] !== '1') sealNetwork();
|
|
@@ -111,8 +111,10 @@ let installed = false;
|
|
|
111
111
|
* otherwise register the hooks twice and report every leak twice.
|
|
112
112
|
*
|
|
113
113
|
* Under `--isolate` each file gets its own module registry, so the guard judges that one file and
|
|
114
|
-
*
|
|
115
|
-
*
|
|
114
|
+
* no REGISTRY state carries across — which is correct, not a hole: a file that leaks is still
|
|
115
|
+
* reported against itself. MEMORY does carry across: on Bun 1.4.0 the plugin this registers keeps
|
|
116
|
+
* every finished file's global object alive for the life of the worker (~57 MB per file measured).
|
|
117
|
+
* `isolated-plugins.ts` clears the plugins after each isolated file.
|
|
116
118
|
*/
|
|
117
119
|
export function installRegistryLeakGuard(): void {
|
|
118
120
|
if (installed) return;
|