@smoothbricks/lmao 0.2.2 → 0.2.3
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/dist/allocator.wasm +0 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/lib/JsBufferStrategy.d.ts +4 -3
- package/dist/lib/JsBufferStrategy.d.ts.map +1 -1
- package/dist/lib/JsBufferStrategy.js +18 -11
- package/dist/lib/arrow/lease.d.ts +10 -0
- package/dist/lib/arrow/lease.d.ts.map +1 -0
- package/dist/lib/arrow/lease.js +33 -0
- package/dist/lib/arrow/utils.d.ts +3 -4
- package/dist/lib/arrow/utils.d.ts.map +1 -1
- package/dist/lib/arrow/utils.js +12 -13
- package/dist/lib/arrow/vocabularyDictionary.d.ts +21 -0
- package/dist/lib/arrow/vocabularyDictionary.d.ts.map +1 -0
- package/dist/lib/arrow/vocabularyDictionary.js +95 -0
- package/dist/lib/bufferStrategy.d.ts +3 -2
- package/dist/lib/bufferStrategy.d.ts.map +1 -1
- package/dist/lib/cloudflare/traceRows.d.ts.map +1 -1
- package/dist/lib/cloudflare/traceRows.js +3 -2
- package/dist/lib/codegen/evaluatorGenerator.d.ts.map +1 -1
- package/dist/lib/codegen/evaluatorGenerator.js +12 -11
- package/dist/lib/codegen/fixedPositionWriterGenerator.d.ts +44 -82
- package/dist/lib/codegen/fixedPositionWriterGenerator.d.ts.map +1 -1
- package/dist/lib/codegen/fixedPositionWriterGenerator.js +223 -162
- package/dist/lib/codegen/spanLoggerClosureMaterializer.d.ts +63 -0
- package/dist/lib/codegen/spanLoggerClosureMaterializer.d.ts.map +1 -0
- package/dist/lib/codegen/spanLoggerClosureMaterializer.js +447 -0
- package/dist/lib/codegen/spanLoggerGenerator.d.ts +36 -19
- package/dist/lib/codegen/spanLoggerGenerator.d.ts.map +1 -1
- package/dist/lib/codegen/spanLoggerGenerator.js +164 -158
- package/dist/lib/convertToArrow.d.ts +7 -2
- package/dist/lib/convertToArrow.d.ts.map +1 -1
- package/dist/lib/convertToArrow.js +499 -285
- package/dist/lib/defineOpContext.js +1 -1
- package/dist/lib/enumMetadata.d.ts +19 -0
- package/dist/lib/enumMetadata.d.ts.map +1 -0
- package/dist/lib/enumMetadata.js +86 -0
- package/dist/lib/flushScheduler.d.ts.map +1 -1
- package/dist/lib/flushScheduler.js +13 -4
- package/dist/lib/library.d.ts +16 -98
- package/dist/lib/library.d.ts.map +1 -1
- package/dist/lib/library.js +32 -525
- package/dist/lib/logBinding.d.ts +21 -27
- package/dist/lib/logBinding.d.ts.map +1 -1
- package/dist/lib/op.d.ts +30 -30
- package/dist/lib/op.d.ts.map +1 -1
- package/dist/lib/op.js +15 -22
- package/dist/lib/opContext/createOpGroup.d.ts +1 -1
- package/dist/lib/opContext/createOpGroup.d.ts.map +1 -1
- package/dist/lib/opContext/createOpGroup.js +22 -29
- package/dist/lib/opContext/defineOp.d.ts +4 -4
- package/dist/lib/opContext/defineOp.d.ts.map +1 -1
- package/dist/lib/opContext/defineOp.js +53 -10
- package/dist/lib/opContext/opGroupTypes.d.ts +2 -2
- package/dist/lib/opContext/opTypes.d.ts +1 -1
- package/dist/lib/opContext/opTypes.d.ts.map +1 -1
- package/dist/lib/opContext/spanContextTypes.d.ts +29 -14
- package/dist/lib/opContext/spanContextTypes.d.ts.map +1 -1
- package/dist/lib/opContext/types.d.ts +4 -4
- package/dist/lib/opContext/types.d.ts.map +1 -1
- package/dist/lib/physicalLayoutPlan.d.ts +89 -0
- package/dist/lib/physicalLayoutPlan.d.ts.map +1 -0
- package/dist/lib/physicalLayoutPlan.js +442 -0
- package/dist/lib/resolveMessage.d.ts +9 -0
- package/dist/lib/resolveMessage.d.ts.map +1 -0
- package/dist/lib/resolveMessage.js +63 -0
- package/dist/lib/result.d.ts +5 -7
- package/dist/lib/result.d.ts.map +1 -1
- package/dist/lib/result.js +19 -26
- package/dist/lib/runtimeHint.d.ts +35 -0
- package/dist/lib/runtimeHint.d.ts.map +1 -0
- package/dist/lib/runtimeHint.js +79 -0
- package/dist/lib/schema/types.d.ts +1 -1
- package/dist/lib/schema/types.d.ts.map +1 -1
- package/dist/lib/span-buffer/aot/v1.d.ts +2 -0
- package/dist/lib/span-buffer/aot/v1.d.ts.map +1 -0
- package/dist/lib/span-buffer/aot/v1.js +24 -0
- package/dist/lib/spanBuffer.d.ts +33 -4
- package/dist/lib/spanBuffer.d.ts.map +1 -1
- package/dist/lib/spanBuffer.js +583 -91
- package/dist/lib/spanBufferStats.d.ts +1 -1
- package/dist/lib/spanBufferStats.d.ts.map +1 -1
- package/dist/lib/spanContext.d.ts +27 -51
- package/dist/lib/spanContext.d.ts.map +1 -1
- package/dist/lib/spanContext.js +822 -344
- package/dist/lib/sqlite/sqlite-common.d.ts.map +1 -1
- package/dist/lib/sqlite/sqlite-common.js +20 -21
- package/dist/lib/testing/bun-harness.d.ts +8 -3
- package/dist/lib/testing/bun-harness.d.ts.map +1 -1
- package/dist/lib/testing/bun-harness.js +30 -18
- package/dist/lib/testing/extractFacts.d.ts +1 -1
- package/dist/lib/testing/extractFacts.d.ts.map +1 -1
- package/dist/lib/testing/extractFacts.js +55 -63
- package/dist/lib/testing/facts.d.ts +1 -1
- package/dist/lib/testing/facts.d.ts.map +1 -1
- package/dist/lib/testing/queryable-span.d.ts +1 -1
- package/dist/lib/testing/queryable-span.d.ts.map +1 -1
- package/dist/lib/testing/queryable-span.js +26 -28
- package/dist/lib/testing/span-query.d.ts.map +1 -1
- package/dist/lib/testing/span-query.js +19 -22
- package/dist/lib/testing/stdio-replay.d.ts.map +1 -1
- package/dist/lib/testing/stdio-replay.js +19 -8
- package/dist/lib/threadId.d.ts.map +1 -1
- package/dist/lib/threadId.js +6 -3
- package/dist/lib/traceRoot.d.ts +30 -8
- package/dist/lib/traceRoot.d.ts.map +1 -1
- package/dist/lib/traceRoot.es.d.ts +17 -15
- package/dist/lib/traceRoot.es.d.ts.map +1 -1
- package/dist/lib/traceRoot.es.js +68 -34
- package/dist/lib/traceRoot.js +11 -0
- package/dist/lib/traceRoot.node.d.ts +17 -19
- package/dist/lib/traceRoot.node.d.ts.map +1 -1
- package/dist/lib/traceRoot.node.js +66 -38
- package/dist/lib/traceTopology.d.ts +42 -0
- package/dist/lib/traceTopology.d.ts.map +1 -0
- package/dist/lib/traceTopology.js +260 -0
- package/dist/lib/tracer.d.ts +9 -5
- package/dist/lib/tracer.d.ts.map +1 -1
- package/dist/lib/tracer.js +65 -71
- package/dist/lib/tracers/ArrayQueueTracer.d.ts +1 -1
- package/dist/lib/tracers/ArrayQueueTracer.js +1 -1
- package/dist/lib/tracers/StdioTracer.d.ts.map +1 -1
- package/dist/lib/tracers/StdioTracer.js +15 -13
- package/dist/lib/tracers/TestTracer.d.ts +4 -6
- package/dist/lib/tracers/TestTracer.d.ts.map +1 -1
- package/dist/lib/tracers/TestTracer.js +6 -8
- package/dist/lib/types.d.ts +49 -32
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/vocabularyRegistry.d.ts +25 -0
- package/dist/lib/vocabularyRegistry.d.ts.map +1 -0
- package/dist/lib/vocabularyRegistry.js +372 -0
- package/dist/lib/wasm/WasmBufferStrategy.d.ts +6 -10
- package/dist/lib/wasm/WasmBufferStrategy.d.ts.map +1 -1
- package/dist/lib/wasm/WasmBufferStrategy.js +44 -37
- package/dist/lib/wasm/wasmAllocator.d.ts +27 -22
- package/dist/lib/wasm/wasmAllocator.d.ts.map +1 -1
- package/dist/lib/wasm/wasmAllocator.js +66 -44
- package/dist/lib/wasm/wasmPhysicalLayout.d.ts +67 -0
- package/dist/lib/wasm/wasmPhysicalLayout.d.ts.map +1 -0
- package/dist/lib/wasm/wasmPhysicalLayout.js +179 -0
- package/dist/lib/wasm/wasmSpanBuffer.d.ts +79 -31
- package/dist/lib/wasm/wasmSpanBuffer.d.ts.map +1 -1
- package/dist/lib/wasm/wasmSpanBuffer.js +442 -272
- package/dist/lib/wasm/wasmTraceRoot.d.ts +24 -22
- package/dist/lib/wasm/wasmTraceRoot.d.ts.map +1 -1
- package/dist/lib/wasm/wasmTraceRoot.js +110 -71
- package/dist/vocabulary/register/v1.d.ts +2 -0
- package/dist/vocabulary/register/v1.d.ts.map +1 -0
- package/dist/vocabulary/register/v1.js +1 -0
- package/dist/wasm.d.ts +5 -0
- package/dist/wasm.d.ts.map +1 -0
- package/dist/wasm.js +4 -0
- package/package.json +54 -6
- package/src/index.ts +1 -0
- package/src/lib/JsBufferStrategy.ts +27 -9
- package/src/lib/__tests__/arrow-builder-integration/arrow-conversion.test.ts +335 -37
- package/src/lib/__tests__/arrow-builder-integration/binary-arrow-conversion.test.ts +97 -26
- package/src/lib/__tests__/arrow-builder-integration/binary-comparison.test.ts +75 -15
- package/src/lib/__tests__/arrow-builder-integration/binary-format-compliance.test.ts +30 -6
- package/src/lib/__tests__/arrow-builder-integration/buffer-chaining.test.ts +18 -21
- package/src/lib/__tests__/arrow-builder-integration/foundation.test.ts +5 -2
- package/src/lib/__tests__/arrow-builder-integration/integration.test.ts +25 -7
- package/src/lib/__tests__/arrow-builder-integration/lazy-columns.test.ts +3 -2
- package/src/lib/__tests__/buffer-overflow.test.ts +24 -18
- package/src/lib/__tests__/capability-span-context.test.ts +505 -0
- package/src/lib/__tests__/capacity-tuning.test.ts +5 -3
- package/src/lib/__tests__/eager-columns.test.ts +345 -0
- package/src/lib/__tests__/enum-metadata-aot.test.ts +153 -0
- package/src/lib/__tests__/enum-metadata.test.ts +177 -0
- package/src/lib/__tests__/fixtures/empty-vocabulary-runtime.fixture.ts +15 -0
- package/src/lib/__tests__/flushScheduler.test.ts +5 -1
- package/src/lib/__tests__/identity-view.property.test.ts +179 -0
- package/src/lib/__tests__/library.test.ts +19 -235
- package/src/lib/__tests__/message-buffer-families.test.ts +878 -0
- package/src/lib/__tests__/nested-library-tasks.test.ts +14 -15
- package/src/lib/__tests__/op-metadata.test.ts +1 -1
- package/src/lib/__tests__/op-type-safety.test.ts +5 -16
- package/src/lib/__tests__/physical-layout-plan.test.ts +333 -0
- package/src/lib/__tests__/remap-descriptor-integration.test.ts +381 -0
- package/src/lib/__tests__/root-context-construction.test.ts +414 -0
- package/src/lib/__tests__/span-auto-runtime.test.ts +386 -0
- package/src/lib/__tests__/span-buffer-segment-stats.test.ts +221 -0
- package/src/lib/__tests__/span-lifecycle.test.ts +53 -25
- package/src/lib/__tests__/spanbuffer-materializer-parity.test.ts +266 -0
- package/src/lib/__tests__/sync-async-trace.test.ts +24 -23
- package/src/lib/__tests__/tag-writer-aot.test.ts +214 -0
- package/src/lib/__tests__/test-helpers.ts +67 -12
- package/src/lib/__tests__/threadId.test.ts +62 -0
- package/src/lib/__tests__/timestamp.test.ts +221 -93
- package/src/lib/__tests__/traceTopology.property.test.ts +383 -0
- package/src/lib/__tests__/type-narrowing.test.ts +63 -0
- package/src/lib/__tests__/vocabulary-dense-decoding.test.ts +405 -0
- package/src/lib/__tests__/vocabularyRegistry.test.ts +313 -0
- package/src/lib/arrow/lease.ts +43 -0
- package/src/lib/arrow/utils.ts +10 -14
- package/src/lib/arrow/vocabularyDictionary.ts +123 -0
- package/src/lib/bufferStrategy.ts +9 -1
- package/src/lib/cloudflare/traceRows.ts +3 -2
- package/src/lib/codegen/__tests__/evaluatorGenerator.test.ts +21 -141
- package/src/lib/codegen/__tests__/fixedPositionWriter-parity.test.ts +273 -0
- package/src/lib/codegen/__tests__/fixedPositionWriter-uint64.test.ts +61 -34
- package/src/lib/codegen/__tests__/nullBitmap.test.ts +33 -37
- package/src/lib/codegen/__tests__/spanLoggerGenerator.test.ts +34 -18
- package/src/lib/codegen/__tests__/spanLoggerMaterializerParity.test.ts +503 -0
- package/src/lib/codegen/evaluatorGenerator.ts +18 -13
- package/src/lib/codegen/fixedPositionWriterGenerator.ts +329 -245
- package/src/lib/codegen/spanLoggerClosureMaterializer.ts +598 -0
- package/src/lib/codegen/spanLoggerGenerator.ts +241 -177
- package/src/lib/convertToArrow.ts +598 -311
- package/src/lib/defineOpContext.ts +1 -1
- package/src/lib/enumMetadata.ts +121 -0
- package/src/lib/flushScheduler.ts +11 -5
- package/src/lib/library.ts +37 -595
- package/src/lib/logBinding.ts +21 -27
- package/src/lib/op.ts +75 -18
- package/src/lib/opContext/__tests__/retry.test.ts +27 -21
- package/src/lib/opContext/createOpGroup.ts +33 -31
- package/src/lib/opContext/defineOp.ts +88 -11
- package/src/lib/opContext/opGroupTypes.ts +2 -2
- package/src/lib/opContext/opTypes.ts +1 -1
- package/src/lib/opContext/spanContextTypes.ts +98 -17
- package/src/lib/opContext/types.ts +7 -3
- package/src/lib/physicalLayoutPlan.ts +598 -0
- package/src/lib/resolveMessage.ts +67 -0
- package/src/lib/result.ts +20 -33
- package/src/lib/runtimeHint.ts +98 -0
- package/src/lib/schema/__tests__/featureFlags.test.ts +2 -1
- package/src/lib/schema/builder.ts +1 -1
- package/src/lib/schema/types.ts +1 -1
- package/src/lib/span-buffer/aot/v1.ts +26 -0
- package/src/lib/spanBuffer.ts +658 -92
- package/src/lib/spanBufferStats.ts +1 -1
- package/src/lib/spanContext.ts +1350 -861
- package/src/lib/sqlite/sqlite-common.ts +20 -31
- package/src/lib/testing/__tests__/topology-traversal.test.ts +174 -0
- package/src/lib/testing/__tests__/vitest-harness.test.ts +2 -1
- package/src/lib/testing/bun-harness.ts +94 -43
- package/src/lib/testing/extractFacts.ts +64 -78
- package/src/lib/testing/facts.ts +1 -1
- package/src/lib/testing/queryable-span.ts +23 -30
- package/src/lib/testing/span-query.ts +16 -20
- package/src/lib/testing/stdio-replay.ts +25 -8
- package/src/lib/testing/vitest-harness.ts +1 -1
- package/src/lib/threadId.ts +6 -3
- package/src/lib/traceRoot.es.ts +77 -42
- package/src/lib/traceRoot.node.ts +75 -46
- package/src/lib/traceRoot.ts +41 -14
- package/src/lib/traceTopology.ts +279 -0
- package/src/lib/tracer.ts +109 -98
- package/src/lib/tracers/ArrayQueueTracer.ts +1 -1
- package/src/lib/tracers/StdioTracer.ts +15 -13
- package/src/lib/tracers/TestTracer.ts +6 -8
- package/src/lib/tracers/__tests__/ArrayQueueTracer.test.ts +15 -10
- package/src/lib/tracers/__tests__/TestTracer.test.ts +23 -13
- package/src/lib/types.ts +64 -33
- package/src/lib/vocabularyRegistry.ts +439 -0
- package/src/lib/wasm/WasmBufferStrategy.ts +56 -48
- package/src/lib/wasm/__tests__/WasmBufferStrategy.test.ts +215 -11
- package/src/lib/wasm/__tests__/allocatorFreeBlockClamp.test.ts +86 -0
- package/src/lib/wasm/__tests__/wasm-identity-view.test.ts +311 -0
- package/src/lib/wasm/__tests__/wasm-integration.test.ts +417 -44
- package/src/lib/wasm/__tests__/wasm-message-buffer-families.test.ts +588 -0
- package/src/lib/wasm/__tests__/wasmAllocator.test.ts +100 -668
- package/src/lib/wasm/__tests__/wasmSpanBuffer.test.ts +419 -63
- package/src/lib/wasm/__tests__/wasmTraceRoot.test.ts +24 -29
- package/src/lib/wasm/__tests__/wasmTracer.test.ts.disabled +2 -2
- package/src/lib/wasm/wasmAllocator.ts +131 -96
- package/src/lib/wasm/wasmPhysicalLayout.ts +309 -0
- package/src/lib/wasm/wasmSpanBuffer.ts +597 -341
- package/src/lib/wasm/wasmTraceRoot.ts +140 -78
- package/src/vocabulary/register/v1.ts +1 -0
- package/src/wasm.ts +19 -0
- package/src/lib/__tests__/remapped-buffer-view-integration.test.ts +0 -319
- package/src/lib/__tests__/remapped-buffer-view.test.ts +0 -635
- package/src/lib/wasm/allocator.zig +0 -948
|
@@ -1,50 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Fixed-position TagWriter and ResultWriter classes.
|
|
3
|
+
*
|
|
4
|
+
* TagWriter uses source-authored constructors and schema-driven prototype methods so
|
|
5
|
+
* Hermes can compile the implementation ahead of time. ResultWriter selects between a
|
|
6
|
+
* compiled renderer (new Function, string-codegen runtimes) and a closure-composed
|
|
7
|
+
* materializer (workerd-safe, no eval) via activeMaterializerMode().
|
|
3
8
|
*
|
|
4
9
|
* These classes provide fluent setter methods that write to a fixed position in a SpanBuffer:
|
|
5
10
|
* - TagWriter: writes to position 0 (span-start row) via ctx.tag.userId("123")
|
|
6
11
|
* - ResultWriter: writes to position 1 (result row) via ctx.ok(data).userId("123")
|
|
7
12
|
*
|
|
8
|
-
* Both share the same codegen since they only differ in:
|
|
9
|
-
* 1. The fixed position (0 vs 1)
|
|
10
|
-
* 2. ResultWriter has additional _result/_error properties
|
|
11
|
-
*
|
|
12
13
|
* WHY Fixed Positions:
|
|
13
14
|
* - Row 0: span-start entry (written at span creation, attributes set via ctx.tag)
|
|
14
15
|
* - Row 1: span-end entry (written at ctx.ok()/ctx.err(), attributes set via fluent API)
|
|
15
16
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* - Fluent chaining: ctx.tag.userId("123").requestId("abc")
|
|
19
|
-
* - Zero allocation: returns same object reference
|
|
17
|
+
* Each wrapper stores only the SpanContext state identity. Setters write through
|
|
18
|
+
* `state._spanBuffer` to their embedded row and return the same wrapper for fluent chaining.
|
|
20
19
|
*/
|
|
21
20
|
|
|
22
|
-
import { bufferHelpers, type ColumnEntry } from '@smoothbricks/arrow-builder';
|
|
23
|
-
import {
|
|
21
|
+
import { activeMaterializerMode, bufferHelpers, type ColumnEntry } from '@smoothbricks/arrow-builder';
|
|
22
|
+
import { resolveEnumLookupDescriptor, type SchemaEnumLookupDescriptor } from '../enumMetadata.js';
|
|
23
|
+
import type { MessageLayoutFamily, MessagePhysicalLayout } from '../runtimeHint.js';
|
|
24
24
|
import type { InferSchema, LogSchema } from '../schema/types.js';
|
|
25
|
+
import type { TimestampAppendPrimitive } from '../traceRoot.js';
|
|
25
26
|
import type { AnySpanBuffer } from '../types.js';
|
|
26
27
|
|
|
27
|
-
/**
|
|
28
|
-
* Extension options for injecting custom code into generated writer classes.
|
|
29
|
-
*/
|
|
28
|
+
/** Extension methods injected into a generated fixed-position writer class. */
|
|
30
29
|
export interface FixedPositionWriterExtension {
|
|
31
|
-
/**
|
|
32
|
-
* Additional code to add to the constructor (after buffer assignment).
|
|
33
|
-
* Has access to `this` and constructorParams.
|
|
34
|
-
*/
|
|
35
|
-
constructorCode?: string;
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Additional methods to add to the class body.
|
|
39
|
-
*/
|
|
40
30
|
methods?: string;
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Constructor parameters beyond buffer.
|
|
44
|
-
* Added AFTER buffer in the constructor signature.
|
|
45
|
-
* @example "result, isError"
|
|
46
|
-
*/
|
|
47
|
-
constructorParams?: string;
|
|
48
31
|
}
|
|
49
32
|
|
|
50
33
|
/**
|
|
@@ -66,105 +49,55 @@ export type TagWriter<T extends LogSchema> = {
|
|
|
66
49
|
[K in keyof InferSchema<T>]: (value: InferSchema<T>[K]) => TagWriter<T>;
|
|
67
50
|
};
|
|
68
51
|
|
|
69
|
-
/**
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
*/
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Whether this is an error result
|
|
87
|
-
*/
|
|
88
|
-
readonly _isError: boolean;
|
|
52
|
+
/** SpanContext-owned hot writer state shared by logger, tag, and result writers. */
|
|
53
|
+
export interface WriterState {
|
|
54
|
+
/** Immutable span root used by fixed row 0/1 writers. */
|
|
55
|
+
readonly _spanBuffer: AnySpanBuffer;
|
|
56
|
+
/** Mutable active buffer used by append writers and updated on overflow. */
|
|
57
|
+
_buffer: AnySpanBuffer;
|
|
58
|
+
/** Plan-bound timestamp append operand retained by the SpanContext. */
|
|
59
|
+
readonly _appendLogEntry: TimestampAppendPrimitive;
|
|
60
|
+
readonly _physicalLayoutPlan: {
|
|
61
|
+
readonly ResultWriterClass: ResultWriterConstructor;
|
|
62
|
+
readonly enumLookup: SchemaEnumLookupDescriptor;
|
|
63
|
+
};
|
|
64
|
+
/** Append one dynamic row, centralizing overflow and active-buffer updates. */
|
|
65
|
+
_appendWriterEntry(entryType: number): number;
|
|
66
|
+
}
|
|
89
67
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
68
|
+
/** Result-row writer with schema-specific fluent setters. */
|
|
69
|
+
export type ResultWriter<T extends LogSchema, R = unknown, E = unknown> = {
|
|
70
|
+
/** Phantom parameters preserve the public generic contract without duplicating result values. */
|
|
71
|
+
readonly _resultType?: R;
|
|
72
|
+
readonly _errorType?: E;
|
|
93
73
|
with(attributes: Partial<InferSchema<T>>): ResultWriter<T, R, E>;
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Set the result-row message (row 1).
|
|
97
|
-
*/
|
|
98
74
|
message(text: string): ResultWriter<T, R, E>;
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Set the result-row source line (row 1).
|
|
102
|
-
*/
|
|
103
75
|
line(lineNumber: number): ResultWriter<T, R, E>;
|
|
104
|
-
/**
|
|
105
|
-
* Set the reserved `uint64_value` column for this result row.
|
|
106
|
-
*/
|
|
107
76
|
uint64_value(value: bigint): ResultWriter<T, R, E>;
|
|
108
77
|
} & {
|
|
109
|
-
/**
|
|
110
|
-
* Individual attribute setters - each returns `this` for chaining.
|
|
111
|
-
*/
|
|
112
78
|
[K in keyof InferSchema<T>]: (value: InferSchema<T>[K]) => ResultWriter<T, R, E>;
|
|
113
79
|
};
|
|
114
80
|
|
|
115
|
-
type TagWriterConstructor<T extends LogSchema> = new (
|
|
81
|
+
export type TagWriterConstructor<T extends LogSchema> = new (state: WriterState) => TagWriter<T>;
|
|
116
82
|
|
|
117
|
-
type ResultWriterConstructor<T extends LogSchema
|
|
118
|
-
|
|
119
|
-
resultOrError: unknown,
|
|
120
|
-
isError: boolean,
|
|
83
|
+
export type ResultWriterConstructor = new <T extends LogSchema = LogSchema, R = unknown, E = unknown>(
|
|
84
|
+
state: WriterState,
|
|
121
85
|
) => ResultWriter<T, R, E>;
|
|
122
86
|
|
|
123
87
|
function isTagWriterConstructor<T extends LogSchema>(value: unknown): value is TagWriterConstructor<T> {
|
|
124
88
|
return typeof value === 'function';
|
|
125
89
|
}
|
|
126
90
|
|
|
127
|
-
function isResultWriterConstructor
|
|
91
|
+
function isResultWriterConstructor(value: unknown): value is ResultWriterConstructor {
|
|
128
92
|
return typeof value === 'function';
|
|
129
93
|
}
|
|
130
94
|
|
|
131
|
-
/**
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
*/
|
|
135
|
-
function generateEnumMapping(fieldName: string, enumValues: readonly string[]): string {
|
|
136
|
-
const cases = enumValues.map((value, index) => ` case ${JSON.stringify(value)}: return ${index};`).join('\n');
|
|
137
|
-
|
|
138
|
-
return `
|
|
139
|
-
function getEnumIndex_${fieldName}(value) {
|
|
140
|
-
switch(value) {
|
|
141
|
-
${cases}
|
|
142
|
-
default: return 0;
|
|
143
|
-
}
|
|
144
|
-
}`;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Generate setter method code for a single attribute.
|
|
149
|
-
* Calls this._buffer.columnName(this._pos, value) and returns this.
|
|
150
|
-
*/
|
|
151
|
-
function generateSetterMethod(fieldName: string, schema: unknown, hasEnumMapping: boolean): string {
|
|
152
|
-
const columnName = fieldName;
|
|
153
|
-
const lmaoType = getSchemaType(schema);
|
|
154
|
-
|
|
155
|
-
if (lmaoType === 'enum' && hasEnumMapping) {
|
|
156
|
-
return `
|
|
157
|
-
${fieldName}(value) {
|
|
158
|
-
this._buffer.${columnName}(this._pos, getEnumIndex_${fieldName}(value));
|
|
159
|
-
return this;
|
|
160
|
-
}`;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
// All other types: direct pass-through to buffer setter
|
|
164
|
-
// The buffer's setter handles null bitmap and storage details
|
|
95
|
+
/** Generate a state-bound setter for one schema attribute and literal row. */
|
|
96
|
+
function generateSetterMethod(fieldName: string, enumEncoderName: string | undefined, position: number): string {
|
|
97
|
+
const value = enumEncoderName ? `${enumEncoderName}(value)` : 'value';
|
|
165
98
|
return `
|
|
166
99
|
${fieldName}(value) {
|
|
167
|
-
this.
|
|
100
|
+
this._state._spanBuffer.${fieldName}(${position}, ${value});
|
|
168
101
|
return this;
|
|
169
102
|
}`;
|
|
170
103
|
}
|
|
@@ -173,14 +106,18 @@ function generateSetterMethod(fieldName: string, schema: unknown, hasEnumMapping
|
|
|
173
106
|
* Generate with() method code - bulk attribute setting.
|
|
174
107
|
* UNROLLED per-column code for zero Object.entries overhead.
|
|
175
108
|
*/
|
|
176
|
-
function generateWithMethod(
|
|
109
|
+
function generateWithMethod(
|
|
110
|
+
schemaFields: readonly ColumnEntry[],
|
|
111
|
+
enumEncoderNames: Readonly<Record<string, string>>,
|
|
112
|
+
position: number,
|
|
113
|
+
): string {
|
|
177
114
|
const columnWrites = schemaFields.map(([fieldName]) => {
|
|
178
|
-
const
|
|
179
|
-
const valueExpr =
|
|
115
|
+
const enumEncoderName = enumEncoderNames[fieldName];
|
|
116
|
+
const valueExpr = enumEncoderName ? `${enumEncoderName}(attributes.${fieldName})` : `attributes.${fieldName}`;
|
|
180
117
|
|
|
181
118
|
return `
|
|
182
119
|
if ('${fieldName}' in attributes && attributes.${fieldName} !== null && attributes.${fieldName} !== undefined) {
|
|
183
|
-
this.
|
|
120
|
+
this._state._spanBuffer.${fieldName}(${position}, ${valueExpr});
|
|
184
121
|
}`;
|
|
185
122
|
});
|
|
186
123
|
|
|
@@ -206,47 +143,26 @@ export function generateFixedPositionWriterClass(
|
|
|
206
143
|
position: number,
|
|
207
144
|
className: string,
|
|
208
145
|
extension?: FixedPositionWriterExtension,
|
|
146
|
+
eagerColumns: readonly string[] = [],
|
|
147
|
+
enumLookup: SchemaEnumLookupDescriptor = resolveEnumLookupDescriptor(schema),
|
|
209
148
|
): string {
|
|
210
149
|
const schemaFields = schema._columns;
|
|
150
|
+
void eagerColumns;
|
|
151
|
+
const enumEncoderNames: Record<string, string> = Object.create(null);
|
|
152
|
+
const enumEncoderBindings = enumLookup.ordered.map(({ fieldName }, index) => {
|
|
153
|
+
const encoderName = `encodeEnum${index}`;
|
|
154
|
+
enumEncoderNames[fieldName] = encoderName;
|
|
155
|
+
return ` const ${encoderName} = enumLookup.byField[${JSON.stringify(fieldName)}].encode;`;
|
|
156
|
+
});
|
|
211
157
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
const enumFieldNames = new Set<string>();
|
|
215
|
-
|
|
216
|
-
for (const [fieldName, fieldSchema] of schemaFields) {
|
|
217
|
-
const lmaoType = getSchemaType(fieldSchema);
|
|
218
|
-
const enumValues = getEnumValues(fieldSchema);
|
|
219
|
-
|
|
220
|
-
if (lmaoType === 'enum' && enumValues) {
|
|
221
|
-
enumMappings.push(generateEnumMapping(fieldName, enumValues));
|
|
222
|
-
enumFieldNames.add(fieldName);
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
// Generate setter methods
|
|
227
|
-
const setterMethods = schemaFields.map(([fieldName, fieldSchema]) =>
|
|
228
|
-
generateSetterMethod(fieldName, fieldSchema, enumFieldNames.has(fieldName)),
|
|
158
|
+
const setterMethods = schemaFields.map(([fieldName]) =>
|
|
159
|
+
generateSetterMethod(fieldName, enumEncoderNames[fieldName], position),
|
|
229
160
|
);
|
|
230
161
|
|
|
231
|
-
|
|
232
|
-
const withMethod = generateWithMethod(schemaFields, enumFieldNames);
|
|
233
|
-
|
|
234
|
-
// Build constructor signature
|
|
235
|
-
const constructorSignature = extension?.constructorParams ? `buffer, ${extension.constructorParams}` : 'buffer';
|
|
162
|
+
const withMethod = generateWithMethod(schemaFields, enumEncoderNames, position);
|
|
236
163
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
const constructorBody = [' this._buffer = buffer;', ` this._pos = ${position};`];
|
|
240
|
-
|
|
241
|
-
if (extension?.constructorCode) {
|
|
242
|
-
constructorBody.push('');
|
|
243
|
-
// Extension constructor code runs after _buffer/_pos assignment
|
|
244
|
-
const extensionLines = extension.constructorCode
|
|
245
|
-
.trim()
|
|
246
|
-
.split('\n')
|
|
247
|
-
.map((line) => ` ${line.trim()}`);
|
|
248
|
-
constructorBody.push(...extensionLines);
|
|
249
|
-
}
|
|
164
|
+
const constructorSignature = 'state';
|
|
165
|
+
const constructorBody = [' this._state = state;'];
|
|
250
166
|
|
|
251
167
|
// Build extension methods (additional methods injected by the caller)
|
|
252
168
|
const extensionMethods = extension?.methods
|
|
@@ -258,15 +174,10 @@ export function generateFixedPositionWriterClass(
|
|
|
258
174
|
.join('\n')
|
|
259
175
|
: '';
|
|
260
176
|
|
|
261
|
-
// Generated class
|
|
262
|
-
// - constructor: assigns _buffer, _pos, then extension code
|
|
263
|
-
// - with(): bulk attribute setting method
|
|
264
|
-
// - Individual setter methods for each schema field
|
|
265
|
-
// - Extension methods (if any)
|
|
177
|
+
// Generated class stores only `_state`; every method embeds its fixed row literal.
|
|
266
178
|
const classCode = `
|
|
267
179
|
'use strict';
|
|
268
|
-
|
|
269
|
-
${enumMappings.join('\n')}
|
|
180
|
+
${enumEncoderBindings.join('\n')}
|
|
270
181
|
|
|
271
182
|
class ${className} {
|
|
272
183
|
constructor(${constructorSignature}) {
|
|
@@ -293,35 +204,129 @@ ${extensionMethods}
|
|
|
293
204
|
* Cache for TagWriter classes (position 0).
|
|
294
205
|
* WeakMap allows garbage collection when schema is no longer referenced.
|
|
295
206
|
*/
|
|
296
|
-
const tagWriterClassCache = new WeakMap<LogSchema, unknown
|
|
207
|
+
const tagWriterClassCache = new WeakMap<LogSchema, Map<string, unknown>>();
|
|
297
208
|
|
|
298
209
|
/**
|
|
299
210
|
* Cache for ResultWriter classes (position 1).
|
|
300
211
|
*/
|
|
301
|
-
const resultWriterClassCache = new WeakMap<LogSchema, unknown
|
|
212
|
+
const resultWriterClassCache = new WeakMap<LogSchema, Map<string, unknown>>();
|
|
302
213
|
|
|
303
214
|
// ============================================================================
|
|
304
|
-
//
|
|
215
|
+
// Closure-composed materializer internals (no eval; shared by tag/result rows)
|
|
305
216
|
// ============================================================================
|
|
306
217
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
*/
|
|
310
|
-
const tagWriterExtension: FixedPositionWriterExtension = {
|
|
311
|
-
methods: `
|
|
312
|
-
uint64_value(value) {
|
|
313
|
-
this._buffer.uint64_value(this._pos, value);
|
|
314
|
-
return this;
|
|
218
|
+
interface RuntimeFixedWriter {
|
|
219
|
+
readonly _state: WriterState;
|
|
315
220
|
}
|
|
316
|
-
`,
|
|
317
|
-
};
|
|
318
221
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
222
|
+
interface FixedFieldPlan {
|
|
223
|
+
readonly fieldName: string;
|
|
224
|
+
readonly encode: ((value: unknown) => number) | undefined;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/** Invoke one schema-specific SpanBuffer setter without generating source. */
|
|
228
|
+
function writeFixedField(writer: RuntimeFixedWriter, fieldName: string, position: number, value: unknown): void {
|
|
229
|
+
const buffer = writer._state._spanBuffer;
|
|
230
|
+
const columnWriter: unknown = Reflect.get(buffer, fieldName);
|
|
231
|
+
if (typeof columnWriter !== 'function') {
|
|
232
|
+
throw new TypeError(`SpanBuffer column writer ${JSON.stringify(fieldName)} is not callable`);
|
|
233
|
+
}
|
|
234
|
+
columnWriter.call(buffer, position, value);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/** Preserve the generated writer's schema order and enum-binding semantics. */
|
|
238
|
+
function createFixedFieldPlans(schema: LogSchema, enumLookup: SchemaEnumLookupDescriptor): readonly FixedFieldPlan[] {
|
|
239
|
+
const enumFieldNames = new Set<string>();
|
|
240
|
+
for (const { fieldName } of enumLookup.ordered) enumFieldNames.add(fieldName);
|
|
241
|
+
|
|
242
|
+
return schema._columns.map(([fieldName]) => {
|
|
243
|
+
if (!enumFieldNames.has(fieldName)) return { fieldName, encode: undefined };
|
|
244
|
+
|
|
245
|
+
const descriptor = enumLookup.byField[fieldName];
|
|
246
|
+
if (!descriptor) {
|
|
247
|
+
throw new TypeError(`Enum lookup for ${JSON.stringify(fieldName)} is missing`);
|
|
248
|
+
}
|
|
249
|
+
return { fieldName, encode: descriptor.encode };
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/** Compiled class members are non-enumerable; every closure-installed member must match. */
|
|
254
|
+
function asClassMemberDescriptor(descriptor: PropertyDescriptor): PropertyDescriptor {
|
|
255
|
+
descriptor.enumerable = false;
|
|
256
|
+
return descriptor;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/** Create a class-method descriptor whose function name is the schema field name. */
|
|
260
|
+
function createFieldSetterDescriptor(plan: FixedFieldPlan, position: number): PropertyDescriptor {
|
|
261
|
+
const encode = plan.encode;
|
|
262
|
+
const methods = encode
|
|
263
|
+
? {
|
|
264
|
+
[plan.fieldName](this: RuntimeFixedWriter, value: string) {
|
|
265
|
+
writeFixedField(this, plan.fieldName, position, encode(value));
|
|
266
|
+
return this;
|
|
267
|
+
},
|
|
268
|
+
}
|
|
269
|
+
: {
|
|
270
|
+
[plan.fieldName](this: RuntimeFixedWriter, value: unknown) {
|
|
271
|
+
writeFixedField(this, plan.fieldName, position, value);
|
|
272
|
+
return this;
|
|
273
|
+
},
|
|
274
|
+
};
|
|
275
|
+
const descriptor = Object.getOwnPropertyDescriptor(methods, plan.fieldName);
|
|
276
|
+
if (!descriptor) throw new Error(`Failed to create writer setter ${JSON.stringify(plan.fieldName)}`);
|
|
277
|
+
return asClassMemberDescriptor(descriptor);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/** Install the schema-specific fluent API with class-member-equivalent descriptors. */
|
|
281
|
+
function installFixedWriterMethods(prototype: object, plans: readonly FixedFieldPlan[], position: number): void {
|
|
282
|
+
const bulkMethods = {
|
|
283
|
+
with(this: RuntimeFixedWriter, attributes: Readonly<Record<string, unknown>>) {
|
|
284
|
+
for (const plan of plans) {
|
|
285
|
+
if (
|
|
286
|
+
plan.fieldName in attributes &&
|
|
287
|
+
attributes[plan.fieldName] !== null &&
|
|
288
|
+
attributes[plan.fieldName] !== undefined
|
|
289
|
+
) {
|
|
290
|
+
const value = attributes[plan.fieldName];
|
|
291
|
+
writeFixedField(this, plan.fieldName, position, plan.encode ? plan.encode(value) : value);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
return this;
|
|
295
|
+
},
|
|
296
|
+
uint64_value(this: RuntimeFixedWriter, value: bigint) {
|
|
297
|
+
this._state._spanBuffer.uint64_value(position, value);
|
|
298
|
+
return this;
|
|
299
|
+
},
|
|
300
|
+
};
|
|
301
|
+
const withDescriptor = Object.getOwnPropertyDescriptor(bulkMethods, 'with');
|
|
302
|
+
if (!withDescriptor) throw new Error('Failed to create writer.with');
|
|
303
|
+
Object.defineProperty(prototype, 'with', asClassMemberDescriptor(withDescriptor));
|
|
304
|
+
|
|
305
|
+
for (const plan of plans) {
|
|
306
|
+
Object.defineProperty(prototype, plan.fieldName, createFieldSetterDescriptor(plan, position));
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const uint64Descriptor = Object.getOwnPropertyDescriptor(bulkMethods, 'uint64_value');
|
|
310
|
+
if (!uint64Descriptor) throw new Error('Failed to create writer.uint64_value');
|
|
311
|
+
Object.defineProperty(prototype, 'uint64_value', asClassMemberDescriptor(uint64Descriptor));
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// ============================================================================
|
|
315
|
+
// TagWriter API
|
|
316
|
+
// ============================================================================
|
|
317
|
+
|
|
318
|
+
/** Build one source-authored constructor for an existing TagWriter cache key. */
|
|
319
|
+
function createStaticTagWriterConstructor(schema: LogSchema, enumLookup: SchemaEnumLookupDescriptor): unknown {
|
|
320
|
+
class GeneratedTagWriter {
|
|
321
|
+
readonly _state: WriterState;
|
|
322
|
+
|
|
323
|
+
constructor(state: WriterState) {
|
|
324
|
+
this._state = state;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
installFixedWriterMethods(GeneratedTagWriter.prototype, createFixedFieldPlans(schema, enumLookup), 0);
|
|
329
|
+
return GeneratedTagWriter;
|
|
325
330
|
}
|
|
326
331
|
|
|
327
332
|
/**
|
|
@@ -330,21 +335,25 @@ export function generateTagWriterClass(schema: LogSchema): string {
|
|
|
330
335
|
* @param schema - Tag attribute schema
|
|
331
336
|
* @returns TagWriter class constructor
|
|
332
337
|
*/
|
|
333
|
-
export function getTagWriterClass<T extends LogSchema>(
|
|
334
|
-
|
|
338
|
+
export function getTagWriterClass<T extends LogSchema>(
|
|
339
|
+
schema: T,
|
|
340
|
+
eagerColumns: readonly string[] = [],
|
|
341
|
+
enumLookup: SchemaEnumLookupDescriptor = resolveEnumLookupDescriptor(schema),
|
|
342
|
+
): TagWriterConstructor<T> {
|
|
343
|
+
const cacheKey = eagerColumns.join('\u0000');
|
|
344
|
+
let classes = tagWriterClassCache.get(schema);
|
|
345
|
+
let WriterClass = classes?.get(cacheKey);
|
|
335
346
|
|
|
336
347
|
if (!WriterClass) {
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
// Compile with new Function()
|
|
340
|
-
const factory = new Function('helpers', classCode);
|
|
341
|
-
WriterClass = factory(bufferHelpers);
|
|
348
|
+
WriterClass = createStaticTagWriterConstructor(schema, enumLookup);
|
|
342
349
|
|
|
343
350
|
if (!isTagWriterConstructor<LogSchema>(WriterClass)) {
|
|
344
|
-
throw new Error('Failed to
|
|
351
|
+
throw new Error('Failed to create TagWriter constructor');
|
|
345
352
|
}
|
|
346
353
|
|
|
347
|
-
|
|
354
|
+
classes ??= new Map();
|
|
355
|
+
classes.set(cacheKey, WriterClass);
|
|
356
|
+
tagWriterClassCache.set(schema, classes);
|
|
348
357
|
}
|
|
349
358
|
|
|
350
359
|
if (!isTagWriterConstructor<T>(WriterClass)) {
|
|
@@ -354,118 +363,193 @@ export function getTagWriterClass<T extends LogSchema>(schema: T): new (buffer:
|
|
|
354
363
|
return WriterClass;
|
|
355
364
|
}
|
|
356
365
|
|
|
357
|
-
/**
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
* @param schema - Tag attribute schema
|
|
361
|
-
* @param buffer - SpanBuffer to write to
|
|
362
|
-
* @returns TagWriter instance bound to position 0
|
|
363
|
-
*/
|
|
364
|
-
export function createTagWriter<T extends LogSchema>(schema: T, buffer: AnySpanBuffer): TagWriter<T> {
|
|
365
|
-
const WriterClass = getTagWriterClass(schema);
|
|
366
|
-
return new WriterClass(buffer);
|
|
366
|
+
/** Create a TagWriter bound to an existing SpanContext writer state. */
|
|
367
|
+
export function createTagWriter<T extends LogSchema>(schema: T, state: WriterState): TagWriter<T> {
|
|
368
|
+
return new (getTagWriterClass(schema))(state);
|
|
367
369
|
}
|
|
368
370
|
|
|
369
371
|
// ============================================================================
|
|
370
372
|
// ResultWriter API
|
|
371
373
|
// ============================================================================
|
|
372
374
|
|
|
373
|
-
/**
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
constructorCode: `
|
|
382
|
-
this._isError = isError;
|
|
383
|
-
if (isError) {
|
|
384
|
-
this._error = resultOrError;
|
|
385
|
-
this._result = undefined;
|
|
386
|
-
} else {
|
|
387
|
-
this._result = resultOrError;
|
|
388
|
-
this._error = undefined;
|
|
389
|
-
}
|
|
390
|
-
`,
|
|
391
|
-
methods: `
|
|
375
|
+
/** Result-row system setters, specialized once for the plan's message layout family. */
|
|
376
|
+
function createResultWriterExtension(messageLayoutFamily: MessageLayoutFamily): FixedPositionWriterExtension {
|
|
377
|
+
const messageWrite =
|
|
378
|
+
messageLayoutFamily === 'static-only'
|
|
379
|
+
? 'this._state._spanBuffer._terminalMessage = text;'
|
|
380
|
+
: 'this._state._spanBuffer.message_values[1] = text;';
|
|
381
|
+
return {
|
|
382
|
+
methods: `
|
|
392
383
|
message(text) {
|
|
393
|
-
|
|
384
|
+
${messageWrite}
|
|
394
385
|
return this;
|
|
395
386
|
}
|
|
396
387
|
|
|
397
388
|
line(lineNumber) {
|
|
398
|
-
this.
|
|
389
|
+
this._state._spanBuffer.line(1, lineNumber);
|
|
399
390
|
return this;
|
|
400
391
|
}
|
|
401
392
|
|
|
402
393
|
uint64_value(value) {
|
|
403
|
-
this.
|
|
394
|
+
this._state._spanBuffer.uint64_value(1, value);
|
|
404
395
|
return this;
|
|
405
396
|
}
|
|
406
397
|
`,
|
|
407
|
-
};
|
|
398
|
+
};
|
|
399
|
+
}
|
|
408
400
|
|
|
409
401
|
/**
|
|
410
402
|
* Generate ResultWriter class code for a schema.
|
|
411
403
|
* ResultWriter writes to position 1 (result row).
|
|
412
404
|
*/
|
|
413
|
-
export function generateResultWriterClass(
|
|
414
|
-
|
|
405
|
+
export function generateResultWriterClass(
|
|
406
|
+
schema: LogSchema,
|
|
407
|
+
messageLayoutFamily: MessageLayoutFamily = 'mixed',
|
|
408
|
+
_messagePhysicalLayout: MessagePhysicalLayout = 'current',
|
|
409
|
+
eagerColumns: readonly string[] = [],
|
|
410
|
+
enumLookup: SchemaEnumLookupDescriptor = resolveEnumLookupDescriptor(schema),
|
|
411
|
+
): string {
|
|
412
|
+
return generateFixedPositionWriterClass(
|
|
413
|
+
schema,
|
|
414
|
+
1,
|
|
415
|
+
'GeneratedResultWriter',
|
|
416
|
+
createResultWriterExtension(messageLayoutFamily),
|
|
417
|
+
eagerColumns,
|
|
418
|
+
enumLookup,
|
|
419
|
+
);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/** Result-row message lane accessor for mixed/dynamic layouts. */
|
|
423
|
+
function messageLaneOf(buffer: AnySpanBuffer): (string | undefined)[] {
|
|
424
|
+
const lane = buffer.message_values;
|
|
425
|
+
if (lane === undefined) {
|
|
426
|
+
throw new TypeError('SpanBuffer has no message_values lane for the result row');
|
|
427
|
+
}
|
|
428
|
+
return lane;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/** Install result-row system setters mirroring createResultWriterExtension without source text. */
|
|
432
|
+
function installResultSystemMethods(prototype: object, messageLayoutFamily: MessageLayoutFamily): void {
|
|
433
|
+
const methods =
|
|
434
|
+
messageLayoutFamily === 'static-only'
|
|
435
|
+
? {
|
|
436
|
+
message(this: RuntimeFixedWriter, text: string) {
|
|
437
|
+
this._state._spanBuffer._terminalMessage = text;
|
|
438
|
+
return this;
|
|
439
|
+
},
|
|
440
|
+
}
|
|
441
|
+
: {
|
|
442
|
+
message(this: RuntimeFixedWriter, text: string) {
|
|
443
|
+
messageLaneOf(this._state._spanBuffer)[1] = text;
|
|
444
|
+
return this;
|
|
445
|
+
},
|
|
446
|
+
};
|
|
447
|
+
const messageDescriptor = Object.getOwnPropertyDescriptor(methods, 'message');
|
|
448
|
+
if (!messageDescriptor) throw new Error('Failed to create ResultWriter.message');
|
|
449
|
+
Object.defineProperty(prototype, 'message', asClassMemberDescriptor(messageDescriptor));
|
|
450
|
+
|
|
451
|
+
const lineMethods = {
|
|
452
|
+
line(this: RuntimeFixedWriter, lineNumber: number) {
|
|
453
|
+
this._state._spanBuffer.line(1, lineNumber);
|
|
454
|
+
return this;
|
|
455
|
+
},
|
|
456
|
+
};
|
|
457
|
+
const lineDescriptor = Object.getOwnPropertyDescriptor(lineMethods, 'line');
|
|
458
|
+
if (!lineDescriptor) throw new Error('Failed to create ResultWriter.line');
|
|
459
|
+
Object.defineProperty(prototype, 'line', asClassMemberDescriptor(lineDescriptor));
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/** Assemble a ResultWriter class from closures (workerd-safe: no string codegen). */
|
|
463
|
+
function createClosureResultWriterConstructor(
|
|
464
|
+
schema: LogSchema,
|
|
465
|
+
messageLayoutFamily: MessageLayoutFamily,
|
|
466
|
+
enumLookup: SchemaEnumLookupDescriptor,
|
|
467
|
+
): unknown {
|
|
468
|
+
class GeneratedResultWriter {
|
|
469
|
+
readonly _state: WriterState;
|
|
470
|
+
|
|
471
|
+
constructor(state: WriterState) {
|
|
472
|
+
this._state = state;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
installFixedWriterMethods(GeneratedResultWriter.prototype, createFixedFieldPlans(schema, enumLookup), 1);
|
|
477
|
+
installResultSystemMethods(GeneratedResultWriter.prototype, messageLayoutFamily);
|
|
478
|
+
return GeneratedResultWriter;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/** Compile the rendered result-writer source with new Function (string-codegen runtimes only). */
|
|
482
|
+
function compileResultWriterClass(
|
|
483
|
+
schema: LogSchema,
|
|
484
|
+
messageLayoutFamily: MessageLayoutFamily,
|
|
485
|
+
messagePhysicalLayout: MessagePhysicalLayout,
|
|
486
|
+
eagerColumns: readonly string[],
|
|
487
|
+
enumLookup: SchemaEnumLookupDescriptor,
|
|
488
|
+
): unknown {
|
|
489
|
+
const classCode = generateResultWriterClass(
|
|
490
|
+
schema,
|
|
491
|
+
messageLayoutFamily,
|
|
492
|
+
messagePhysicalLayout,
|
|
493
|
+
eagerColumns,
|
|
494
|
+
enumLookup,
|
|
495
|
+
).trim();
|
|
496
|
+
|
|
497
|
+
const factory = new Function('helpers', 'enumLookup', classCode);
|
|
498
|
+
return factory(bufferHelpers, enumLookup);
|
|
415
499
|
}
|
|
416
500
|
|
|
417
501
|
/**
|
|
418
502
|
* Get or create a cached ResultWriter class for a schema.
|
|
419
503
|
*
|
|
504
|
+
* Selects the compiled or closure-composed materializer via activeMaterializerMode();
|
|
505
|
+
* cache keys are mode-prefixed so an override flip never returns the wrong kind.
|
|
506
|
+
*
|
|
420
507
|
* @param schema - Tag attribute schema
|
|
421
508
|
* @returns ResultWriter class constructor
|
|
422
509
|
*/
|
|
423
510
|
export function getResultWriterClass<T extends LogSchema>(
|
|
424
511
|
schema: T,
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
)
|
|
430
|
-
|
|
512
|
+
messageLayoutFamily: MessageLayoutFamily = 'mixed',
|
|
513
|
+
messagePhysicalLayout: MessagePhysicalLayout = 'current',
|
|
514
|
+
eagerColumns: readonly string[] = [],
|
|
515
|
+
enumLookup: SchemaEnumLookupDescriptor = resolveEnumLookupDescriptor(schema),
|
|
516
|
+
): ResultWriterConstructor {
|
|
517
|
+
const mode = activeMaterializerMode();
|
|
518
|
+
const cacheKey = `${mode}:${messageLayoutFamily}:${messagePhysicalLayout}:${eagerColumns.join('\u0000')}`;
|
|
519
|
+
let familyClasses = resultWriterClassCache.get(schema);
|
|
520
|
+
let WriterClass = familyClasses?.get(cacheKey);
|
|
431
521
|
|
|
432
522
|
if (!WriterClass) {
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
WriterClass = factory(bufferHelpers);
|
|
523
|
+
WriterClass =
|
|
524
|
+
mode === 'compiled'
|
|
525
|
+
? compileResultWriterClass(schema, messageLayoutFamily, messagePhysicalLayout, eagerColumns, enumLookup)
|
|
526
|
+
: createClosureResultWriterConstructor(schema, messageLayoutFamily, enumLookup);
|
|
438
527
|
|
|
439
|
-
if (!isResultWriterConstructor
|
|
528
|
+
if (!isResultWriterConstructor(WriterClass)) {
|
|
440
529
|
throw new Error('Failed to generate ResultWriter constructor');
|
|
441
530
|
}
|
|
442
531
|
|
|
443
|
-
|
|
532
|
+
familyClasses ??= new Map();
|
|
533
|
+
familyClasses.set(cacheKey, WriterClass);
|
|
534
|
+
resultWriterClassCache.set(schema, familyClasses);
|
|
444
535
|
}
|
|
445
536
|
|
|
446
|
-
if (!isResultWriterConstructor
|
|
537
|
+
if (!isResultWriterConstructor(WriterClass)) {
|
|
447
538
|
throw new Error('Invalid cached ResultWriter constructor');
|
|
448
539
|
}
|
|
449
540
|
|
|
450
541
|
return WriterClass;
|
|
451
542
|
}
|
|
452
543
|
|
|
453
|
-
/**
|
|
454
|
-
* Create a ResultWriter instance for a buffer.
|
|
455
|
-
*
|
|
456
|
-
* @param schema - Tag attribute schema
|
|
457
|
-
* @param buffer - SpanBuffer to write to
|
|
458
|
-
* @param resultOrError - The result value or error
|
|
459
|
-
* @param isError - Whether this is an error result
|
|
460
|
-
* @returns ResultWriter instance bound to position 1
|
|
461
|
-
*/
|
|
544
|
+
/** Create a ResultWriter bound to an existing SpanContext writer state. */
|
|
462
545
|
export function createResultWriter<T extends LogSchema, R = unknown, E = unknown>(
|
|
463
546
|
schema: T,
|
|
464
|
-
|
|
465
|
-
resultOrError: R | E,
|
|
466
|
-
isError: boolean,
|
|
547
|
+
state: WriterState,
|
|
467
548
|
): ResultWriter<T, R, E> {
|
|
468
|
-
|
|
469
|
-
|
|
549
|
+
return new (getResultWriterClass(
|
|
550
|
+
schema,
|
|
551
|
+
state._spanBuffer._messageLayoutFamily,
|
|
552
|
+
state._spanBuffer._messagePhysicalLayout,
|
|
553
|
+
))<T, R, E>(state);
|
|
470
554
|
}
|
|
471
555
|
//#endregion smoo/lmao!n/codegen-architecture
|