@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.
Files changed (276) hide show
  1. package/dist/allocator.wasm +0 -0
  2. package/dist/index.d.ts +1 -0
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +1 -0
  5. package/dist/lib/JsBufferStrategy.d.ts +4 -3
  6. package/dist/lib/JsBufferStrategy.d.ts.map +1 -1
  7. package/dist/lib/JsBufferStrategy.js +18 -11
  8. package/dist/lib/arrow/lease.d.ts +10 -0
  9. package/dist/lib/arrow/lease.d.ts.map +1 -0
  10. package/dist/lib/arrow/lease.js +33 -0
  11. package/dist/lib/arrow/utils.d.ts +3 -4
  12. package/dist/lib/arrow/utils.d.ts.map +1 -1
  13. package/dist/lib/arrow/utils.js +12 -13
  14. package/dist/lib/arrow/vocabularyDictionary.d.ts +21 -0
  15. package/dist/lib/arrow/vocabularyDictionary.d.ts.map +1 -0
  16. package/dist/lib/arrow/vocabularyDictionary.js +95 -0
  17. package/dist/lib/bufferStrategy.d.ts +3 -2
  18. package/dist/lib/bufferStrategy.d.ts.map +1 -1
  19. package/dist/lib/cloudflare/traceRows.d.ts.map +1 -1
  20. package/dist/lib/cloudflare/traceRows.js +3 -2
  21. package/dist/lib/codegen/evaluatorGenerator.d.ts.map +1 -1
  22. package/dist/lib/codegen/evaluatorGenerator.js +12 -11
  23. package/dist/lib/codegen/fixedPositionWriterGenerator.d.ts +44 -82
  24. package/dist/lib/codegen/fixedPositionWriterGenerator.d.ts.map +1 -1
  25. package/dist/lib/codegen/fixedPositionWriterGenerator.js +223 -162
  26. package/dist/lib/codegen/spanLoggerClosureMaterializer.d.ts +63 -0
  27. package/dist/lib/codegen/spanLoggerClosureMaterializer.d.ts.map +1 -0
  28. package/dist/lib/codegen/spanLoggerClosureMaterializer.js +447 -0
  29. package/dist/lib/codegen/spanLoggerGenerator.d.ts +36 -19
  30. package/dist/lib/codegen/spanLoggerGenerator.d.ts.map +1 -1
  31. package/dist/lib/codegen/spanLoggerGenerator.js +164 -158
  32. package/dist/lib/convertToArrow.d.ts +7 -2
  33. package/dist/lib/convertToArrow.d.ts.map +1 -1
  34. package/dist/lib/convertToArrow.js +499 -285
  35. package/dist/lib/defineOpContext.js +1 -1
  36. package/dist/lib/enumMetadata.d.ts +19 -0
  37. package/dist/lib/enumMetadata.d.ts.map +1 -0
  38. package/dist/lib/enumMetadata.js +86 -0
  39. package/dist/lib/flushScheduler.d.ts.map +1 -1
  40. package/dist/lib/flushScheduler.js +13 -4
  41. package/dist/lib/library.d.ts +16 -98
  42. package/dist/lib/library.d.ts.map +1 -1
  43. package/dist/lib/library.js +32 -525
  44. package/dist/lib/logBinding.d.ts +21 -27
  45. package/dist/lib/logBinding.d.ts.map +1 -1
  46. package/dist/lib/op.d.ts +30 -30
  47. package/dist/lib/op.d.ts.map +1 -1
  48. package/dist/lib/op.js +15 -22
  49. package/dist/lib/opContext/createOpGroup.d.ts +1 -1
  50. package/dist/lib/opContext/createOpGroup.d.ts.map +1 -1
  51. package/dist/lib/opContext/createOpGroup.js +22 -29
  52. package/dist/lib/opContext/defineOp.d.ts +4 -4
  53. package/dist/lib/opContext/defineOp.d.ts.map +1 -1
  54. package/dist/lib/opContext/defineOp.js +53 -10
  55. package/dist/lib/opContext/opGroupTypes.d.ts +2 -2
  56. package/dist/lib/opContext/opTypes.d.ts +1 -1
  57. package/dist/lib/opContext/opTypes.d.ts.map +1 -1
  58. package/dist/lib/opContext/spanContextTypes.d.ts +29 -14
  59. package/dist/lib/opContext/spanContextTypes.d.ts.map +1 -1
  60. package/dist/lib/opContext/types.d.ts +4 -4
  61. package/dist/lib/opContext/types.d.ts.map +1 -1
  62. package/dist/lib/physicalLayoutPlan.d.ts +89 -0
  63. package/dist/lib/physicalLayoutPlan.d.ts.map +1 -0
  64. package/dist/lib/physicalLayoutPlan.js +442 -0
  65. package/dist/lib/resolveMessage.d.ts +9 -0
  66. package/dist/lib/resolveMessage.d.ts.map +1 -0
  67. package/dist/lib/resolveMessage.js +63 -0
  68. package/dist/lib/result.d.ts +5 -7
  69. package/dist/lib/result.d.ts.map +1 -1
  70. package/dist/lib/result.js +19 -26
  71. package/dist/lib/runtimeHint.d.ts +35 -0
  72. package/dist/lib/runtimeHint.d.ts.map +1 -0
  73. package/dist/lib/runtimeHint.js +79 -0
  74. package/dist/lib/schema/types.d.ts +1 -1
  75. package/dist/lib/schema/types.d.ts.map +1 -1
  76. package/dist/lib/span-buffer/aot/v1.d.ts +2 -0
  77. package/dist/lib/span-buffer/aot/v1.d.ts.map +1 -0
  78. package/dist/lib/span-buffer/aot/v1.js +24 -0
  79. package/dist/lib/spanBuffer.d.ts +33 -4
  80. package/dist/lib/spanBuffer.d.ts.map +1 -1
  81. package/dist/lib/spanBuffer.js +583 -91
  82. package/dist/lib/spanBufferStats.d.ts +1 -1
  83. package/dist/lib/spanBufferStats.d.ts.map +1 -1
  84. package/dist/lib/spanContext.d.ts +27 -51
  85. package/dist/lib/spanContext.d.ts.map +1 -1
  86. package/dist/lib/spanContext.js +822 -344
  87. package/dist/lib/sqlite/sqlite-common.d.ts.map +1 -1
  88. package/dist/lib/sqlite/sqlite-common.js +20 -21
  89. package/dist/lib/testing/bun-harness.d.ts +8 -3
  90. package/dist/lib/testing/bun-harness.d.ts.map +1 -1
  91. package/dist/lib/testing/bun-harness.js +30 -18
  92. package/dist/lib/testing/extractFacts.d.ts +1 -1
  93. package/dist/lib/testing/extractFacts.d.ts.map +1 -1
  94. package/dist/lib/testing/extractFacts.js +55 -63
  95. package/dist/lib/testing/facts.d.ts +1 -1
  96. package/dist/lib/testing/facts.d.ts.map +1 -1
  97. package/dist/lib/testing/queryable-span.d.ts +1 -1
  98. package/dist/lib/testing/queryable-span.d.ts.map +1 -1
  99. package/dist/lib/testing/queryable-span.js +26 -28
  100. package/dist/lib/testing/span-query.d.ts.map +1 -1
  101. package/dist/lib/testing/span-query.js +19 -22
  102. package/dist/lib/testing/stdio-replay.d.ts.map +1 -1
  103. package/dist/lib/testing/stdio-replay.js +19 -8
  104. package/dist/lib/threadId.d.ts.map +1 -1
  105. package/dist/lib/threadId.js +6 -3
  106. package/dist/lib/traceRoot.d.ts +30 -8
  107. package/dist/lib/traceRoot.d.ts.map +1 -1
  108. package/dist/lib/traceRoot.es.d.ts +17 -15
  109. package/dist/lib/traceRoot.es.d.ts.map +1 -1
  110. package/dist/lib/traceRoot.es.js +68 -34
  111. package/dist/lib/traceRoot.js +11 -0
  112. package/dist/lib/traceRoot.node.d.ts +17 -19
  113. package/dist/lib/traceRoot.node.d.ts.map +1 -1
  114. package/dist/lib/traceRoot.node.js +66 -38
  115. package/dist/lib/traceTopology.d.ts +42 -0
  116. package/dist/lib/traceTopology.d.ts.map +1 -0
  117. package/dist/lib/traceTopology.js +260 -0
  118. package/dist/lib/tracer.d.ts +9 -5
  119. package/dist/lib/tracer.d.ts.map +1 -1
  120. package/dist/lib/tracer.js +65 -71
  121. package/dist/lib/tracers/ArrayQueueTracer.d.ts +1 -1
  122. package/dist/lib/tracers/ArrayQueueTracer.js +1 -1
  123. package/dist/lib/tracers/StdioTracer.d.ts.map +1 -1
  124. package/dist/lib/tracers/StdioTracer.js +15 -13
  125. package/dist/lib/tracers/TestTracer.d.ts +4 -6
  126. package/dist/lib/tracers/TestTracer.d.ts.map +1 -1
  127. package/dist/lib/tracers/TestTracer.js +6 -8
  128. package/dist/lib/types.d.ts +49 -32
  129. package/dist/lib/types.d.ts.map +1 -1
  130. package/dist/lib/vocabularyRegistry.d.ts +25 -0
  131. package/dist/lib/vocabularyRegistry.d.ts.map +1 -0
  132. package/dist/lib/vocabularyRegistry.js +372 -0
  133. package/dist/lib/wasm/WasmBufferStrategy.d.ts +6 -10
  134. package/dist/lib/wasm/WasmBufferStrategy.d.ts.map +1 -1
  135. package/dist/lib/wasm/WasmBufferStrategy.js +44 -37
  136. package/dist/lib/wasm/wasmAllocator.d.ts +27 -22
  137. package/dist/lib/wasm/wasmAllocator.d.ts.map +1 -1
  138. package/dist/lib/wasm/wasmAllocator.js +66 -44
  139. package/dist/lib/wasm/wasmPhysicalLayout.d.ts +67 -0
  140. package/dist/lib/wasm/wasmPhysicalLayout.d.ts.map +1 -0
  141. package/dist/lib/wasm/wasmPhysicalLayout.js +179 -0
  142. package/dist/lib/wasm/wasmSpanBuffer.d.ts +79 -31
  143. package/dist/lib/wasm/wasmSpanBuffer.d.ts.map +1 -1
  144. package/dist/lib/wasm/wasmSpanBuffer.js +442 -272
  145. package/dist/lib/wasm/wasmTraceRoot.d.ts +24 -22
  146. package/dist/lib/wasm/wasmTraceRoot.d.ts.map +1 -1
  147. package/dist/lib/wasm/wasmTraceRoot.js +110 -71
  148. package/dist/vocabulary/register/v1.d.ts +2 -0
  149. package/dist/vocabulary/register/v1.d.ts.map +1 -0
  150. package/dist/vocabulary/register/v1.js +1 -0
  151. package/dist/wasm.d.ts +5 -0
  152. package/dist/wasm.d.ts.map +1 -0
  153. package/dist/wasm.js +4 -0
  154. package/package.json +54 -6
  155. package/src/index.ts +1 -0
  156. package/src/lib/JsBufferStrategy.ts +27 -9
  157. package/src/lib/__tests__/arrow-builder-integration/arrow-conversion.test.ts +335 -37
  158. package/src/lib/__tests__/arrow-builder-integration/binary-arrow-conversion.test.ts +97 -26
  159. package/src/lib/__tests__/arrow-builder-integration/binary-comparison.test.ts +75 -15
  160. package/src/lib/__tests__/arrow-builder-integration/binary-format-compliance.test.ts +30 -6
  161. package/src/lib/__tests__/arrow-builder-integration/buffer-chaining.test.ts +18 -21
  162. package/src/lib/__tests__/arrow-builder-integration/foundation.test.ts +5 -2
  163. package/src/lib/__tests__/arrow-builder-integration/integration.test.ts +25 -7
  164. package/src/lib/__tests__/arrow-builder-integration/lazy-columns.test.ts +3 -2
  165. package/src/lib/__tests__/buffer-overflow.test.ts +24 -18
  166. package/src/lib/__tests__/capability-span-context.test.ts +505 -0
  167. package/src/lib/__tests__/capacity-tuning.test.ts +5 -3
  168. package/src/lib/__tests__/eager-columns.test.ts +345 -0
  169. package/src/lib/__tests__/enum-metadata-aot.test.ts +153 -0
  170. package/src/lib/__tests__/enum-metadata.test.ts +177 -0
  171. package/src/lib/__tests__/fixtures/empty-vocabulary-runtime.fixture.ts +15 -0
  172. package/src/lib/__tests__/flushScheduler.test.ts +5 -1
  173. package/src/lib/__tests__/identity-view.property.test.ts +179 -0
  174. package/src/lib/__tests__/library.test.ts +19 -235
  175. package/src/lib/__tests__/message-buffer-families.test.ts +878 -0
  176. package/src/lib/__tests__/nested-library-tasks.test.ts +14 -15
  177. package/src/lib/__tests__/op-metadata.test.ts +1 -1
  178. package/src/lib/__tests__/op-type-safety.test.ts +5 -16
  179. package/src/lib/__tests__/physical-layout-plan.test.ts +333 -0
  180. package/src/lib/__tests__/remap-descriptor-integration.test.ts +381 -0
  181. package/src/lib/__tests__/root-context-construction.test.ts +414 -0
  182. package/src/lib/__tests__/span-auto-runtime.test.ts +386 -0
  183. package/src/lib/__tests__/span-buffer-segment-stats.test.ts +221 -0
  184. package/src/lib/__tests__/span-lifecycle.test.ts +53 -25
  185. package/src/lib/__tests__/spanbuffer-materializer-parity.test.ts +266 -0
  186. package/src/lib/__tests__/sync-async-trace.test.ts +24 -23
  187. package/src/lib/__tests__/tag-writer-aot.test.ts +214 -0
  188. package/src/lib/__tests__/test-helpers.ts +67 -12
  189. package/src/lib/__tests__/threadId.test.ts +62 -0
  190. package/src/lib/__tests__/timestamp.test.ts +221 -93
  191. package/src/lib/__tests__/traceTopology.property.test.ts +383 -0
  192. package/src/lib/__tests__/type-narrowing.test.ts +63 -0
  193. package/src/lib/__tests__/vocabulary-dense-decoding.test.ts +405 -0
  194. package/src/lib/__tests__/vocabularyRegistry.test.ts +313 -0
  195. package/src/lib/arrow/lease.ts +43 -0
  196. package/src/lib/arrow/utils.ts +10 -14
  197. package/src/lib/arrow/vocabularyDictionary.ts +123 -0
  198. package/src/lib/bufferStrategy.ts +9 -1
  199. package/src/lib/cloudflare/traceRows.ts +3 -2
  200. package/src/lib/codegen/__tests__/evaluatorGenerator.test.ts +21 -141
  201. package/src/lib/codegen/__tests__/fixedPositionWriter-parity.test.ts +273 -0
  202. package/src/lib/codegen/__tests__/fixedPositionWriter-uint64.test.ts +61 -34
  203. package/src/lib/codegen/__tests__/nullBitmap.test.ts +33 -37
  204. package/src/lib/codegen/__tests__/spanLoggerGenerator.test.ts +34 -18
  205. package/src/lib/codegen/__tests__/spanLoggerMaterializerParity.test.ts +503 -0
  206. package/src/lib/codegen/evaluatorGenerator.ts +18 -13
  207. package/src/lib/codegen/fixedPositionWriterGenerator.ts +329 -245
  208. package/src/lib/codegen/spanLoggerClosureMaterializer.ts +598 -0
  209. package/src/lib/codegen/spanLoggerGenerator.ts +241 -177
  210. package/src/lib/convertToArrow.ts +598 -311
  211. package/src/lib/defineOpContext.ts +1 -1
  212. package/src/lib/enumMetadata.ts +121 -0
  213. package/src/lib/flushScheduler.ts +11 -5
  214. package/src/lib/library.ts +37 -595
  215. package/src/lib/logBinding.ts +21 -27
  216. package/src/lib/op.ts +75 -18
  217. package/src/lib/opContext/__tests__/retry.test.ts +27 -21
  218. package/src/lib/opContext/createOpGroup.ts +33 -31
  219. package/src/lib/opContext/defineOp.ts +88 -11
  220. package/src/lib/opContext/opGroupTypes.ts +2 -2
  221. package/src/lib/opContext/opTypes.ts +1 -1
  222. package/src/lib/opContext/spanContextTypes.ts +98 -17
  223. package/src/lib/opContext/types.ts +7 -3
  224. package/src/lib/physicalLayoutPlan.ts +598 -0
  225. package/src/lib/resolveMessage.ts +67 -0
  226. package/src/lib/result.ts +20 -33
  227. package/src/lib/runtimeHint.ts +98 -0
  228. package/src/lib/schema/__tests__/featureFlags.test.ts +2 -1
  229. package/src/lib/schema/builder.ts +1 -1
  230. package/src/lib/schema/types.ts +1 -1
  231. package/src/lib/span-buffer/aot/v1.ts +26 -0
  232. package/src/lib/spanBuffer.ts +658 -92
  233. package/src/lib/spanBufferStats.ts +1 -1
  234. package/src/lib/spanContext.ts +1350 -861
  235. package/src/lib/sqlite/sqlite-common.ts +20 -31
  236. package/src/lib/testing/__tests__/topology-traversal.test.ts +174 -0
  237. package/src/lib/testing/__tests__/vitest-harness.test.ts +2 -1
  238. package/src/lib/testing/bun-harness.ts +94 -43
  239. package/src/lib/testing/extractFacts.ts +64 -78
  240. package/src/lib/testing/facts.ts +1 -1
  241. package/src/lib/testing/queryable-span.ts +23 -30
  242. package/src/lib/testing/span-query.ts +16 -20
  243. package/src/lib/testing/stdio-replay.ts +25 -8
  244. package/src/lib/testing/vitest-harness.ts +1 -1
  245. package/src/lib/threadId.ts +6 -3
  246. package/src/lib/traceRoot.es.ts +77 -42
  247. package/src/lib/traceRoot.node.ts +75 -46
  248. package/src/lib/traceRoot.ts +41 -14
  249. package/src/lib/traceTopology.ts +279 -0
  250. package/src/lib/tracer.ts +109 -98
  251. package/src/lib/tracers/ArrayQueueTracer.ts +1 -1
  252. package/src/lib/tracers/StdioTracer.ts +15 -13
  253. package/src/lib/tracers/TestTracer.ts +6 -8
  254. package/src/lib/tracers/__tests__/ArrayQueueTracer.test.ts +15 -10
  255. package/src/lib/tracers/__tests__/TestTracer.test.ts +23 -13
  256. package/src/lib/types.ts +64 -33
  257. package/src/lib/vocabularyRegistry.ts +439 -0
  258. package/src/lib/wasm/WasmBufferStrategy.ts +56 -48
  259. package/src/lib/wasm/__tests__/WasmBufferStrategy.test.ts +215 -11
  260. package/src/lib/wasm/__tests__/allocatorFreeBlockClamp.test.ts +86 -0
  261. package/src/lib/wasm/__tests__/wasm-identity-view.test.ts +311 -0
  262. package/src/lib/wasm/__tests__/wasm-integration.test.ts +417 -44
  263. package/src/lib/wasm/__tests__/wasm-message-buffer-families.test.ts +588 -0
  264. package/src/lib/wasm/__tests__/wasmAllocator.test.ts +100 -668
  265. package/src/lib/wasm/__tests__/wasmSpanBuffer.test.ts +419 -63
  266. package/src/lib/wasm/__tests__/wasmTraceRoot.test.ts +24 -29
  267. package/src/lib/wasm/__tests__/wasmTracer.test.ts.disabled +2 -2
  268. package/src/lib/wasm/wasmAllocator.ts +131 -96
  269. package/src/lib/wasm/wasmPhysicalLayout.ts +309 -0
  270. package/src/lib/wasm/wasmSpanBuffer.ts +597 -341
  271. package/src/lib/wasm/wasmTraceRoot.ts +140 -78
  272. package/src/vocabulary/register/v1.ts +1 -0
  273. package/src/wasm.ts +19 -0
  274. package/src/lib/__tests__/remapped-buffer-view-integration.test.ts +0 -319
  275. package/src/lib/__tests__/remapped-buffer-view.test.ts +0 -635
  276. package/src/lib/wasm/allocator.zig +0 -948
@@ -8,7 +8,14 @@
8
8
  import { describe, expect, it } from 'bun:test';
9
9
  import { decode } from '@msgpack/msgpack';
10
10
  import { createColumnWriter } from '@smoothbricks/arrow-builder';
11
- import { convertSpanTreeToArrowTable, convertToArrowTable, createSpanBuffer, S } from '@smoothbricks/lmao';
11
+ import {
12
+ convertSpanTreeToArrowTable,
13
+ convertToArrowTable,
14
+ createChildSpanBuffer,
15
+ createSpanBuffer,
16
+ getSpanBufferClass,
17
+ S,
18
+ } from '@smoothbricks/lmao';
12
19
  import typia from 'typia';
13
20
  import { ENTRY_TYPE_INFO, ENTRY_TYPE_SPAN_START } from '../../schema/systemSchema.js';
14
21
  import { invokeWriterMethod, nextWriterRow, requireBinaryCell, requireColumn } from '../arrow-test-helpers.js';
@@ -29,13 +36,21 @@ describe('Binary Arrow Conversion', () => {
29
36
  const row0 = invokeWriterMethod(nextWriterRow(writer), 'payload', { action: 'click', x: 100, y: 200 });
30
37
  invokeWriterMethod(row0, 'requestId', 'req-1');
31
38
  buffer.timestamp[0] = 1000n;
32
- buffer.entry_type[0] = ENTRY_TYPE_SPAN_START;
39
+ {
40
+ const entryTypes = buffer.entry_type;
41
+ if (entryTypes === undefined) throw new Error('Expected split entry-type lane');
42
+ entryTypes[0] = ENTRY_TYPE_SPAN_START;
43
+ }
33
44
 
34
45
  // Write row with a string payload
35
46
  const row1 = invokeWriterMethod(nextWriterRow(writer), 'payload', 'simple-string');
36
47
  invokeWriterMethod(row1, 'requestId', 'req-2');
37
48
  buffer.timestamp[1] = 2000n;
38
- buffer.entry_type[1] = ENTRY_TYPE_INFO;
49
+ {
50
+ const entryTypes = buffer.entry_type;
51
+ if (entryTypes === undefined) throw new Error('Expected split entry-type lane');
52
+ entryTypes[1] = ENTRY_TYPE_INFO;
53
+ }
39
54
 
40
55
  buffer._writeIndex = 2;
41
56
 
@@ -82,7 +97,11 @@ describe('Binary Arrow Conversion', () => {
82
97
  };
83
98
  invokeWriterMethod(nextWriterRow(writer), 'request', requestData);
84
99
  buffer.timestamp[0] = 1000n;
85
- buffer.entry_type[0] = ENTRY_TYPE_SPAN_START;
100
+ {
101
+ const entryTypes = buffer.entry_type;
102
+ if (entryTypes === undefined) throw new Error('Expected split entry-type lane');
103
+ entryTypes[0] = ENTRY_TYPE_SPAN_START;
104
+ }
86
105
  buffer._writeIndex = 1;
87
106
 
88
107
  const table = convertToArrowTable(buffer);
@@ -108,7 +127,11 @@ describe('Binary Arrow Conversion', () => {
108
127
  const rawBytes = new Uint8Array([0xde, 0xad, 0xbe, 0xef]);
109
128
  invokeWriterMethod(nextWriterRow(writer), 'rawData', rawBytes);
110
129
  buffer.timestamp[0] = 1000n;
111
- buffer.entry_type[0] = ENTRY_TYPE_SPAN_START;
130
+ {
131
+ const entryTypes = buffer.entry_type;
132
+ if (entryTypes === undefined) throw new Error('Expected split entry-type lane');
133
+ entryTypes[0] = ENTRY_TYPE_SPAN_START;
134
+ }
112
135
  buffer._writeIndex = 1;
113
136
 
114
137
  const table = convertToArrowTable(buffer);
@@ -133,12 +156,20 @@ describe('Binary Arrow Conversion', () => {
133
156
  const firstRow = invokeWriterMethod(nextWriterRow(writer), 'payload', { key: 'value' });
134
157
  invokeWriterMethod(firstRow, 'requestId', 'req-1');
135
158
  buffer.timestamp[0] = 1000n;
136
- buffer.entry_type[0] = ENTRY_TYPE_SPAN_START;
159
+ {
160
+ const entryTypes = buffer.entry_type;
161
+ if (entryTypes === undefined) throw new Error('Expected split entry-type lane');
162
+ entryTypes[0] = ENTRY_TYPE_SPAN_START;
163
+ }
137
164
 
138
165
  // Row 1: payload NOT set (null)
139
166
  invokeWriterMethod(nextWriterRow(writer), 'requestId', 'req-2');
140
167
  buffer.timestamp[1] = 2000n;
141
- buffer.entry_type[1] = ENTRY_TYPE_INFO;
168
+ {
169
+ const entryTypes = buffer.entry_type;
170
+ if (entryTypes === undefined) throw new Error('Expected split entry-type lane');
171
+ entryTypes[1] = ENTRY_TYPE_INFO;
172
+ }
142
173
 
143
174
  buffer._writeIndex = 2;
144
175
 
@@ -175,7 +206,11 @@ describe('Binary Arrow Conversion', () => {
175
206
  'GET',
176
207
  );
177
208
  buffer.timestamp[0] = 1000n;
178
- buffer.entry_type[0] = ENTRY_TYPE_SPAN_START;
209
+ {
210
+ const entryTypes = buffer.entry_type;
211
+ if (entryTypes === undefined) throw new Error('Expected split entry-type lane');
212
+ entryTypes[0] = ENTRY_TYPE_SPAN_START;
213
+ }
179
214
  buffer._writeIndex = 1;
180
215
 
181
216
  const table = convertToArrowTable(buffer);
@@ -204,23 +239,32 @@ describe('Binary Arrow Conversion', () => {
204
239
  const rootRow = invokeWriterMethod(nextWriterRow(rootWriter), 'payload', { level: 'root', data: [1, 2] });
205
240
  invokeWriterMethod(rootRow, 'userId', 'user-root');
206
241
  rootBuffer.timestamp[0] = 1000n;
207
- rootBuffer.entry_type[0] = ENTRY_TYPE_SPAN_START;
242
+ {
243
+ const entryTypes = rootBuffer.entry_type;
244
+ if (entryTypes === undefined) throw new Error('Expected split entry-type lane');
245
+ entryTypes[0] = ENTRY_TYPE_SPAN_START;
246
+ }
208
247
  rootBuffer._writeIndex = 1;
209
248
 
210
- // Create child buffer
211
- const childBuffer = createSpanBuffer(schema, createTestTraceRoot('test-trace'), createTestOpMetadata());
249
+ // Create and register child buffer in the root trace topology.
250
+ const childBuffer = createChildSpanBuffer(
251
+ rootBuffer,
252
+ getSpanBufferClass(schema),
253
+ createTestOpMetadata(),
254
+ createTestOpMetadata(),
255
+ );
212
256
  const childWriter = createColumnWriter(schema, childBuffer);
213
257
 
214
258
  const childRow = invokeWriterMethod(nextWriterRow(childWriter), 'payload', { level: 'child', nested: { a: 1 } });
215
259
  invokeWriterMethod(childRow, 'userId', 'user-child');
216
260
  childBuffer.timestamp[0] = 2000n;
217
- childBuffer.entry_type[0] = ENTRY_TYPE_SPAN_START;
261
+ {
262
+ const entryTypes = childBuffer.entry_type;
263
+ if (entryTypes === undefined) throw new Error('Expected split entry-type lane');
264
+ entryTypes[0] = ENTRY_TYPE_SPAN_START;
265
+ }
218
266
  childBuffer._writeIndex = 1;
219
267
 
220
- // Link parent-child
221
- rootBuffer._children.push(childBuffer);
222
- childBuffer._parent = rootBuffer;
223
-
224
268
  const table = convertSpanTreeToArrowTable(rootBuffer);
225
269
  const payloadCol = requireColumn(table, 'payload');
226
270
  expect(payloadCol).toBeDefined();
@@ -251,7 +295,11 @@ describe('Binary Arrow Conversion', () => {
251
295
 
252
296
  invokeWriterMethod(nextWriterRow(writer), 'payload', obj);
253
297
  buffer.timestamp[0] = 1000n;
254
- buffer.entry_type[0] = ENTRY_TYPE_SPAN_START;
298
+ {
299
+ const entryTypes = buffer.entry_type;
300
+ if (entryTypes === undefined) throw new Error('Expected split entry-type lane');
301
+ entryTypes[0] = ENTRY_TYPE_SPAN_START;
302
+ }
255
303
  buffer._writeIndex = 1;
256
304
 
257
305
  // Mutate AFTER tagging -- Object.freeze should prevent this from affecting the stored reference
@@ -284,32 +332,51 @@ describe('Binary Arrow Conversion', () => {
284
332
  const rootRow0 = invokeWriterMethod(nextWriterRow(rootWriter), 'payload', { req: 1 });
285
333
  invokeWriterMethod(invokeWriterMethod(rootRow0, 'userId', 'user-A'), 'action', 'click');
286
334
  rootBuffer.timestamp[0] = 1000n;
287
- rootBuffer.entry_type[0] = ENTRY_TYPE_SPAN_START;
335
+ {
336
+ const entryTypes = rootBuffer.entry_type;
337
+ if (entryTypes === undefined) throw new Error('Expected split entry-type lane');
338
+ entryTypes[0] = ENTRY_TYPE_SPAN_START;
339
+ }
288
340
 
289
341
  const rootRow1 = invokeWriterMethod(nextWriterRow(rootWriter), 'payload', { req: 2 });
290
342
  invokeWriterMethod(invokeWriterMethod(rootRow1, 'userId', 'user-A'), 'action', 'scroll');
291
343
  rootBuffer.timestamp[1] = 2000n;
292
- rootBuffer.entry_type[1] = ENTRY_TYPE_INFO;
344
+ {
345
+ const entryTypes = rootBuffer.entry_type;
346
+ if (entryTypes === undefined) throw new Error('Expected split entry-type lane');
347
+ entryTypes[1] = ENTRY_TYPE_INFO;
348
+ }
293
349
 
294
350
  const rootRow2 = invokeWriterMethod(nextWriterRow(rootWriter), 'payload', { req: 3 });
295
351
  invokeWriterMethod(invokeWriterMethod(rootRow2, 'userId', 'user-B'), 'action', 'click');
296
352
  rootBuffer.timestamp[2] = 3000n;
297
- rootBuffer.entry_type[2] = ENTRY_TYPE_INFO;
353
+ {
354
+ const entryTypes = rootBuffer.entry_type;
355
+ if (entryTypes === undefined) throw new Error('Expected split entry-type lane');
356
+ entryTypes[2] = ENTRY_TYPE_INFO;
357
+ }
298
358
 
299
359
  rootBuffer._writeIndex = 3;
300
360
 
301
- // Child buffer with overlapping category values
302
- const childBuffer = createSpanBuffer(schema, createTestTraceRoot('test-trace'), createTestOpMetadata());
361
+ // Child buffer with overlapping category values, registered in the root topology.
362
+ const childBuffer = createChildSpanBuffer(
363
+ rootBuffer,
364
+ getSpanBufferClass(schema),
365
+ createTestOpMetadata(),
366
+ createTestOpMetadata(),
367
+ );
303
368
  const childWriter = createColumnWriter(schema, childBuffer);
304
369
 
305
370
  const childDataRow = invokeWriterMethod(nextWriterRow(childWriter), 'payload', { req: 4 });
306
371
  invokeWriterMethod(invokeWriterMethod(childDataRow, 'userId', 'user-B'), 'action', 'submit');
307
372
  childBuffer.timestamp[0] = 4000n;
308
- childBuffer.entry_type[0] = ENTRY_TYPE_SPAN_START;
373
+ {
374
+ const entryTypes = childBuffer.entry_type;
375
+ if (entryTypes === undefined) throw new Error('Expected split entry-type lane');
376
+ entryTypes[0] = ENTRY_TYPE_SPAN_START;
377
+ }
309
378
 
310
379
  childBuffer._writeIndex = 1;
311
- rootBuffer._children.push(childBuffer);
312
- childBuffer._parent = rootBuffer;
313
380
 
314
381
  // convertSpanTreeToArrowTable uses the shared-dict path (buildSortedCategoryDictionary)
315
382
  const table = convertSpanTreeToArrowTable(rootBuffer);
@@ -370,7 +437,11 @@ describe('Binary Arrow Conversion', () => {
370
437
 
371
438
  invokeWriterMethod(nextWriterRow(writer), 'payload', testValue);
372
439
  buffer.timestamp[0] = 1000n;
373
- buffer.entry_type[0] = ENTRY_TYPE_SPAN_START;
440
+ {
441
+ const entryTypes = buffer.entry_type;
442
+ if (entryTypes === undefined) throw new Error('Expected split entry-type lane');
443
+ entryTypes[0] = ENTRY_TYPE_SPAN_START;
444
+ }
374
445
  buffer._writeIndex = 1;
375
446
 
376
447
  const table = convertToArrowTable(buffer);
@@ -123,7 +123,11 @@ describe('Arrow IPC Round-Trip', () => {
123
123
  for (const value of testValues) {
124
124
  const idx = buffer._writeIndex;
125
125
  buffer.timestamp[idx] = 1000n;
126
- buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
126
+ {
127
+ const entryTypes = buffer.entry_type;
128
+ if (entryTypes === undefined) throw new Error('Expected split entry-type lane');
129
+ entryTypes[idx] = ENTRY_TYPE_SPAN_START;
130
+ }
127
131
  buffer.value(idx, value);
128
132
  buffer._writeIndex++;
129
133
  }
@@ -158,7 +162,11 @@ describe('Arrow IPC Round-Trip', () => {
158
162
  for (const value of testValues) {
159
163
  const idx = buffer._writeIndex;
160
164
  buffer.timestamp[idx] = 1000n;
161
- buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
165
+ {
166
+ const entryTypes = buffer.entry_type;
167
+ if (entryTypes === undefined) throw new Error('Expected split entry-type lane');
168
+ entryTypes[idx] = ENTRY_TYPE_SPAN_START;
169
+ }
162
170
  buffer.flag(idx, value);
163
171
  buffer._writeIndex++;
164
172
  }
@@ -184,7 +192,11 @@ describe('Arrow IPC Round-Trip', () => {
184
192
  for (const enumIdx of testIndices) {
185
193
  const idx = buffer._writeIndex;
186
194
  buffer.timestamp[idx] = 1000n;
187
- buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
195
+ {
196
+ const entryTypes = buffer.entry_type;
197
+ if (entryTypes === undefined) throw new Error('Expected split entry-type lane');
198
+ entryTypes[idx] = ENTRY_TYPE_SPAN_START;
199
+ }
188
200
  callBufferWriter(buffer, 'status', idx, enumIdx);
189
201
  buffer._writeIndex++;
190
202
  }
@@ -207,7 +219,11 @@ describe('Arrow IPC Round-Trip', () => {
207
219
  for (const userId of testValues) {
208
220
  const idx = buffer._writeIndex;
209
221
  buffer.timestamp[idx] = 1000n;
210
- buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
222
+ {
223
+ const entryTypes = buffer.entry_type;
224
+ if (entryTypes === undefined) throw new Error('Expected split entry-type lane');
225
+ entryTypes[idx] = ENTRY_TYPE_SPAN_START;
226
+ }
211
227
  buffer.userId(idx, userId);
212
228
  buffer._writeIndex++;
213
229
  }
@@ -233,7 +249,11 @@ describe('Arrow IPC Round-Trip', () => {
233
249
  for (const value of testValues) {
234
250
  const idx = buffer._writeIndex;
235
251
  buffer.timestamp[idx] = 1000n;
236
- buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
252
+ {
253
+ const entryTypes = buffer.entry_type;
254
+ if (entryTypes === undefined) throw new Error('Expected split entry-type lane');
255
+ entryTypes[idx] = ENTRY_TYPE_SPAN_START;
256
+ }
237
257
  buffer.userMessage(idx, value);
238
258
  buffer._writeIndex++;
239
259
  }
@@ -257,7 +277,11 @@ describe('Arrow IPC Round-Trip', () => {
257
277
  for (const value of testValues) {
258
278
  const idx = buffer._writeIndex;
259
279
  buffer.timestamp[idx] = 1000n;
260
- buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
280
+ {
281
+ const entryTypes = buffer.entry_type;
282
+ if (entryTypes === undefined) throw new Error('Expected split entry-type lane');
283
+ entryTypes[idx] = ENTRY_TYPE_SPAN_START;
284
+ }
261
285
  if (value !== null) {
262
286
  buffer.value(idx, value);
263
287
  } else {
@@ -298,7 +322,11 @@ describe('Arrow IPC Round-Trip', () => {
298
322
  for (const row of testData) {
299
323
  const idx = buffer._writeIndex;
300
324
  buffer.timestamp[idx] = 1000n;
301
- buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
325
+ {
326
+ const entryTypes = buffer.entry_type;
327
+ if (entryTypes === undefined) throw new Error('Expected split entry-type lane');
328
+ entryTypes[idx] = ENTRY_TYPE_SPAN_START;
329
+ }
302
330
 
303
331
  if (row.count !== null) {
304
332
  buffer.count(idx, row.count);
@@ -351,7 +379,11 @@ describe('Arrow IPC Round-Trip', () => {
351
379
  for (let i = 0; i < 3; i++) {
352
380
  const idx = buffer._writeIndex;
353
381
  buffer.timestamp[idx] = timestamps[i];
354
- buffer.entry_type[idx] = i;
382
+ {
383
+ const entryTypes = buffer.entry_type;
384
+ if (entryTypes === undefined) throw new Error('Expected split entry-type lane');
385
+ entryTypes[idx] = i;
386
+ }
355
387
  buffer._writeIndex++;
356
388
  }
357
389
 
@@ -407,7 +439,11 @@ describe('Arrow IPC Round-Trip', () => {
407
439
 
408
440
  const idx = buffer._writeIndex;
409
441
  buffer.timestamp[idx] = 1000n;
410
- buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
442
+ {
443
+ const entryTypes = buffer.entry_type;
444
+ if (entryTypes === undefined) throw new Error('Expected split entry-type lane');
445
+ entryTypes[idx] = ENTRY_TYPE_SPAN_START;
446
+ }
411
447
  buffer._writeIndex++;
412
448
 
413
449
  const table = convertToArrowTable(buffer);
@@ -449,7 +485,11 @@ describe('Arrow IPC Round-Trip', () => {
449
485
 
450
486
  const idx = buffer._writeIndex;
451
487
  buffer.timestamp[idx] = 1000n;
452
- buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
488
+ {
489
+ const entryTypes = buffer.entry_type;
490
+ if (entryTypes === undefined) throw new Error('Expected split entry-type lane');
491
+ entryTypes[idx] = ENTRY_TYPE_SPAN_START;
492
+ }
453
493
  buffer.category(idx, 'cat1');
454
494
  buffer.text(idx, 'text1');
455
495
  callBufferWriter(buffer, 'status', idx, 0);
@@ -482,7 +522,11 @@ describe('Arrow IPC Round-Trip', () => {
482
522
  for (const value of values) {
483
523
  const idx = buffer._writeIndex;
484
524
  buffer.timestamp[idx] = 1000n;
485
- buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
525
+ {
526
+ const entryTypes = buffer.entry_type;
527
+ if (entryTypes === undefined) throw new Error('Expected split entry-type lane');
528
+ entryTypes[idx] = ENTRY_TYPE_SPAN_START;
529
+ }
486
530
  if (value !== null) {
487
531
  buffer.value(idx, value);
488
532
  } else {
@@ -526,7 +570,11 @@ describe('Arrow IPC Round-Trip', () => {
526
570
  for (const value of values) {
527
571
  const idx = buffer._writeIndex;
528
572
  buffer.timestamp[idx] = 1000n;
529
- buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
573
+ {
574
+ const entryTypes = buffer.entry_type;
575
+ if (entryTypes === undefined) throw new Error('Expected split entry-type lane');
576
+ entryTypes[idx] = ENTRY_TYPE_SPAN_START;
577
+ }
530
578
  if (value !== null) {
531
579
  buffer.value(idx, value);
532
580
  } else {
@@ -566,7 +614,11 @@ describe('Arrow IPC Round-Trip', () => {
566
614
  for (const value of values) {
567
615
  const idx = buffer._writeIndex;
568
616
  buffer.timestamp[idx] = 1000n;
569
- buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
617
+ {
618
+ const entryTypes = buffer.entry_type;
619
+ if (entryTypes === undefined) throw new Error('Expected split entry-type lane');
620
+ entryTypes[idx] = ENTRY_TYPE_SPAN_START;
621
+ }
570
622
  buffer.value(idx, value);
571
623
  buffer._writeIndex++;
572
624
  }
@@ -599,7 +651,11 @@ describe('Arrow IPC Round-Trip', () => {
599
651
  for (const category of testValues) {
600
652
  const idx = buffer._writeIndex;
601
653
  buffer.timestamp[idx] = 1000n;
602
- buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
654
+ {
655
+ const entryTypes = buffer.entry_type;
656
+ if (entryTypes === undefined) throw new Error('Expected split entry-type lane');
657
+ entryTypes[idx] = ENTRY_TYPE_SPAN_START;
658
+ }
603
659
  buffer.category(idx, category);
604
660
  buffer._writeIndex++;
605
661
  }
@@ -622,7 +678,11 @@ describe('Arrow IPC Round-Trip', () => {
622
678
  for (let i = 0; i < 100; i++) {
623
679
  const idx = buffer._writeIndex;
624
680
  buffer.timestamp[idx] = 1000n;
625
- buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
681
+ {
682
+ const entryTypes = buffer.entry_type;
683
+ if (entryTypes === undefined) throw new Error('Expected split entry-type lane');
684
+ entryTypes[idx] = ENTRY_TYPE_SPAN_START;
685
+ }
626
686
  buffer.userId(idx, testValue);
627
687
  buffer._writeIndex++;
628
688
  }
@@ -48,7 +48,11 @@ describe('Arrow Binary Format Compliance', () => {
48
48
  // Donbuffer._opMetadata = DEFAULT_METADATA;
49
49
 
50
50
  // Writebuffer.timestamp[0] = BigInt(Date.now()) * 1000000n;
51
- buffer.entry_type[0] = ENTRY_TYPE_SPAN_START;
51
+ {
52
+ const entryTypes = buffer.entry_type;
53
+ if (entryTypes === undefined) throw new Error('Expected split entry-type lane');
54
+ entryTypes[0] = ENTRY_TYPE_SPAN_START;
55
+ }
52
56
  buffer.numberValue(0, 42);
53
57
  buffer._writeIndex = 1;
54
58
 
@@ -74,7 +78,11 @@ describe('Arrow Binary Format Compliance', () => {
74
78
  // Write test data using generated methods
75
79
  const testValue = 0x12345678;
76
80
  buffer.timestamp[0] = BigInt(Date.now()) * 1000000n;
77
- buffer.entry_type[0] = ENTRY_TYPE_SPAN_START;
81
+ {
82
+ const entryTypes = buffer.entry_type;
83
+ if (entryTypes === undefined) throw new Error('Expected split entry-type lane');
84
+ entryTypes[0] = ENTRY_TYPE_SPAN_START;
85
+ }
78
86
  buffer.uint32Value(0, testValue);
79
87
  buffer._writeIndex = 1;
80
88
 
@@ -115,7 +123,11 @@ describe('Arrow Binary Format Compliance', () => {
115
123
  for (let i = 0; i < testData.length; i++) {
116
124
  const value = testData[i];
117
125
  buffer.timestamp[i] = BigInt(Date.now()) * 1000000n;
118
- buffer.entry_type[i] = ENTRY_TYPE_SPAN_START;
126
+ {
127
+ const entryTypes = buffer.entry_type;
128
+ if (entryTypes === undefined) throw new Error('Expected split entry-type lane');
129
+ entryTypes[i] = ENTRY_TYPE_SPAN_START;
130
+ }
119
131
 
120
132
  if (value === null) {
121
133
  // Don't call the method for null values, just leave as default (null)
@@ -166,7 +178,11 @@ describe('Arrow Binary Format Compliance', () => {
166
178
 
167
179
  for (let i = 0; i < testValues.length; i++) {
168
180
  buffer.timestamp[i] = BigInt(Date.now()) * 1000000n;
169
- buffer.entry_type[i] = ENTRY_TYPE_SPAN_START;
181
+ {
182
+ const entryTypes = buffer.entry_type;
183
+ if (entryTypes === undefined) throw new Error('Expected split entry-type lane');
184
+ entryTypes[i] = ENTRY_TYPE_SPAN_START;
185
+ }
170
186
  buffer.enumValue(i, testValues[i]);
171
187
  }
172
188
  buffer._writeIndex = testValues.length;
@@ -202,7 +218,11 @@ describe('Arrow Binary Format Compliance', () => {
202
218
 
203
219
  for (let i = 0; i < testValues.length; i++) {
204
220
  buffer.timestamp[i] = BigInt(Date.now()) * 1000000n;
205
- buffer.entry_type[i] = ENTRY_TYPE_SPAN_START;
221
+ {
222
+ const entryTypes = buffer.entry_type;
223
+ if (entryTypes === undefined) throw new Error('Expected split entry-type lane');
224
+ entryTypes[i] = ENTRY_TYPE_SPAN_START;
225
+ }
206
226
  buffer.textValue(i, testValues[i]);
207
227
  }
208
228
  buffer._writeIndex = testValues.length;
@@ -260,7 +280,11 @@ describe('Arrow Binary Format Compliance', () => {
260
280
 
261
281
  for (let i = 0; i < testValues.length; i++) {
262
282
  buffer.timestamp[i] = BigInt(Date.now()) * 1000000n;
263
- buffer.entry_type[i] = ENTRY_TYPE_SPAN_START;
283
+ {
284
+ const entryTypes = buffer.entry_type;
285
+ if (entryTypes === undefined) throw new Error('Expected split entry-type lane');
286
+ entryTypes[i] = ENTRY_TYPE_SPAN_START;
287
+ }
264
288
  buffer.boolValue(i, testValues[i]);
265
289
  }
266
290
  buffer._writeIndex = testValues.length;
@@ -10,6 +10,7 @@ import {
10
10
  getSpanBufferClass,
11
11
  type SpanBufferConstructor,
12
12
  } from '../../spanBuffer.js';
13
+ import { iterateSpanChildren, NO_NODE } from '../../traceTopology.js';
13
14
 
14
15
  import type { SpanBuffer } from '../../types.js';
15
16
  import { createBuffer, createTestSchema, createTestTraceRoot, createTraceId } from '../test-helpers.js';
@@ -117,7 +118,6 @@ describe('Buffer Chaining', () => {
117
118
  const parentBuffer = createBuffer(schema);
118
119
 
119
120
  const childBuffer = createChildSpanBuffer(parentBuffer, SpanBufferClass, DEFAULT_METADATA, DEFAULT_METADATA);
120
- parentBuffer._children.push(childBuffer);
121
121
 
122
122
  const nextChildBuffer = createOverflowBuffer(childBuffer);
123
123
 
@@ -125,21 +125,20 @@ describe('Buffer Chaining', () => {
125
125
  expect(nextChildBuffer._parent).toBe(parentBuffer);
126
126
 
127
127
  // Should NOT be added to parent's children (it's a continuation, not a new span)
128
- expect(parentBuffer._children).toHaveLength(1);
129
- expect(parentBuffer._children[0]).toBe(childBuffer);
128
+ expect(Array.from(iterateSpanChildren(parentBuffer))).toEqual([childBuffer]);
130
129
  });
131
130
 
132
- it('should create empty children array for chained buffer', () => {
131
+ it('should share logical child topology with a chained buffer', () => {
133
132
  const buffer = createBuffer(schema);
134
133
 
135
134
  // Add a child to original buffer
136
135
  const childBuffer = createChildSpanBuffer(buffer, SpanBufferClass, DEFAULT_METADATA, DEFAULT_METADATA);
137
- buffer._children.push(childBuffer);
138
136
 
139
137
  const nextBuffer = createOverflowBuffer(buffer);
140
138
 
141
- // Chained buffer should have empty children array
142
- expect(nextBuffer._children).toHaveLength(0);
139
+ // Overflow segments share the logical span node and its children.
140
+ expect(nextBuffer._nodeIndex).toBe(buffer._nodeIndex);
141
+ expect(Array.from(iterateSpanChildren(nextBuffer))).toEqual([childBuffer]);
143
142
  });
144
143
  });
145
144
 
@@ -247,31 +246,29 @@ describe('Buffer Chaining', () => {
247
246
  const buffer1 = createOverflowBuffer(rootBuffer);
248
247
  const child1 = createChildSpanBuffer(buffer1, SpanBufferClass, DEFAULT_METADATA, DEFAULT_METADATA);
249
248
  const child2 = createChildSpanBuffer(buffer1, SpanBufferClass, DEFAULT_METADATA, DEFAULT_METADATA);
250
- buffer1._children.push(child1, child2);
251
249
 
252
250
  // Create second chained buffer with children
253
251
  const buffer2 = createOverflowBuffer(buffer1);
254
252
  const child3 = createChildSpanBuffer(buffer2, SpanBufferClass, DEFAULT_METADATA, DEFAULT_METADATA);
255
- buffer2._children.push(child3);
256
253
 
257
- // Verify topology
258
- // Overflow buffers inherit the logical parent (rootBuffer has no parent → undefined)
254
+ // Verify physical overflow links and allocation-free logical topology.
255
+ const topology = rootBuffer._traceRoot._topology;
259
256
  expect(rootBuffer._parent).toBeUndefined();
260
257
  expect(rootBuffer._overflow).toBe(buffer1);
261
- expect(rootBuffer._children).toHaveLength(0);
262
-
263
- // buffer1 is an OVERFLOW of rootBuffer, so it inherits rootBuffer._parent (undefined)
264
258
  expect(buffer1._parent).toBeUndefined();
265
259
  expect(buffer1._overflow).toBe(buffer2);
266
- expect(buffer1._children).toHaveLength(2);
267
- expect(buffer1._children[0]).toBe(child1);
268
- expect(buffer1._children[1]).toBe(child2);
269
-
270
- // buffer2 is an OVERFLOW of buffer1, so it inherits buffer1._parent (undefined)
271
260
  expect(buffer2._parent).toBeUndefined();
272
261
  expect(buffer2._overflow).toBeUndefined();
273
- expect(buffer2._children).toHaveLength(1);
274
- expect(buffer2._children[0]).toBe(child3);
262
+ expect(buffer1._nodeIndex).toBe(rootBuffer._nodeIndex);
263
+ expect(buffer2._nodeIndex).toBe(rootBuffer._nodeIndex);
264
+ expect(topology.count).toBe(4);
265
+ expect(topology.buffers[topology.root]).toBe(rootBuffer);
266
+ expect(topology.firstChild[rootBuffer._nodeIndex]).toBe(child1._nodeIndex);
267
+ expect(topology.nextSibling[child1._nodeIndex]).toBe(child2._nodeIndex);
268
+ expect(topology.nextSibling[child2._nodeIndex]).toBe(child3._nodeIndex);
269
+ expect(topology.nextSibling[child3._nodeIndex]).toBe(NO_NODE);
270
+ expect(topology.lastChild[rootBuffer._nodeIndex]).toBe(child3._nodeIndex);
271
+ expect(Array.from(iterateSpanChildren(rootBuffer))).toEqual([child1, child2, child3]);
275
272
 
276
273
  // Verify identity sharing
277
274
  expect(rootBuffer.trace_id).toBe(traceId);
@@ -3,6 +3,7 @@ import { DEFAULT_BUFFER_CAPACITY } from '@smoothbricks/arrow-builder';
3
3
  import { DEFAULT_METADATA } from '../../opContext/defineOp.js';
4
4
  import { S } from '../../schema/builder.js';
5
5
  import { createSpanBuffer, getSpanBufferClass } from '../../spanBuffer.js';
6
+ import { NO_NODE } from '../../traceTopology.js';
6
7
 
7
8
  import { createBuffer, createTestSchema, createTestTraceRoot, createTraceId } from '../test-helpers.js';
8
9
 
@@ -34,7 +35,9 @@ describe('Buffer Foundation', () => {
34
35
  expect(buf.count_values).toBeInstanceOf(Float64Array); // number → Float64Array
35
36
 
36
37
  // Metadata
37
- expect(buf._children).toBeInstanceOf(Array);
38
+ const topology = buf._traceRoot._topology;
39
+ expect(topology.buffers[topology.root]).toBe(buf);
40
+ expect(topology.firstChild[buf._nodeIndex]).toBe(NO_NODE);
38
41
  expect(buf._writeIndex).toBe(0);
39
42
  expect(buf._capacity).toBe(DEFAULT_BUFFER_CAPACITY);
40
43
  });
@@ -50,7 +53,7 @@ describe('Buffer Foundation', () => {
50
53
  expect(buf.span_id).toBeGreaterThan(0);
51
54
  expect(buf._hasParent).toBe(false);
52
55
  expect(buf._parent).toBeUndefined();
53
- expect(buf._children).toHaveLength(0);
56
+ expect(buf._traceRoot._topology.firstChild[buf._nodeIndex]).toBe(NO_NODE);
54
57
  });
55
58
 
56
59
  it('provides access to buffer stats via constructor', () => {