-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdetect.ts
More file actions
131 lines (122 loc) · 5.2 KB
/
Copy pathdetect.ts
File metadata and controls
131 lines (122 loc) · 5.2 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
130
131
/**
* @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, requireBuiltin } 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')) {
// requireBuiltin passes a non-literal specifier so AOT bundlers and
// compilers keep this optional binding external; unreached on stock Node.
smolUtilCache = requireBuiltin('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
}