@smoothbricks/lmao 0.2.2 → 0.3.0

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.
Files changed (285) hide show
  1. package/README.md +206 -206
  2. package/dist/allocator.wasm +0 -0
  3. package/dist/index.d.ts +1 -0
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +1 -0
  6. package/dist/lib/JsBufferStrategy.d.ts +4 -3
  7. package/dist/lib/JsBufferStrategy.d.ts.map +1 -1
  8. package/dist/lib/JsBufferStrategy.js +18 -11
  9. package/dist/lib/arrow/lease.d.ts +10 -0
  10. package/dist/lib/arrow/lease.d.ts.map +1 -0
  11. package/dist/lib/arrow/lease.js +33 -0
  12. package/dist/lib/arrow/utils.d.ts +3 -4
  13. package/dist/lib/arrow/utils.d.ts.map +1 -1
  14. package/dist/lib/arrow/utils.js +12 -13
  15. package/dist/lib/arrow/vocabularyDictionary.d.ts +21 -0
  16. package/dist/lib/arrow/vocabularyDictionary.d.ts.map +1 -0
  17. package/dist/lib/arrow/vocabularyDictionary.js +95 -0
  18. package/dist/lib/bufferStrategy.d.ts +3 -2
  19. package/dist/lib/bufferStrategy.d.ts.map +1 -1
  20. package/dist/lib/cloudflare/traceRows.d.ts.map +1 -1
  21. package/dist/lib/cloudflare/traceRows.js +3 -2
  22. package/dist/lib/codegen/evaluatorGenerator.d.ts.map +1 -1
  23. package/dist/lib/codegen/evaluatorGenerator.js +12 -11
  24. package/dist/lib/codegen/fixedPositionWriterGenerator.d.ts +44 -82
  25. package/dist/lib/codegen/fixedPositionWriterGenerator.d.ts.map +1 -1
  26. package/dist/lib/codegen/fixedPositionWriterGenerator.js +223 -162
  27. package/dist/lib/codegen/spanLoggerClosureMaterializer.d.ts +63 -0
  28. package/dist/lib/codegen/spanLoggerClosureMaterializer.d.ts.map +1 -0
  29. package/dist/lib/codegen/spanLoggerClosureMaterializer.js +447 -0
  30. package/dist/lib/codegen/spanLoggerGenerator.d.ts +36 -19
  31. package/dist/lib/codegen/spanLoggerGenerator.d.ts.map +1 -1
  32. package/dist/lib/codegen/spanLoggerGenerator.js +164 -158
  33. package/dist/lib/convertToArrow.d.ts +7 -2
  34. package/dist/lib/convertToArrow.d.ts.map +1 -1
  35. package/dist/lib/convertToArrow.js +499 -285
  36. package/dist/lib/defineOpContext.js +1 -1
  37. package/dist/lib/enumMetadata.d.ts +19 -0
  38. package/dist/lib/enumMetadata.d.ts.map +1 -0
  39. package/dist/lib/enumMetadata.js +86 -0
  40. package/dist/lib/flushScheduler.d.ts.map +1 -1
  41. package/dist/lib/flushScheduler.js +13 -4
  42. package/dist/lib/library.d.ts +16 -98
  43. package/dist/lib/library.d.ts.map +1 -1
  44. package/dist/lib/library.js +32 -525
  45. package/dist/lib/logBinding.d.ts +21 -27
  46. package/dist/lib/logBinding.d.ts.map +1 -1
  47. package/dist/lib/op.d.ts +30 -30
  48. package/dist/lib/op.d.ts.map +1 -1
  49. package/dist/lib/op.js +15 -22
  50. package/dist/lib/opContext/createOpGroup.d.ts +1 -1
  51. package/dist/lib/opContext/createOpGroup.d.ts.map +1 -1
  52. package/dist/lib/opContext/createOpGroup.js +22 -29
  53. package/dist/lib/opContext/defineOp.d.ts +4 -4
  54. package/dist/lib/opContext/defineOp.d.ts.map +1 -1
  55. package/dist/lib/opContext/defineOp.js +53 -10
  56. package/dist/lib/opContext/opGroupTypes.d.ts +2 -2
  57. package/dist/lib/opContext/opTypes.d.ts +1 -1
  58. package/dist/lib/opContext/opTypes.d.ts.map +1 -1
  59. package/dist/lib/opContext/spanContextTypes.d.ts +33 -18
  60. package/dist/lib/opContext/spanContextTypes.d.ts.map +1 -1
  61. package/dist/lib/opContext/types.d.ts +4 -4
  62. package/dist/lib/opContext/types.d.ts.map +1 -1
  63. package/dist/lib/physicalLayoutPlan.d.ts +89 -0
  64. package/dist/lib/physicalLayoutPlan.d.ts.map +1 -0
  65. package/dist/lib/physicalLayoutPlan.js +442 -0
  66. package/dist/lib/resolveMessage.d.ts +9 -0
  67. package/dist/lib/resolveMessage.d.ts.map +1 -0
  68. package/dist/lib/resolveMessage.js +63 -0
  69. package/dist/lib/result.d.ts +5 -7
  70. package/dist/lib/result.d.ts.map +1 -1
  71. package/dist/lib/result.js +19 -26
  72. package/dist/lib/runtimeHint.d.ts +35 -0
  73. package/dist/lib/runtimeHint.d.ts.map +1 -0
  74. package/dist/lib/runtimeHint.js +79 -0
  75. package/dist/lib/schema/typeGuards.d.ts +7 -47
  76. package/dist/lib/schema/typeGuards.d.ts.map +1 -1
  77. package/dist/lib/schema/typeGuards.js +7 -123
  78. package/dist/lib/schema/types.d.ts +1 -1
  79. package/dist/lib/schema/types.d.ts.map +1 -1
  80. package/dist/lib/span-buffer/aot/v1.d.ts +2 -0
  81. package/dist/lib/span-buffer/aot/v1.d.ts.map +1 -0
  82. package/dist/lib/span-buffer/aot/v1.js +24 -0
  83. package/dist/lib/spanBuffer.d.ts +33 -4
  84. package/dist/lib/spanBuffer.d.ts.map +1 -1
  85. package/dist/lib/spanBuffer.js +583 -91
  86. package/dist/lib/spanBufferStats.d.ts +1 -1
  87. package/dist/lib/spanBufferStats.d.ts.map +1 -1
  88. package/dist/lib/spanContext.d.ts +27 -51
  89. package/dist/lib/spanContext.d.ts.map +1 -1
  90. package/dist/lib/spanContext.js +822 -344
  91. package/dist/lib/sqlite/sqlite-common.d.ts.map +1 -1
  92. package/dist/lib/sqlite/sqlite-common.js +20 -21
  93. package/dist/lib/testing/bun-harness.d.ts +8 -3
  94. package/dist/lib/testing/bun-harness.d.ts.map +1 -1
  95. package/dist/lib/testing/bun-harness.js +30 -18
  96. package/dist/lib/testing/extractFacts.d.ts +1 -1
  97. package/dist/lib/testing/extractFacts.d.ts.map +1 -1
  98. package/dist/lib/testing/extractFacts.js +55 -63
  99. package/dist/lib/testing/facts.d.ts +1 -1
  100. package/dist/lib/testing/facts.d.ts.map +1 -1
  101. package/dist/lib/testing/queryable-span.d.ts +1 -1
  102. package/dist/lib/testing/queryable-span.d.ts.map +1 -1
  103. package/dist/lib/testing/queryable-span.js +26 -28
  104. package/dist/lib/testing/span-query.d.ts.map +1 -1
  105. package/dist/lib/testing/span-query.js +19 -22
  106. package/dist/lib/testing/stdio-replay.d.ts.map +1 -1
  107. package/dist/lib/testing/stdio-replay.js +19 -8
  108. package/dist/lib/threadId.d.ts.map +1 -1
  109. package/dist/lib/threadId.js +6 -3
  110. package/dist/lib/traceContext.d.ts.map +1 -1
  111. package/dist/lib/traceContext.js +1 -4
  112. package/dist/lib/traceRoot.d.ts +30 -8
  113. package/dist/lib/traceRoot.d.ts.map +1 -1
  114. package/dist/lib/traceRoot.es.d.ts +17 -15
  115. package/dist/lib/traceRoot.es.d.ts.map +1 -1
  116. package/dist/lib/traceRoot.es.js +68 -34
  117. package/dist/lib/traceRoot.js +11 -0
  118. package/dist/lib/traceRoot.node.d.ts +17 -19
  119. package/dist/lib/traceRoot.node.d.ts.map +1 -1
  120. package/dist/lib/traceRoot.node.js +66 -38
  121. package/dist/lib/traceTopology.d.ts +42 -0
  122. package/dist/lib/traceTopology.d.ts.map +1 -0
  123. package/dist/lib/traceTopology.js +260 -0
  124. package/dist/lib/tracer.d.ts +9 -5
  125. package/dist/lib/tracer.d.ts.map +1 -1
  126. package/dist/lib/tracer.js +65 -71
  127. package/dist/lib/tracers/ArrayQueueTracer.d.ts +1 -1
  128. package/dist/lib/tracers/ArrayQueueTracer.js +1 -1
  129. package/dist/lib/tracers/StdioTracer.d.ts.map +1 -1
  130. package/dist/lib/tracers/StdioTracer.js +15 -13
  131. package/dist/lib/tracers/TestTracer.d.ts +4 -6
  132. package/dist/lib/tracers/TestTracer.d.ts.map +1 -1
  133. package/dist/lib/tracers/TestTracer.js +6 -8
  134. package/dist/lib/types.d.ts +49 -32
  135. package/dist/lib/types.d.ts.map +1 -1
  136. package/dist/lib/vocabularyRegistry.d.ts +25 -0
  137. package/dist/lib/vocabularyRegistry.d.ts.map +1 -0
  138. package/dist/lib/vocabularyRegistry.js +372 -0
  139. package/dist/lib/wasm/WasmBufferStrategy.d.ts +6 -10
  140. package/dist/lib/wasm/WasmBufferStrategy.d.ts.map +1 -1
  141. package/dist/lib/wasm/WasmBufferStrategy.js +44 -37
  142. package/dist/lib/wasm/wasmAllocator.d.ts +27 -22
  143. package/dist/lib/wasm/wasmAllocator.d.ts.map +1 -1
  144. package/dist/lib/wasm/wasmAllocator.js +66 -44
  145. package/dist/lib/wasm/wasmPhysicalLayout.d.ts +67 -0
  146. package/dist/lib/wasm/wasmPhysicalLayout.d.ts.map +1 -0
  147. package/dist/lib/wasm/wasmPhysicalLayout.js +179 -0
  148. package/dist/lib/wasm/wasmSpanBuffer.d.ts +79 -31
  149. package/dist/lib/wasm/wasmSpanBuffer.d.ts.map +1 -1
  150. package/dist/lib/wasm/wasmSpanBuffer.js +442 -272
  151. package/dist/lib/wasm/wasmTraceRoot.d.ts +24 -22
  152. package/dist/lib/wasm/wasmTraceRoot.d.ts.map +1 -1
  153. package/dist/lib/wasm/wasmTraceRoot.js +110 -71
  154. package/dist/vocabulary/register/v1.d.ts +2 -0
  155. package/dist/vocabulary/register/v1.d.ts.map +1 -0
  156. package/dist/vocabulary/register/v1.js +1 -0
  157. package/dist/wasm.d.ts +5 -0
  158. package/dist/wasm.d.ts.map +1 -0
  159. package/dist/wasm.js +4 -0
  160. package/package.json +54 -6
  161. package/src/index.ts +1 -0
  162. package/src/lib/JsBufferStrategy.ts +27 -9
  163. package/src/lib/__tests__/arrow-builder-integration/arrow-conversion.test.ts +335 -37
  164. package/src/lib/__tests__/arrow-builder-integration/binary-arrow-conversion.test.ts +97 -26
  165. package/src/lib/__tests__/arrow-builder-integration/binary-comparison.test.ts +75 -15
  166. package/src/lib/__tests__/arrow-builder-integration/binary-format-compliance.test.ts +30 -6
  167. package/src/lib/__tests__/arrow-builder-integration/buffer-chaining.test.ts +18 -21
  168. package/src/lib/__tests__/arrow-builder-integration/foundation.test.ts +5 -2
  169. package/src/lib/__tests__/arrow-builder-integration/integration.test.ts +25 -7
  170. package/src/lib/__tests__/arrow-builder-integration/lazy-columns.test.ts +3 -2
  171. package/src/lib/__tests__/buffer-overflow.test.ts +24 -18
  172. package/src/lib/__tests__/capability-span-context.test.ts +505 -0
  173. package/src/lib/__tests__/capacity-tuning.test.ts +5 -3
  174. package/src/lib/__tests__/eager-columns.test.ts +345 -0
  175. package/src/lib/__tests__/enum-metadata-aot.test.ts +153 -0
  176. package/src/lib/__tests__/enum-metadata.test.ts +177 -0
  177. package/src/lib/__tests__/fixtures/empty-vocabulary-runtime.fixture.ts +15 -0
  178. package/src/lib/__tests__/flushScheduler.test.ts +5 -1
  179. package/src/lib/__tests__/identity-view.property.test.ts +179 -0
  180. package/src/lib/__tests__/library.test.ts +19 -235
  181. package/src/lib/__tests__/message-buffer-families.test.ts +878 -0
  182. package/src/lib/__tests__/nested-library-tasks.test.ts +14 -15
  183. package/src/lib/__tests__/op-metadata.test.ts +1 -1
  184. package/src/lib/__tests__/op-type-safety.test.ts +5 -16
  185. package/src/lib/__tests__/physical-layout-plan.test.ts +333 -0
  186. package/src/lib/__tests__/remap-descriptor-integration.test.ts +381 -0
  187. package/src/lib/__tests__/root-context-construction.test.ts +414 -0
  188. package/src/lib/__tests__/span-auto-runtime.test.ts +386 -0
  189. package/src/lib/__tests__/span-buffer-segment-stats.test.ts +221 -0
  190. package/src/lib/__tests__/span-lifecycle.test.ts +53 -25
  191. package/src/lib/__tests__/spanbuffer-materializer-parity.test.ts +266 -0
  192. package/src/lib/__tests__/sync-async-trace.test.ts +24 -23
  193. package/src/lib/__tests__/tag-writer-aot.test.ts +214 -0
  194. package/src/lib/__tests__/test-helpers.ts +67 -12
  195. package/src/lib/__tests__/threadId.test.ts +62 -0
  196. package/src/lib/__tests__/timestamp.test.ts +221 -93
  197. package/src/lib/__tests__/traceTopology.property.test.ts +383 -0
  198. package/src/lib/__tests__/type-narrowing.test.ts +63 -0
  199. package/src/lib/__tests__/vocabulary-dense-decoding.test.ts +405 -0
  200. package/src/lib/__tests__/vocabularyRegistry.test.ts +313 -0
  201. package/src/lib/arrow/lease.ts +43 -0
  202. package/src/lib/arrow/utils.ts +10 -14
  203. package/src/lib/arrow/vocabularyDictionary.ts +123 -0
  204. package/src/lib/bufferStrategy.ts +9 -1
  205. package/src/lib/cloudflare/traceRows.ts +3 -2
  206. package/src/lib/codegen/__tests__/evaluatorGenerator.test.ts +21 -141
  207. package/src/lib/codegen/__tests__/fixedPositionWriter-parity.test.ts +273 -0
  208. package/src/lib/codegen/__tests__/fixedPositionWriter-uint64.test.ts +61 -34
  209. package/src/lib/codegen/__tests__/nullBitmap.test.ts +33 -37
  210. package/src/lib/codegen/__tests__/spanLoggerGenerator.test.ts +34 -18
  211. package/src/lib/codegen/__tests__/spanLoggerMaterializerParity.test.ts +503 -0
  212. package/src/lib/codegen/evaluatorGenerator.ts +18 -13
  213. package/src/lib/codegen/fixedPositionWriterGenerator.ts +329 -245
  214. package/src/lib/codegen/spanLoggerClosureMaterializer.ts +598 -0
  215. package/src/lib/codegen/spanLoggerGenerator.ts +241 -177
  216. package/src/lib/convertToArrow.ts +598 -311
  217. package/src/lib/defineOpContext.ts +1 -1
  218. package/src/lib/enumMetadata.ts +121 -0
  219. package/src/lib/flushScheduler.ts +11 -5
  220. package/src/lib/library.ts +37 -595
  221. package/src/lib/logBinding.ts +21 -27
  222. package/src/lib/op.ts +75 -18
  223. package/src/lib/opContext/__tests__/retry.test.ts +27 -21
  224. package/src/lib/opContext/createOpGroup.ts +33 -31
  225. package/src/lib/opContext/defineOp.ts +88 -11
  226. package/src/lib/opContext/opGroupTypes.ts +2 -2
  227. package/src/lib/opContext/opTypes.ts +1 -1
  228. package/src/lib/opContext/spanContextTypes.ts +122 -24
  229. package/src/lib/opContext/types.ts +7 -3
  230. package/src/lib/physicalLayoutPlan.ts +598 -0
  231. package/src/lib/resolveMessage.ts +67 -0
  232. package/src/lib/result.ts +20 -33
  233. package/src/lib/runtimeHint.ts +98 -0
  234. package/src/lib/schema/__tests__/featureFlags.test.ts +2 -1
  235. package/src/lib/schema/builder.ts +1 -1
  236. package/src/lib/schema/typeGuards.ts +7 -151
  237. package/src/lib/schema/types.ts +1 -1
  238. package/src/lib/span-buffer/aot/v1.ts +26 -0
  239. package/src/lib/spanBuffer.ts +658 -92
  240. package/src/lib/spanBufferStats.ts +1 -1
  241. package/src/lib/spanContext.ts +1350 -861
  242. package/src/lib/sqlite/sqlite-common.ts +20 -31
  243. package/src/lib/testing/__tests__/topology-traversal.test.ts +174 -0
  244. package/src/lib/testing/__tests__/vitest-harness.test.ts +2 -1
  245. package/src/lib/testing/bun-harness.ts +94 -43
  246. package/src/lib/testing/extractFacts.ts +64 -78
  247. package/src/lib/testing/facts.ts +1 -1
  248. package/src/lib/testing/queryable-span.ts +23 -30
  249. package/src/lib/testing/span-query.ts +16 -20
  250. package/src/lib/testing/stdio-replay.ts +25 -8
  251. package/src/lib/testing/vitest-harness.ts +1 -1
  252. package/src/lib/threadId.ts +6 -3
  253. package/src/lib/traceContext.ts +1 -6
  254. package/src/lib/traceRoot.es.ts +77 -42
  255. package/src/lib/traceRoot.node.ts +75 -46
  256. package/src/lib/traceRoot.ts +41 -14
  257. package/src/lib/traceTopology.ts +279 -0
  258. package/src/lib/tracer.ts +109 -98
  259. package/src/lib/tracers/ArrayQueueTracer.ts +1 -1
  260. package/src/lib/tracers/StdioTracer.ts +15 -13
  261. package/src/lib/tracers/TestTracer.ts +6 -8
  262. package/src/lib/tracers/__tests__/ArrayQueueTracer.test.ts +15 -10
  263. package/src/lib/tracers/__tests__/CompositeTracer.test.ts +150 -0
  264. package/src/lib/tracers/__tests__/TestTracer.test.ts +23 -13
  265. package/src/lib/types.ts +64 -33
  266. package/src/lib/vocabularyRegistry.ts +439 -0
  267. package/src/lib/wasm/WasmBufferStrategy.ts +56 -48
  268. package/src/lib/wasm/__tests__/WasmBufferStrategy.test.ts +215 -11
  269. package/src/lib/wasm/__tests__/allocatorFreeBlockClamp.test.ts +86 -0
  270. package/src/lib/wasm/__tests__/wasm-identity-view.test.ts +311 -0
  271. package/src/lib/wasm/__tests__/wasm-integration.test.ts +417 -44
  272. package/src/lib/wasm/__tests__/wasm-message-buffer-families.test.ts +588 -0
  273. package/src/lib/wasm/__tests__/wasmAllocator.test.ts +100 -668
  274. package/src/lib/wasm/__tests__/wasmSpanBuffer.test.ts +419 -63
  275. package/src/lib/wasm/__tests__/wasmTraceRoot.test.ts +24 -29
  276. package/src/lib/wasm/__tests__/wasmTracer.test.ts.disabled +2 -2
  277. package/src/lib/wasm/wasmAllocator.ts +131 -96
  278. package/src/lib/wasm/wasmPhysicalLayout.ts +309 -0
  279. package/src/lib/wasm/wasmSpanBuffer.ts +597 -341
  280. package/src/lib/wasm/wasmTraceRoot.ts +140 -78
  281. package/src/vocabulary/register/v1.ts +1 -0
  282. package/src/wasm.ts +19 -0
  283. package/src/lib/__tests__/remapped-buffer-view-integration.test.ts +0 -319
  284. package/src/lib/__tests__/remapped-buffer-view.test.ts +0 -635
  285. package/src/lib/wasm/allocator.zig +0 -948
@@ -22,7 +22,13 @@
22
22
 
23
23
  import { describe, expect, it } from 'bun:test';
24
24
  import { createResultWriter, createTagWriter, ENTRY_TYPE_SPAN_OK, ENTRY_TYPE_SPAN_START, S } from '@smoothbricks/lmao';
25
- import { createTestOpMetadata, createTestSchema, createTestTraceRoot } from '../../__tests__/test-helpers.js';
25
+ import {
26
+ createTestOpMetadata,
27
+ createTestSchema,
28
+ createTestSpanContext,
29
+ createTestTraceRoot,
30
+ } from '../../__tests__/test-helpers.js';
31
+ import { resolveEntryType } from '../../resolveMessage.js';
26
32
  import { createSpanBuffer } from '../../spanBuffer.js';
27
33
  import type { AnySpanBuffer } from '../../types.js';
28
34
 
@@ -37,7 +43,8 @@ import type { AnySpanBuffer } from '../../types.js';
37
43
  function setup() {
38
44
  const schema = createTestSchema({ batchId: S.category(), count: S.number() });
39
45
  const buffer = createSpanBuffer(schema, createTestTraceRoot('t'), createTestOpMetadata(), 8);
40
- return { schema, buffer };
46
+ const context = createTestSpanContext(schema, buffer);
47
+ return { schema, buffer, context };
41
48
  }
42
49
 
43
50
  // Read the allocated `uint64_value` values, narrowed to BigUint64Array.
@@ -77,15 +84,35 @@ function writeUint64Runtime(writer: object, value: bigint | null): void {
77
84
  Reflect.apply(method, writer, [value]);
78
85
  }
79
86
 
87
+ describe('fixed-position WriterState ownership', () => {
88
+ it('keeps tag and result writers as one-field views over declared state', () => {
89
+ const { schema, buffer, context } = setup();
90
+ const writers = [createTagWriter(schema, context), createResultWriter(schema, context)];
91
+
92
+ for (const writer of writers) {
93
+ expect(Reflect.ownKeys(writer)).toEqual(['_state']);
94
+ expect(Object.hasOwn(writer, '_buffer')).toBe(false);
95
+ expect(Object.hasOwn(writer, '_spanBuffer')).toBe(false);
96
+ expect(Object.hasOwn(writer, '_traceRoot')).toBe(false);
97
+ expect(Object.hasOwn(writer, '_appendLogEntry')).toBe(false);
98
+
99
+ const state = Reflect.get(writer, '_state');
100
+ expect(Object.is(state, context)).toBe(true);
101
+ expect(Reflect.get(state, '_spanBuffer')).toBe(buffer);
102
+ expect(Reflect.get(state, '_buffer')).toBe(buffer);
103
+ }
104
+ });
105
+ });
106
+
80
107
  // ---------------------------------------------------------------------------
81
108
  // Row placement
82
109
  // ---------------------------------------------------------------------------
83
110
 
84
111
  describe('uint64_value row placement', () => {
85
112
  it('TagWriter writes to row 0 (span-start)', () => {
86
- const { schema, buffer } = setup();
113
+ const { schema, buffer, context } = setup();
87
114
 
88
- createTagWriter(schema, buffer).uint64_value(123n);
115
+ createTagWriter(schema, context).uint64_value(123n);
89
116
 
90
117
  const values = uint64Column(buffer);
91
118
  const nulls = uint64Nulls(buffer);
@@ -96,9 +123,9 @@ describe('uint64_value row placement', () => {
96
123
  });
97
124
 
98
125
  it('ResultWriter writes to row 1 (span-completion)', () => {
99
- const { schema, buffer } = setup();
126
+ const { schema, buffer, context } = setup();
100
127
 
101
- createResultWriter(schema, buffer, { ok: true }, false).uint64_value(456n);
128
+ createResultWriter(schema, context).uint64_value(456n);
102
129
 
103
130
  const values = uint64Column(buffer);
104
131
  const nulls = uint64Nulls(buffer);
@@ -115,12 +142,12 @@ describe('uint64_value row placement', () => {
115
142
 
116
143
  describe('uint64_value cross-row independence (no collision)', () => {
117
144
  it('tag row 0 and result row 1 hold distinct values on one buffer', () => {
118
- const { schema, buffer } = setup();
145
+ const { schema, buffer, context } = setup();
119
146
  const rowZero = 111n;
120
147
  const rowOne = 222n;
121
148
 
122
- createTagWriter(schema, buffer).uint64_value(rowZero);
123
- createResultWriter(schema, buffer, { ok: true }, false).uint64_value(rowOne);
149
+ createTagWriter(schema, context).uint64_value(rowZero);
150
+ createResultWriter(schema, context).uint64_value(rowOne);
124
151
 
125
152
  const values = uint64Column(buffer);
126
153
  const nulls = uint64Nulls(buffer);
@@ -132,13 +159,13 @@ describe('uint64_value cross-row independence (no collision)', () => {
132
159
  });
133
160
 
134
161
  it('is order-independent: result-first then tag yields the same layout', () => {
135
- const { schema, buffer } = setup();
162
+ const { schema, buffer, context } = setup();
136
163
  const rowZero = 333n;
137
164
  const rowOne = 444n;
138
165
 
139
166
  // Reverse the write order relative to the previous case.
140
- createResultWriter(schema, buffer, { ok: true }, false).uint64_value(rowOne);
141
- createTagWriter(schema, buffer).uint64_value(rowZero);
167
+ createResultWriter(schema, context).uint64_value(rowOne);
168
+ createTagWriter(schema, context).uint64_value(rowZero);
142
169
 
143
170
  const values = uint64Column(buffer);
144
171
  expect(values[0]).toBe(rowZero);
@@ -146,12 +173,12 @@ describe('uint64_value cross-row independence (no collision)', () => {
146
173
  });
147
174
 
148
175
  it('survives the span lifecycle: writeSpanStart/writeSpanEnd never touch uint64_value', () => {
149
- const { schema, buffer } = setup();
176
+ const { schema, buffer, context } = setup();
150
177
  const rowZero = 900n;
151
178
  const rowOne = 901n;
152
179
 
153
- const tag = createTagWriter(schema, buffer);
154
- const result = createResultWriter(schema, buffer, { ok: true }, false);
180
+ const tag = createTagWriter(schema, context);
181
+ const result = createResultWriter(schema, context);
155
182
 
156
183
  // Reproduce the production sequence: lifecycle start, user tags, user result, lifecycle end.
157
184
  buffer._traceRoot.writeSpanStart(buffer, 'lifecycle-span');
@@ -160,8 +187,8 @@ describe('uint64_value cross-row independence (no collision)', () => {
160
187
  buffer._traceRoot.writeSpanEnd(buffer, ENTRY_TYPE_SPAN_OK);
161
188
 
162
189
  // The lifecycle actually ran and wrote its OWN columns (entry_type)...
163
- expect(buffer.entry_type[0]).toBe(ENTRY_TYPE_SPAN_START);
164
- expect(buffer.entry_type[1]).toBe(ENTRY_TYPE_SPAN_OK);
190
+ expect(resolveEntryType(buffer, 0)).toBe(ENTRY_TYPE_SPAN_START);
191
+ expect(resolveEntryType(buffer, 1)).toBe(ENTRY_TYPE_SPAN_OK);
165
192
  // ...without clobbering the user uint64 values in either row.
166
193
  const values = uint64Column(buffer);
167
194
  const nulls = uint64Nulls(buffer);
@@ -178,12 +205,12 @@ describe('uint64_value cross-row independence (no collision)', () => {
178
205
 
179
206
  describe('uint64_value lazy allocation', () => {
180
207
  it('is unallocated until first write, then allocated', () => {
181
- const { schema, buffer } = setup();
208
+ const { schema, buffer, context } = setup();
182
209
 
183
210
  expect(buffer.getColumnIfAllocated('uint64_value')).toBeUndefined();
184
211
  expect(buffer.getNullsIfAllocated('uint64_value')).toBeUndefined();
185
212
 
186
- createTagWriter(schema, buffer).uint64_value(7n);
213
+ createTagWriter(schema, context).uint64_value(7n);
187
214
 
188
215
  expect(buffer.getColumnIfAllocated('uint64_value')).toBeDefined();
189
216
  expect(uint64Column(buffer)[0]).toBe(7n);
@@ -196,15 +223,15 @@ describe('uint64_value lazy allocation', () => {
196
223
 
197
224
  describe('uint64_value chaining and sibling non-interference', () => {
198
225
  it('returns the writer for chaining', () => {
199
- const { schema, buffer } = setup();
200
- const tag = createTagWriter(schema, buffer);
226
+ const { schema, context } = setup();
227
+ const tag = createTagWriter(schema, context);
201
228
  expect(tag.uint64_value(1n)).toBe(tag);
202
229
  });
203
230
 
204
231
  it('batchId(...).uint64_value(...) lands both values', () => {
205
- const { schema, buffer } = setup();
232
+ const { schema, buffer, context } = setup();
206
233
 
207
- createTagWriter(schema, buffer).batchId('batch-A').uint64_value(10n);
234
+ createTagWriter(schema, context).batchId('batch-A').uint64_value(10n);
208
235
 
209
236
  expect(uint64Column(buffer)[0]).toBe(10n);
210
237
  const batch = buffer.getColumnIfAllocated('batchId');
@@ -215,9 +242,9 @@ describe('uint64_value chaining and sibling non-interference', () => {
215
242
  });
216
243
 
217
244
  it('uint64_value(...).batchId(...) lands both values (reverse order)', () => {
218
- const { schema, buffer } = setup();
245
+ const { schema, buffer, context } = setup();
219
246
 
220
- createTagWriter(schema, buffer).uint64_value(20n).batchId('batch-B');
247
+ createTagWriter(schema, context).uint64_value(20n).batchId('batch-B');
221
248
 
222
249
  expect(uint64Column(buffer)[0]).toBe(20n);
223
250
  const batch = buffer.getColumnIfAllocated('batchId');
@@ -234,8 +261,8 @@ describe('uint64_value chaining and sibling non-interference', () => {
234
261
 
235
262
  describe('uint64_value null handling', () => {
236
263
  it('writing null clears the null bit (value marked absent), not sets it', () => {
237
- const { schema, buffer } = setup();
238
- const tag = createTagWriter(schema, buffer);
264
+ const { schema, buffer, context } = setup();
265
+ const tag = createTagWriter(schema, context);
239
266
 
240
267
  // First set a real value so the null bit is on...
241
268
  tag.uint64_value(99n);
@@ -247,9 +274,9 @@ describe('uint64_value null handling', () => {
247
274
  });
248
275
 
249
276
  it('null at row 1 clears row 1 only, leaving a non-null row 0 intact', () => {
250
- const { schema, buffer } = setup();
251
- const tag = createTagWriter(schema, buffer);
252
- const result = createResultWriter(schema, buffer, { ok: true }, false);
277
+ const { schema, buffer, context } = setup();
278
+ const tag = createTagWriter(schema, context);
279
+ const result = createResultWriter(schema, context);
253
280
 
254
281
  tag.uint64_value(5n);
255
282
  result.uint64_value(6n);
@@ -280,8 +307,8 @@ describe('uint64_value boundary values', () => {
280
307
 
281
308
  for (const { name, value } of cases) {
282
309
  it(`round-trips ${name} exactly`, () => {
283
- const { schema, buffer } = setup();
284
- createTagWriter(schema, buffer).uint64_value(value);
310
+ const { schema, buffer, context } = setup();
311
+ createTagWriter(schema, context).uint64_value(value);
285
312
 
286
313
  const values = uint64Column(buffer);
287
314
  expect(values[0]).toBe(value);
@@ -290,8 +317,8 @@ describe('uint64_value boundary values', () => {
290
317
  }
291
318
 
292
319
  it('stores 0n as a non-null zero, distinct from absent', () => {
293
- const { schema, buffer } = setup();
294
- createTagWriter(schema, buffer).uint64_value(0n);
320
+ const { schema, buffer, context } = setup();
321
+ createTagWriter(schema, context).uint64_value(0n);
295
322
 
296
323
  const values = uint64Column(buffer);
297
324
  const nulls = uint64Nulls(buffer);
@@ -7,48 +7,44 @@
7
7
  * Architecture changes (new design):
8
8
  * - SpanLogger handles log entries (rows 2+), NOT tag writes (row 0)
9
9
  * - Tag writing is done via ctx.tag which is a separate API (not on SpanLogger)
10
- * - SpanLogger constructor: (buffer, createNextBuffer)
11
- * - SpanLogger._writeIndex starts at 1 (rows 0/1 are reserved for span-start/end)
10
+ * - SpanLogger owns only `_state`, shared with its SpanContext
11
+ * - SpanContext owns the active buffer and write index state
12
12
  * - _setScope() stores scope values in buffer._scopeValues (immutable, frozen)
13
13
  * - Scope filling happens at Arrow conversion time, NOT during span execution
14
14
  * - Direct writes (tag/log) win over scope values on their respective rows
15
15
  */
16
16
 
17
17
  import { describe, expect, it } from 'bun:test';
18
- import { createBuffer, createTestTraceRoot } from '../../__tests__/test-helpers.js';
18
+ import {
19
+ createBuffer,
20
+ createTestSchema,
21
+ createTestSpanContext,
22
+ createTestTraceRoot,
23
+ } from '../../__tests__/test-helpers.js';
19
24
  import { DEFAULT_METADATA } from '../../opContext/defineOp.js';
20
25
  import { S } from '../../schema/builder.js';
21
- import { defineLogSchema } from '../../schema/defineLogSchema.js';
22
26
  import type { LogSchema } from '../../schema/types.js';
23
27
  import { createSpanBuffer, SpanBufferTestUtils } from '../../spanBuffer.js';
24
28
 
25
- import type { AnySpanBuffer } from '../../types.js';
26
- import { createSpanLoggerClass } from '../spanLoggerGenerator.js';
29
+ import type { SpanBuffer } from '../../types.js';
27
30
 
28
31
  /**
29
32
  * Create a test buffer from a schema
30
33
  */
31
- function createTestBuffer(schema: LogSchema): AnySpanBuffer {
34
+ function createTestBuffer<T extends LogSchema>(schema: T): SpanBuffer<T> {
32
35
  return createBuffer(schema);
33
36
  }
34
37
 
35
- /**
36
- * Create a test buffer with a specific capacity
37
- */
38
- function createTestBufferWithCapacity(schema: LogSchema, capacity: number): AnySpanBuffer {
39
- return createSpanBuffer(schema, createTestTraceRoot('test-trace'), DEFAULT_METADATA, capacity);
40
- }
41
-
42
38
  describe('null bitmap correctness', () => {
43
39
  describe('immutable scope semantics', () => {
44
40
  it('should store scope values in buffer._scopeValues as frozen object', () => {
45
- const schema = defineLogSchema({
41
+ const schema = createTestSchema({
46
42
  requestId: S.category(),
47
43
  });
48
44
  const buffer = createTestBuffer(schema);
49
45
 
50
- const SpanLoggerClass = createSpanLoggerClass(schema);
51
- const logger = new SpanLoggerClass(buffer);
46
+ const ctx = createTestSpanContext(schema, buffer);
47
+ const logger = ctx._spanLogger;
52
48
 
53
49
  // _setScope should store values in buffer._scopeValues (not fill buffer columns)
54
50
  logger._setScope({ requestId: 'req-123' });
@@ -62,14 +58,14 @@ describe('null bitmap correctness', () => {
62
58
  });
63
59
 
64
60
  it('should create new frozen object on each _setScope call (merge semantics)', () => {
65
- const schema = defineLogSchema({
61
+ const schema = createTestSchema({
66
62
  requestId: S.category(),
67
63
  userId: S.category(),
68
64
  });
69
65
  const buffer = createTestBuffer(schema);
70
66
 
71
- const SpanLoggerClass = createSpanLoggerClass(schema);
72
- const logger = new SpanLoggerClass(buffer);
67
+ const ctx = createTestSpanContext(schema, buffer);
68
+ const logger = ctx._spanLogger;
73
69
 
74
70
  // First setScope call
75
71
  logger._setScope({ requestId: 'req-123' });
@@ -94,14 +90,14 @@ describe('null bitmap correctness', () => {
94
90
  });
95
91
 
96
92
  it('should clear keys when null is passed (null clears, undefined ignores)', () => {
97
- const schema = defineLogSchema({
93
+ const schema = createTestSchema({
98
94
  requestId: S.category(),
99
95
  userId: S.category(),
100
96
  });
101
97
  const buffer = createTestBuffer(schema);
102
98
 
103
- const SpanLoggerClass = createSpanLoggerClass(schema);
104
- const logger = new SpanLoggerClass(buffer);
99
+ const ctx = createTestSpanContext(schema, buffer);
100
+ const logger = ctx._spanLogger;
105
101
 
106
102
  // Set initial values
107
103
  logger._setScope({ requestId: 'req-123', userId: 'user-456' });
@@ -117,13 +113,13 @@ describe('null bitmap correctness', () => {
117
113
  });
118
114
 
119
115
  it('should NOT fill buffer columns during _setScope (deferred to Arrow conversion)', () => {
120
- const schema = defineLogSchema({
116
+ const schema = createTestSchema({
121
117
  requestId: S.category(),
122
118
  });
123
119
  const buffer = createTestBuffer(schema);
124
120
 
125
- const SpanLoggerClass = createSpanLoggerClass(schema);
126
- const logger = new SpanLoggerClass(buffer);
121
+ const ctx = createTestSpanContext(schema, buffer);
122
+ const logger = ctx._spanLogger;
127
123
 
128
124
  // _setScope should NOT fill buffer columns
129
125
  logger._setScope({ requestId: 'req-123' });
@@ -143,7 +139,7 @@ describe('null bitmap correctness', () => {
143
139
  // - Scope values are stored in buffer._scopeValues as a plain object
144
140
  // - Scope filling happens at Arrow conversion time, NOT during span execution
145
141
  // - This is because scope values are "defaults" that fill null slots
146
- const schema = defineLogSchema({
142
+ const schema = createTestSchema({
147
143
  requestId: S.category(),
148
144
  });
149
145
  const buffer = createTestBuffer(schema);
@@ -151,11 +147,11 @@ describe('null bitmap correctness', () => {
151
147
  // Set scope value via buffer._scopeValues directly for test setup
152
148
  buffer._scopeValues = Object.freeze({ requestId: 'req-123' });
153
149
 
154
- const SpanLoggerClass = createSpanLoggerClass(schema);
155
- const logger = new SpanLoggerClass(buffer);
150
+ const ctx = createTestSpanContext(schema, buffer);
151
+ const logger = ctx._spanLogger;
156
152
 
157
- // Set _writeIndex to 4 so nextRow() makes it 5
158
- logger._writeIndex = 4;
153
+ // Set the shared writer state so the next append writes row 5
154
+ ctx._buffer._writeIndex = 5;
159
155
 
160
156
  // Log a message - this does NOT write scoped attributes during execution
161
157
  // Scope values are filled at Arrow conversion time
@@ -173,20 +169,20 @@ describe('null bitmap correctness', () => {
173
169
  it('should NOT set null bitmap at index 9 during info() - scope is deferred', () => {
174
170
  // Same as above - scope values are NOT written during span execution
175
171
  // They are stored in buffer._scopeValues and filled at Arrow conversion
176
- const schema = defineLogSchema({
172
+ const schema = createTestSchema({
177
173
  requestId: S.category(),
178
174
  });
179
175
  // Need capacity > 9 to test writing at index 9
180
- const buffer = createTestBufferWithCapacity(schema, 16);
176
+ const buffer = createSpanBuffer(schema, createTestTraceRoot('test-trace'), DEFAULT_METADATA, 16);
181
177
 
182
178
  // Set scope value via buffer._scopeValues directly for test setup
183
179
  buffer._scopeValues = Object.freeze({ requestId: 'req-456' });
184
180
 
185
- const SpanLoggerClass = createSpanLoggerClass(schema);
186
- const logger = new SpanLoggerClass(buffer);
181
+ const ctx = createTestSpanContext(schema, buffer);
182
+ const logger = ctx._spanLogger;
187
183
 
188
- // Set _writeIndex to 8 so nextRow() makes it 9
189
- logger._writeIndex = 8;
184
+ // Set the shared writer state so the next append writes row 9
185
+ ctx._buffer._writeIndex = 9;
190
186
 
191
187
  // Log a message - does NOT write scoped attributes immediately
192
188
  logger.info('test message');
@@ -12,6 +12,7 @@
12
12
 
13
13
  import { describe, expect, it } from 'bun:test';
14
14
  import { createTestLogger } from '../../__tests__/test-helpers.js';
15
+ import { resolveEntryType } from '../../resolveMessage.js';
15
16
  import { S } from '../../schema/builder.js';
16
17
  import { defineLogSchema } from '../../schema/defineLogSchema.js';
17
18
  import {
@@ -56,31 +57,46 @@ describe('createSpanLoggerClass', () => {
56
57
  });
57
58
 
58
59
  describe('instance creation', () => {
59
- it('should create instance with buffer and createNextBuffer', () => {
60
+ it('should create instance with a state-backed buffer getter', () => {
60
61
  const schema = defineLogSchema({ userId: S.category() });
61
62
  const { buffer, logger } = createTestLogger(schema);
62
63
 
63
64
  expect(logger).toBeDefined();
64
- expect(logger._buffer).toBe(buffer);
65
+ expect(Reflect.get(Reflect.get(logger, '_state'), 'buffer')).toBe(buffer);
65
66
  expect(buffer._scopeValues).toBeDefined();
66
67
  });
67
68
 
68
- it('should start with _writeIndex = 1', () => {
69
+ it('should start at the first append row', () => {
69
70
  const schema = defineLogSchema({});
70
- const { logger } = createTestLogger(schema);
71
+ const { buffer } = createTestLogger(schema);
72
+
73
+ expect(buffer._writeIndex - 1).toBe(1);
74
+ });
75
+ it('owns only the shared WriterState reference', () => {
76
+ const schema = defineLogSchema({ userId: S.category() });
77
+ const { buffer, logger } = createTestLogger(schema);
78
+
79
+ expect(Reflect.ownKeys(logger)).toEqual(['_state']);
80
+ expect(Object.hasOwn(logger, '_buffer')).toBe(false);
81
+ expect(Object.hasOwn(logger, '_writeIndex')).toBe(false);
82
+ expect(Object.hasOwn(logger, '_spanBuffer')).toBe(false);
83
+ expect(Object.hasOwn(logger, '_traceRoot')).toBe(false);
84
+ expect(Object.hasOwn(logger, '_appendLogEntry')).toBe(false);
85
+ expect(Object.hasOwn(logger, '_physicalLayoutPlan')).toBe(false);
71
86
 
72
- expect(logger._writeIndex).toBe(1);
87
+ const state = Reflect.get(logger, '_state');
88
+ expect(Reflect.get(state, 'buffer')).toBe(buffer);
73
89
  });
74
90
  });
75
91
 
76
92
  describe('logging methods', () => {
77
- it('should increment _writeIndex on info()', () => {
93
+ it('should advance the active buffer write index on info()', () => {
78
94
  const schema = defineLogSchema({ userId: S.category() });
79
- const { logger } = createTestLogger(schema);
95
+ const { buffer, logger } = createTestLogger(schema);
80
96
 
81
- expect(logger._writeIndex).toBe(1);
97
+ expect(buffer._writeIndex - 1).toBe(1);
82
98
  logger.info('Test message');
83
- expect(logger._writeIndex).toBe(2);
99
+ expect(buffer._writeIndex - 1).toBe(2);
84
100
  });
85
101
 
86
102
  it('should write entry type for info()', () => {
@@ -88,7 +104,7 @@ describe('createSpanLoggerClass', () => {
88
104
  const { buffer, logger } = createTestLogger(schema);
89
105
 
90
106
  logger.info('Test message');
91
- expect(buffer.entry_type[2]).toBe(ENTRY_TYPE_INFO);
107
+ expect(resolveEntryType(buffer, 2)).toBe(ENTRY_TYPE_INFO);
92
108
  });
93
109
 
94
110
  it('should write entry type for debug()', () => {
@@ -96,7 +112,7 @@ describe('createSpanLoggerClass', () => {
96
112
  const { buffer, logger } = createTestLogger(schema);
97
113
 
98
114
  logger.debug('Debug message');
99
- expect(buffer.entry_type[2]).toBe(ENTRY_TYPE_DEBUG);
115
+ expect(resolveEntryType(buffer, 2)).toBe(ENTRY_TYPE_DEBUG);
100
116
  });
101
117
 
102
118
  it('should write entry type for warn()', () => {
@@ -104,7 +120,7 @@ describe('createSpanLoggerClass', () => {
104
120
  const { buffer, logger } = createTestLogger(schema);
105
121
 
106
122
  logger.warn('Warning message');
107
- expect(buffer.entry_type[2]).toBe(ENTRY_TYPE_WARN);
123
+ expect(resolveEntryType(buffer, 2)).toBe(ENTRY_TYPE_WARN);
108
124
  });
109
125
 
110
126
  it('should write entry type for error()', () => {
@@ -112,7 +128,7 @@ describe('createSpanLoggerClass', () => {
112
128
  const { buffer, logger } = createTestLogger(schema);
113
129
 
114
130
  logger.error('Error message');
115
- expect(buffer.entry_type[2]).toBe(ENTRY_TYPE_ERROR);
131
+ expect(resolveEntryType(buffer, 2)).toBe(ENTRY_TYPE_ERROR);
116
132
  });
117
133
 
118
134
  it('should write entry type for trace()', () => {
@@ -120,7 +136,7 @@ describe('createSpanLoggerClass', () => {
120
136
  const { buffer, logger } = createTestLogger(schema);
121
137
 
122
138
  logger.trace('Trace message');
123
- expect(buffer.entry_type[2]).toBe(ENTRY_TYPE_TRACE);
139
+ expect(resolveEntryType(buffer, 2)).toBe(ENTRY_TYPE_TRACE);
124
140
  });
125
141
 
126
142
  it('should write timestamp for log entries', () => {
@@ -150,10 +166,10 @@ describe('createSpanLoggerClass', () => {
150
166
  // FluentLogEntry includes logging methods for continued chaining
151
167
  logger.info('First').info('Second').warn('Third');
152
168
 
153
- expect(logger._writeIndex).toBe(4);
154
- expect(buffer.entry_type[2]).toBe(ENTRY_TYPE_INFO);
155
- expect(buffer.entry_type[3]).toBe(ENTRY_TYPE_INFO);
156
- expect(buffer.entry_type[4]).toBe(ENTRY_TYPE_WARN);
169
+ expect(buffer._writeIndex - 1).toBe(4);
170
+ expect(resolveEntryType(buffer, 2)).toBe(ENTRY_TYPE_INFO);
171
+ expect(resolveEntryType(buffer, 3)).toBe(ENTRY_TYPE_INFO);
172
+ expect(resolveEntryType(buffer, 4)).toBe(ENTRY_TYPE_WARN);
157
173
  });
158
174
  });
159
175