-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathdetect.ts
More file actions
72 lines (62 loc) · 2.92 KB
/
Copy pathdetect.ts
File metadata and controls
72 lines (62 loc) · 2.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
/**
* Runtime detection for actor-ts.
*
* The framework runs on three JS runtimes — Bun, Node.js, and Deno. Most of
* the codebase is runtime-neutral TypeScript that uses `node:*` modules or
* standard Web APIs, but a few capabilities (TCP sockets, HTTP-server-from-
* fetch-handler, Web Workers, SQLite) need a per-runtime backend. This
* module is the shared place where those backends ask "what am I running
* under?" so the answer is cached, consistent, and overridable in tests.
*
* The module has no dependencies and no side effects beyond the memoised
* cache — it is safe to import from any layer.
*/
export type RuntimeKind = 'bun' | 'node' | 'deno';
type GlobalShape = {
readonly Bun?: { nanoseconds?: () => number } & Record<string, unknown>;
readonly Deno?: Record<string, unknown>;
readonly process?: { versions?: { node?: string; bun?: string; deno?: string } };
readonly performance?: { now(): number };
};
const globalScope: GlobalShape = globalThis as unknown as GlobalShape;
import { Lazy } from '../util/Lazy.js';
/**
* The detected runtime. `Lazy.of(...)` runs the detection once and then
* memoises. Test overrides go through `setOverride` (below) which uses
* `Lazy.setOverride` under the hood — no explicit cache bookkeeping.
*/
const runtimeLazy: Lazy<RuntimeKind> = Lazy.of<RuntimeKind>(() => {
if (typeof globalScope.Bun !== 'undefined') return 'bun';
if (typeof globalScope.Deno !== 'undefined') return 'deno';
return 'node';
});
/** Returns the current runtime. Cached after first call. */
export function detectRuntime(): RuntimeKind { return runtimeLazy.get(); }
/** True iff `globalThis.Bun` is present. */
export function hasBun(): boolean { return typeof globalScope.Bun !== 'undefined'; }
/** True iff `globalThis.Deno` is present. */
export function hasDeno(): boolean { return typeof globalScope.Deno !== 'undefined'; }
/**
* High-resolution timestamp in nanoseconds. Uses `Bun.nanoseconds()` when
* available (it is truly ns-resolution); otherwise falls back to
* `performance.now() * 1e6` which is ms-resolution × 1_000_000 — ~µs
* precision on Node and Deno, still good enough for benchmark harness
* purposes (individual iteration jitter swamps any sub-µs accuracy).
*/
export function highResNow(): number {
const bunNs = globalScope.Bun?.nanoseconds;
if (typeof bunNs === 'function') return bunNs();
const perf = globalScope.performance;
if (perf && typeof perf.now === 'function') return perf.now() * 1_000_000;
// Last-resort: Date.now() has ms resolution. Any benchmark running in
// such a degraded environment deserves what it gets.
return Date.now() * 1_000_000;
}
/**
* Test-only hook: force `detectRuntime()` to return a specific value. Pass
* `null` to restore real detection. Intentionally NOT re-exported from
* `src/index.ts` — it is an internal seam.
*/
export function setRuntimeOverride(r: RuntimeKind | null): void {
runtimeLazy.setOverride(r);
}