castrum 0.9.1 → 0.9.2
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/README.md +1 -1
- package/castrum.linux-x64-gnu.node +0 -0
- package/dist/index.d.ts +239 -5
- package/dist/index.js +3852 -3375
- package/docs/ARCHITECTURE.md +11 -9
- package/docs/BENCHMARKS.md +70 -38
- package/docs/CASE_STUDY.md +10 -7
- package/docs/ENVIRONMENT.md +16 -1
- package/docs/FFI_BUN_GUIDE.md +18 -10
- package/docs/GETTING_STARTED.md +5 -4
- package/docs/HOW_TO_ADD_AN_OP.md +180 -0
- package/docs/INGRESS-ROUTER.md +3 -2
- package/docs/INGRESS.md +6 -3
- package/docs/NATIVE-ROUTE.md +28 -4
- package/docs/REPO_MAP.md +60 -30
- package/docs/adr/0001-two-wire-formats.md +1 -1
- package/docs/ai/LOCAL_DEV.md +81 -0
- package/docs/ai/TREE.md +1070 -0
- package/package.json +24 -23
- package/src/ingress/decode/result-base.ts +10 -2
- package/src/ingress/handlers.ts +45 -290
- package/src/ingress/headers/security.ts +41 -0
- package/src/ingress/index.ts +12 -148
- package/src/ingress/native-route.ts +182 -0
- package/src/ingress/packing/gather-raw-headers.ts +26 -2
- package/src/ingress/packing/route-wire.ts +197 -0
- package/src/ingress/packing/select-headers.ts +8 -1
- package/src/ingress/path-matcher.ts +115 -0
- package/src/ingress/response/baked-response.ts +302 -0
- package/src/ingress/router.ts +42 -2
- package/src/ingress/routes/common.ts +9 -1
- package/src/ingress/routes/json-write.ts +21 -18
- package/src/ingress/routes/native.ts +130 -0
- package/src/ingress/server-node.ts +1 -1
- package/src/ingress/server.ts +38 -99
- package/src/ingress/sync.ts +151 -0
- package/src/ingress/types.ts +9 -0
- package/src/native/ffi/build/codecs.ts +736 -0
- package/src/native/ffi/build/compress.ts +248 -0
- package/src/native/ffi/build/instances.ts +598 -0
- package/src/native/ffi/build/parse.ts +539 -0
- package/src/native/ffi/build/util.ts +140 -0
- package/src/native/ffi/build.ts +94 -0
- package/src/native/ffi/selftest.ts +11 -718
- package/src/native/ffi/types.ts +25 -0
- package/src/native/ffi.ts +36 -1320
- package/src/native/types/instances.ts +5 -0
- package/src/rust-ffi/packed.ts +38 -0
- package/src/rust-ffi/scalar/factories.ts +4 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// src/native/ffi/build.ts — the `build()` orchestrator for the BunFFI surface.
|
|
2
|
+
//
|
|
3
|
+
// `build(sym, useBufferLength)` sets up the shared per-bind state — the
|
|
4
|
+
// probe-gated `lenOrView`/`oneArg` argument adapters and the pooled scratch
|
|
5
|
+
// buffers — then delegates to the four domain builders (each receives the raw
|
|
6
|
+
// dlopen'd symbols + this context) and merges their method objects into the
|
|
7
|
+
// final `BunFFI`. Extracted from the former monolithic `ffi.ts` so the
|
|
8
|
+
// per-call wrapper surface is navigable by domain:
|
|
9
|
+
// - `build/codecs.ts` hashing / codec / crypto / auth / ws-key / etag
|
|
10
|
+
// - `build/compress.ts` gzip / brotli / json patch
|
|
11
|
+
// - `build/parse.ts` packed parsers / media-type / http-date / sse
|
|
12
|
+
// - `build/instances.ts` opaque-handle evals + ingress + route stack
|
|
13
|
+
|
|
14
|
+
import { buildCodecs } from './build/codecs'
|
|
15
|
+
import { buildCompress } from './build/compress'
|
|
16
|
+
import { buildInstances } from './build/instances'
|
|
17
|
+
import { buildParse } from './build/parse'
|
|
18
|
+
import type { BuildCtx } from './build/util'
|
|
19
|
+
import type { BunFFI } from './types'
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Assemble the `BunFFI` surface from the raw dlopen'd symbols.
|
|
23
|
+
*
|
|
24
|
+
* @param sym The `symbols` object from `dlopen(path, {...})`.
|
|
25
|
+
* @param useBufferLength `true` when the engine's `buffer`/`buffer_length`
|
|
26
|
+
* ABI pair is live (see the probe in `ffi.ts`).
|
|
27
|
+
*/
|
|
28
|
+
export function build(
|
|
29
|
+
sym: Record<string, (...a: unknown[]) => unknown>,
|
|
30
|
+
useBufferLength: boolean,
|
|
31
|
+
): BunFFI {
|
|
32
|
+
// Single-buffer input fns: with the probe-gated `buffer/buffer_length` ABI the
|
|
33
|
+
// engine reads ptr + byteLength off the SAME TypedArray at call time (an
|
|
34
|
+
// atomic snapshot — pass the view twice, per Bun's docs); with `(ptr,len)` we
|
|
35
|
+
// pass the length explicitly. The branch is on a bind-time constant, so the
|
|
36
|
+
// JIT folds it away at the call site.
|
|
37
|
+
const oneArg = (raw: (...a: unknown[]) => number | bigint, v: Uint8Array): number | bigint =>
|
|
38
|
+
useBufferLength ? raw(v, v) : raw(v, v.length)
|
|
39
|
+
// Phase 1.1: under `buffer`/`buffer_length` the engine reads ptr + byteLength
|
|
40
|
+
// off the SAME view, so every `(ptr,len)` pair passes the view itself for the
|
|
41
|
+
// length slot (atomic snapshot, one JS arg fewer); under `(ptr,usize)` it's
|
|
42
|
+
// the explicit length. The branch is a bind-time constant → JIT folds it.
|
|
43
|
+
const lenOrView = (v: Uint8Array): Uint8Array | number => (useBufferLength ? v : v.length)
|
|
44
|
+
|
|
45
|
+
// ── Reusable scratch for the STRING-returning encode wrappers ────────
|
|
46
|
+
// Each wrapper writes its result and decodes it into an immutable JS string
|
|
47
|
+
// (or primitive) SYNCHRONOUSLY before the next call reuses the buffer — the
|
|
48
|
+
// same safety rationale as `jsonSumOut` / `generateRequestId`. Per-Worker
|
|
49
|
+
// module state (single-threaded event loop); never shared across Workers.
|
|
50
|
+
// NOT used for byte-returning ops (hexDecode/urlDecode/base64Decode/aead/
|
|
51
|
+
// wsFrame/packed parsers): their returned `Uint8Array` aliases the buffer
|
|
52
|
+
// and escapes to the caller — those stay on `*Into` (caller-owned).
|
|
53
|
+
let encodeScratch = new Uint8Array(0)
|
|
54
|
+
const scratchFor = (size: number): Uint8Array => {
|
|
55
|
+
if (encodeScratch.byteLength < size) encodeScratch = new Uint8Array(size)
|
|
56
|
+
return encodeScratch
|
|
57
|
+
}
|
|
58
|
+
// Pooled 9-byte scratch for jsonSumIds (the packed `[u8 ok][i64 sum LE]`
|
|
59
|
+
// output). The wrapper returns the BigInt VALUE (no byte aliasing escapes),
|
|
60
|
+
// so a single reused buffer + cached DataView is safe — removes the per-call
|
|
61
|
+
// Uint8Array + DataView allocs (measured ~400ns of the FFI wrapper cost).
|
|
62
|
+
const jsonSumOut = new Uint8Array(9)
|
|
63
|
+
const jsonSumView = new DataView(jsonSumOut.buffer)
|
|
64
|
+
// Fixed-size packed-verdict scratch + cached DataViews (parseHttpDate 9 B,
|
|
65
|
+
// rate-limit check 13 B) — same pooled pattern as `jsonSumView`. Kept
|
|
66
|
+
// separate from the growable `encodeScratch` so the cached DataViews are
|
|
67
|
+
// never invalidated by a buffer replacement.
|
|
68
|
+
const dateScratch = new Uint8Array(9)
|
|
69
|
+
const dateScratchView = new DataView(dateScratch.buffer)
|
|
70
|
+
const rateScratch = new Uint8Array(13)
|
|
71
|
+
const rateScratchView = new DataView(rateScratch.buffer)
|
|
72
|
+
|
|
73
|
+
const ctx: BuildCtx = {
|
|
74
|
+
useBufferLength,
|
|
75
|
+
lenOrView,
|
|
76
|
+
oneArg,
|
|
77
|
+
scratchFor,
|
|
78
|
+
jsonSumOut,
|
|
79
|
+
jsonSumView,
|
|
80
|
+
dateScratch,
|
|
81
|
+
dateScratchView,
|
|
82
|
+
rateScratch,
|
|
83
|
+
rateScratchView,
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Merge the domain surfaces. Each builder's method bodies are verbatim from
|
|
87
|
+
// the original single return object; the cast asserts the merged shape.
|
|
88
|
+
return {
|
|
89
|
+
...buildCodecs(sym, ctx),
|
|
90
|
+
...buildCompress(sym, ctx),
|
|
91
|
+
...buildParse(sym, ctx),
|
|
92
|
+
...buildInstances(sym, ctx),
|
|
93
|
+
} as BunFFI
|
|
94
|
+
}
|