-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdetect.ts
More file actions
129 lines (120 loc) · 5.02 KB
/
detect.ts
File metadata and controls
129 lines (120 loc) · 5.02 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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/**
* @file Smol detection + lazy-loader for `node:smol-util`. Two
* responsibilities:
*
* 1. `isSmol()` — memoized boolean detector for socket-btm's smol Node binary.
* Mirrors `isSeaBinary()` from `src/sea.ts`. Probes via
* `node:module.isBuiltin('node:smol-util')` since only the smol binary
* registers any `node:smol-*` builtins.
* 2. `getSmolUtil()` — lazy-loader for the `node:smol-util` binding, which
* provides native `uncurryThis` and `applyBind` (single V8 dispatch via
* `args.Data()` + `v8::Function::Call`, skipping the BoundFunction adapter
* + `Function.prototype.call` trampoline that the JS form
* `bind.bind(call)(fn)` hits twice per invocation). ~2x faster on hot
* uncurried-call sites. `getSmolUtil()` returns `undefined` on stock Node
* + non-Node runtimes. Result is cached across calls; the lazy-loader
* follows the same shape as `src/node/fs.ts` etc.
*
* @see https://github.com/SocketDev/socket-btm — socket-btm builds
* the smol binary that exposes the `node:smol-util` binding.
*/
import { isNodeBuiltin } from '../node/module'
// ─── types ─────────────────────────────────────────────────────────────
/**
* Surface of `node:smol-util`. See socket-btm's
* additions/source-patched/lib/smol-util.js for the canonical shape.
*/
export interface SmolUtilBinding {
/**
* Native equivalent of `Function.prototype.bind.bind(apply)(fn)`.
*/
applyBind: <T, A extends readonly unknown[], R>(
fn: (this: T, ...args: A) => R,
) => (self: T, args: A) => R
/**
* Native equivalent of: `(self, args) => { try { return fn.apply(self, args)
* } catch {} }`. Returns a function that swallows synchronous throws and
* returns `undefined`. Avoids JS-level throw construction on the swallow path
* — useful for logger sinks, debug hooks, abort handlers, etc.
*/
applySafe: <T, A extends readonly unknown[], R>(
fn: (this: T, ...args: A) => R,
) => (self: T, args: A) => R | undefined
/**
* Native equivalent of: `(...newArgs) => fn.call(thisArg, ...presetArgs,
* ...newArgs)`. Same shape as `Function.prototype.bind` but with a single C++
* dispatch instead of going through V8's BoundFunction adapter. Useful where
* `bind` would be hot — captured callbacks fed to
* `setImmediate`/`setTimeout`/promise continuations.
*/
bindCall: <T, P extends readonly unknown[], A extends readonly unknown[], R>(
fn: (this: T, ...args: [...P, ...A]) => R,
thisArg: T,
...presetArgs: P
) => (...newArgs: A) => R
/**
* Native equivalent of `Function.prototype.bind.bind(call)(fn)`. Single C++
* dispatch via `args.Data()` + `v8::Function::Call`.
*/
uncurryThis: <T, A extends readonly unknown[], R>(
fn: (this: T, ...args: A) => R,
) => (self: T, ...args: A) => R
/**
* Native equivalent of: `try { return new WeakRef(target) } catch { return
* undefined }`. Returns `undefined` for non-Object, non-Symbol inputs that
* would make the constructor throw. The Safe suffix follows the project's
* non-throwing-wrapper convention.
*/
weakRefSafe: <T extends object | symbol>(target: T) => WeakRef<T> | undefined
}
// ─── module-level caches ───────────────────────────────────────────────
/**
* Cached smol-binary detection result.
*/
let isSmolCache: boolean | undefined
/**
* Cached `node:smol-util` binding. `null` = probed and unavailable; `undefined`
* = not yet probed. JS truthiness collapses both to "no binding" at the call
* site.
*/
let smolUtilCache: SmolUtilBinding | undefined
let smolUtilProbed = false
// ─── exports (alphabetical) ────────────────────────────────────────────
/**
* Returns `node:smol-util` when running on the smol Node binary, otherwise
* `undefined`. Result is cached across calls.
*/
export function getSmolUtil(): SmolUtilBinding | undefined {
if (!smolUtilProbed) {
smolUtilProbed = true
/* c8 ignore start - smol Node binary only. */
if (isNodeBuiltin('node:smol-util')) {
smolUtilCache = require('node:smol-util') as SmolUtilBinding
}
/* c8 ignore stop */
}
return smolUtilCache
}
/**
* Detect if the current process is running on socket-btm's smol Node binary.
* Memoized on first call.
*
* Defensive across runtimes: returns `false` on stock Node, browsers (no
* `node:module`), Deno / Bun (different module resolution), and worker threads
* (each has its own builtin table).
*
* @example
* ;```ts
* import { isSmol } from '@socketsecurity/lib/smol/detect'
*
* if (isSmol()) {
* // running on the smol binary; native fast paths available
* }
* ```
*/
export function isSmol(): boolean {
if (isSmolCache === undefined) {
isSmolCache = isNodeBuiltin('node:smol-util')
}
return isSmolCache
}