@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
@@ -0,0 +1,214 @@
1
+ import { describe, expect, it } from 'bun:test';
2
+ import './test-helpers.js';
3
+ import { createTagWriter, getTagWriterClass } from '../codegen/fixedPositionWriterGenerator.js';
4
+ import { resolveEnumLookupDescriptor } from '../enumMetadata.js';
5
+ import { S } from '../schema/builder.js';
6
+ import { defineLogSchema } from '../schema/defineLogSchema.js';
7
+ import { createSpanBuffer } from '../spanBuffer.js';
8
+ import type { AnySpanBuffer } from '../types.js';
9
+ import { createTestOpMetadata, createTestSchema, createTestSpanContext, createTestTraceRoot } from './test-helpers.js';
10
+
11
+ function countFunctionConstructorCalls(run: () => void): number {
12
+ const originalDescriptor = Object.getOwnPropertyDescriptor(globalThis, 'Function');
13
+ if (!originalDescriptor) throw new Error('Expected global Function descriptor');
14
+
15
+ const originalFunction = globalThis.Function;
16
+ let calls = 0;
17
+ const functionProbe = new Proxy(originalFunction, {
18
+ apply(target, thisArgument, argumentList) {
19
+ calls++;
20
+ return Reflect.apply(target, thisArgument, argumentList);
21
+ },
22
+ construct(target, argumentList, newTarget) {
23
+ calls++;
24
+ return Reflect.construct(target, argumentList, newTarget);
25
+ },
26
+ });
27
+
28
+ Object.defineProperty(globalThis, 'Function', {
29
+ configurable: originalDescriptor.configurable,
30
+ enumerable: originalDescriptor.enumerable,
31
+ value: functionProbe,
32
+ writable: originalDescriptor.writable,
33
+ });
34
+ try {
35
+ run();
36
+ } finally {
37
+ Object.defineProperty(globalThis, 'Function', originalDescriptor);
38
+ }
39
+ return calls;
40
+ }
41
+
42
+ function arrayColumn(buffer: AnySpanBuffer, name: string): unknown[] {
43
+ const column = buffer.getColumnIfAllocated(name);
44
+ if (!Array.isArray(column)) {
45
+ throw new Error(`${name} column was not allocated as an array`);
46
+ }
47
+ return column;
48
+ }
49
+
50
+ function float64Column(buffer: AnySpanBuffer, name: string): Float64Array {
51
+ const column = buffer.getColumnIfAllocated(name);
52
+ if (!(column instanceof Float64Array)) {
53
+ throw new Error(`${name} column was not allocated as a Float64Array`);
54
+ }
55
+ return column;
56
+ }
57
+
58
+ function uint8Column(buffer: AnySpanBuffer, name: string): Uint8Array {
59
+ const column = buffer.getColumnIfAllocated(name);
60
+ if (!(column instanceof Uint8Array)) {
61
+ throw new Error(`${name} column was not allocated as a Uint8Array`);
62
+ }
63
+ return column;
64
+ }
65
+
66
+ function bigUint64Column(buffer: AnySpanBuffer, name: string): BigUint64Array {
67
+ const column = buffer.getColumnIfAllocated(name);
68
+ if (!(column instanceof BigUint64Array)) {
69
+ throw new Error(`${name} column was not allocated as a BigUint64Array`);
70
+ }
71
+ return column;
72
+ }
73
+
74
+ function invokeWriterMethod(writer: object, methodName: string, value: unknown): unknown {
75
+ const method = Reflect.get(writer, methodName);
76
+ if (typeof method !== 'function') {
77
+ throw new Error(`TagWriter is missing ${methodName}()`);
78
+ }
79
+ return Reflect.apply(method, writer, [value]);
80
+ }
81
+
82
+ function setupWriter() {
83
+ const schema = createTestSchema({
84
+ categoryValue: S.category(),
85
+ textValue: S.text(),
86
+ numberValue: S.number(),
87
+ booleanValue: S.boolean(),
88
+ enumValue: S.enum(['FIRST', 'SECOND']),
89
+ });
90
+ const buffer = createSpanBuffer(schema, createTestTraceRoot('tag-writer-aot'), createTestOpMetadata(), 8);
91
+ const context = createTestSpanContext(schema, buffer);
92
+ return { buffer, schema, writer: createTagWriter(schema, context) };
93
+ }
94
+
95
+ describe('AOT-safe TagWriter class creation', () => {
96
+ it('creates and caches a constructor for a fresh schema without calling global Function', () => {
97
+ const schema = defineLogSchema({ status: S.enum(['QUEUED', 'DONE']) });
98
+ const enumLookup = resolveEnumLookupDescriptor(schema);
99
+
100
+ const functionConstructorCalls = countFunctionConstructorCalls(() => {
101
+ getTagWriterClass(schema, ['status'], enumLookup);
102
+ });
103
+
104
+ expect(functionConstructorCalls).toBe(0);
105
+ });
106
+
107
+ it('caches by schema identity and ordered eager-column key', () => {
108
+ const schema = defineLogSchema({ alpha: S.number(), beta: S.number() });
109
+ const sameEagerKey = getTagWriterClass(schema, ['alpha']);
110
+
111
+ expect(getTagWriterClass(schema, ['alpha'])).toBe(sameEagerKey);
112
+ expect(getTagWriterClass(schema, ['beta'])).not.toBe(sameEagerKey);
113
+ expect(getTagWriterClass(schema, ['alpha', 'beta'])).not.toBe(getTagWriterClass(schema, ['beta', 'alpha']));
114
+
115
+ const structurallyEqualSchema = defineLogSchema({ alpha: S.number(), beta: S.number() });
116
+ expect(getTagWriterClass(structurallyEqualSchema, ['alpha'])).not.toBe(sameEagerKey);
117
+ });
118
+ });
119
+
120
+ describe('TagWriter row-0 semantics', () => {
121
+ it('uses exact schema setter names, writes every scalar lane at row 0, and preserves fluent identity', () => {
122
+ const { buffer, writer } = setupWriter();
123
+
124
+ expect(writer.categoryValue('category-0')).toBe(writer);
125
+ expect(writer.textValue('text-0')).toBe(writer);
126
+ expect(writer.numberValue(42.5)).toBe(writer);
127
+ expect(writer.booleanValue(true)).toBe(writer);
128
+ expect(writer.enumValue('SECOND')).toBe(writer);
129
+ expect(writer.uint64_value(18_446_744_073_709_551_615n)).toBe(writer);
130
+
131
+ expect(arrayColumn(buffer, 'categoryValue')[0]).toBe('category-0');
132
+ expect(arrayColumn(buffer, 'textValue')[0]).toBe('text-0');
133
+ expect(float64Column(buffer, 'numberValue')[0]).toBe(42.5);
134
+ expect((uint8Column(buffer, 'booleanValue')[0] & 0b0000_0001) !== 0).toBe(true);
135
+ expect(uint8Column(buffer, 'enumValue')[0]).toBe(1);
136
+ expect(bigUint64Column(buffer, 'uint64_value')[0]).toBe(18_446_744_073_709_551_615n);
137
+ });
138
+
139
+ it('encodes an invalid enum value as ordinal zero', () => {
140
+ const { buffer, writer } = setupWriter();
141
+
142
+ expect(invokeWriterMethod(writer, 'enumValue', 'INVALID')).toBe(writer);
143
+ expect(uint8Column(buffer, 'enumValue')[0]).toBe(0);
144
+ });
145
+
146
+ it('with skips nullish values, evaluates attributes in schema order, and returns the same writer', () => {
147
+ const schema = createTestSchema({
148
+ first: S.number(),
149
+ nullValue: S.text(),
150
+ second: S.category(),
151
+ undefinedValue: S.number(),
152
+ third: S.boolean(),
153
+ });
154
+ const buffer = createSpanBuffer(schema, createTestTraceRoot('tag-writer-with-order'), createTestOpMetadata(), 8);
155
+ const context = createTestSpanContext(schema, buffer);
156
+ const writer = createTagWriter(schema, context);
157
+ const firstAccesses: string[] = [];
158
+ const accessed = new Set<string>();
159
+ const recordFirstAccess = (name: string): void => {
160
+ if (!accessed.has(name)) {
161
+ accessed.add(name);
162
+ firstAccesses.push(name);
163
+ }
164
+ };
165
+ const attributes = Object.defineProperties(
166
+ {},
167
+ {
168
+ third: {
169
+ enumerable: true,
170
+ get() {
171
+ recordFirstAccess('third');
172
+ return true;
173
+ },
174
+ },
175
+ undefinedValue: {
176
+ enumerable: true,
177
+ get() {
178
+ recordFirstAccess('undefinedValue');
179
+ return undefined;
180
+ },
181
+ },
182
+ second: {
183
+ enumerable: true,
184
+ get() {
185
+ recordFirstAccess('second');
186
+ return 'second-0';
187
+ },
188
+ },
189
+ nullValue: {
190
+ enumerable: true,
191
+ get() {
192
+ recordFirstAccess('nullValue');
193
+ return null;
194
+ },
195
+ },
196
+ first: {
197
+ enumerable: true,
198
+ get() {
199
+ recordFirstAccess('first');
200
+ return 1;
201
+ },
202
+ },
203
+ },
204
+ );
205
+
206
+ expect(invokeWriterMethod(writer, 'with', attributes)).toBe(writer);
207
+ expect(firstAccesses).toEqual(['first', 'nullValue', 'second', 'undefinedValue', 'third']);
208
+ expect(float64Column(buffer, 'first')[0]).toBe(1);
209
+ expect(arrayColumn(buffer, 'second')[0]).toBe('second-0');
210
+ expect((uint8Column(buffer, 'third')[0] & 0b0000_0001) !== 0).toBe(true);
211
+ expect(buffer.getColumnIfAllocated('nullValue')).toBeUndefined();
212
+ expect(buffer.getColumnIfAllocated('undefinedValue')).toBeUndefined();
213
+ });
214
+ });
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import { DEFAULT_BUFFER_CAPACITY } from '@smoothbricks/arrow-builder';
9
- import { createSpanLogger, type SpanLoggerImpl } from '../codegen/spanLoggerGenerator.js';
9
+ import type { SpanLoggerImpl } from '../codegen/spanLoggerGenerator.js';
10
10
  import { defineOpContext } from '../defineOpContext.js';
11
11
  import { JsBufferStrategy } from '../JsBufferStrategy.js';
12
12
  import { createOpMetadata, DEFAULT_METADATA } from '../opContext/defineOp.js';
@@ -20,10 +20,19 @@ import type {
20
20
  } from '../opContext/opGroupTypes.js';
21
21
  import type { OpMetadata } from '../opContext/opTypes.js';
22
22
  import type { OpContext } from '../opContext/types.js';
23
+ import { type CallsitePlan, getPhysicalLayoutPlan, sealCallsitePlan } from '../physicalLayoutPlan.js';
24
+ import {
25
+ RUNTIME_HINT_ANALYZED_VALID,
26
+ RUNTIME_HINT_FULL_CAPABILITIES,
27
+ RUNTIME_HINT_MESSAGE_LAYOUT_DYNAMIC_ONLY,
28
+ RUNTIME_HINT_MESSAGE_LAYOUT_MIXED,
29
+ RUNTIME_HINT_MESSAGE_LAYOUT_STATIC_ONLY,
30
+ } from '../runtimeHint.js';
23
31
  import { LogSchema } from '../schema/LogSchema.js';
24
32
  import { mergeWithSystemSchema, type SystemSchemaFieldTypes } from '../schema/systemSchema.js';
25
33
  import type { SchemaFields } from '../schema/types.js';
26
- import { createSpanBuffer } from '../spanBuffer.js';
34
+ import { createSpanBuffer, getSpanBufferClass } from '../spanBuffer.js';
35
+ import { createSpanContextClass } from '../spanContext.js';
27
36
  import { createTraceId, type TraceId } from '../traceId.js';
28
37
  import type { ITraceRoot, TracerLifecycleHooks } from '../traceRoot.js';
29
38
  import { createTraceRoot } from '../traceRoot.node.js';
@@ -107,7 +116,11 @@ export function createTestTracerOptions<T extends LogSchema>(): TracerOptions<T>
107
116
  * Shared TestTracer instance for tests that create buffers directly.
108
117
  * Typed as TracerLifecycleHooks because that's what TraceRoot expects.
109
118
  */
110
- export const TEST_TRACER: TracerLifecycleHooks = new TestTracer(minimalOpContext, createTestTracerOptions());
119
+ type MinimalLogSchema = (typeof minimalOpContext)['logBinding']['logSchema'];
120
+ export const TEST_TRACER: TracerLifecycleHooks<MinimalLogSchema> = new TestTracer(
121
+ minimalOpContext,
122
+ createTestTracerOptions(),
123
+ );
111
124
 
112
125
  type TestSpanBufferBundle<T extends SchemaFields> = {
113
126
  logBinding: LogBinding;
@@ -180,10 +193,7 @@ export function createTestLogBinding<T extends SchemaFields>(schema: T | LogSche
180
193
  // Wrap in LogSchema if plain SchemaFields provided
181
194
  const logSchema = schema instanceof LogSchema ? schema : createTestSchema(schema);
182
195
 
183
- return {
184
- logSchema,
185
- remappedViewClass: undefined,
186
- };
196
+ return { logSchema };
187
197
  }
188
198
 
189
199
  /**
@@ -237,6 +247,48 @@ export function createTestSpanBuffer<T extends SchemaFields>(
237
247
  return { logBinding, spanBuffer };
238
248
  }
239
249
 
250
+ let testWriterContextPlanId = 0;
251
+
252
+ type TestWriterOpContext<T extends SchemaFields> = OpContext<
253
+ LogSchema<T>,
254
+ Record<string, never>,
255
+ Record<string, never>,
256
+ Record<string, never>
257
+ >;
258
+
259
+ /** Create a real capability-complete SpanContext around an existing test buffer. */
260
+ export function createTestSpanContext<
261
+ T extends SchemaFields,
262
+ Ctx extends OpContext<LogSchema<T>> = TestWriterOpContext<T>,
263
+ >(schema: LogSchema<T>, buffer: SpanBuffer<LogSchema<T>>, callsitePlan?: CallsitePlan<LogSchema<T>, Ctx>) {
264
+ const messageLayoutHint =
265
+ buffer._messageLayoutFamily === 'static-only'
266
+ ? RUNTIME_HINT_MESSAGE_LAYOUT_STATIC_ONLY
267
+ : buffer._messageLayoutFamily === 'dynamic-only'
268
+ ? RUNTIME_HINT_MESSAGE_LAYOUT_DYNAMIC_ONLY
269
+ : RUNTIME_HINT_MESSAGE_LAYOUT_MIXED;
270
+ const runtimeHint =
271
+ RUNTIME_HINT_ANALYZED_VALID | RUNTIME_HINT_FULL_CAPABILITIES | messageLayoutHint | buffer._capacity;
272
+ const resolvedPlan =
273
+ callsitePlan ??
274
+ sealCallsitePlan(
275
+ getPhysicalLayoutPlan(
276
+ getSpanBufferClass(schema),
277
+ runtimeHint,
278
+ createSpanContextClass<Ctx>(
279
+ schema,
280
+ { logSchema: schema, remapDescriptor: undefined },
281
+ RUNTIME_HINT_FULL_CAPABILITIES,
282
+ ),
283
+ undefined,
284
+ 'strategy-selected',
285
+ `test-writer-context:${testWriterContextPlanId++}`,
286
+ ),
287
+ DEFAULT_METADATA,
288
+ );
289
+ resolvedPlan.appenders.writeSpanStart(buffer, 'test-writer-context');
290
+ return new resolvedPlan.SpanContextClass(buffer, schema, resolvedPlan);
291
+ }
240
292
  /**
241
293
  * Create a properly typed SpanLogger for testing.
242
294
  *
@@ -246,12 +298,15 @@ export function createTestSpanBuffer<T extends SchemaFields>(
246
298
  * @param schema - LogSchema to use
247
299
  * @returns Object with buffer and logger, both properly typed
248
300
  */
249
- export function createTestLogger<T extends LogSchema>(schema: T): TestLoggerBundle<T> {
250
- const logBinding = createTestLogBinding(schema);
301
+ export function createTestLogger<T extends SchemaFields>(
302
+ schema: LogSchema<T>,
303
+ ): TestLoggerBundle<LogSchema<SystemSchemaFieldTypes & T>> {
304
+ const runtimeSchema = createTestSchema(schema.fields);
305
+ const logBinding = createTestLogBinding(runtimeSchema);
251
306
  const traceRoot = createTestTraceRoot();
252
- const buffer = createSpanBuffer(schema, traceRoot, DEFAULT_METADATA);
253
- const logger = createSpanLogger(schema, buffer);
254
- return { buffer, logger, logBinding };
307
+ const buffer = createSpanBuffer(runtimeSchema, traceRoot, DEFAULT_METADATA);
308
+ const context = createTestSpanContext(runtimeSchema, buffer);
309
+ return { buffer, logger: context._spanLogger, logBinding };
255
310
  }
256
311
 
257
312
  // =============================================================================
@@ -0,0 +1,62 @@
1
+ import { afterEach, describe, expect, it, spyOn } from 'bun:test';
2
+
3
+ import { _resetThreadId, copyThreadIdTo, getThreadId } from '../threadId.js';
4
+
5
+ const THREAD_ID_BYTES = Uint8Array.of(0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef);
6
+ const THREAD_ID_BIGINT = 0xefcdab8967452301n;
7
+
8
+ afterEach(() => {
9
+ _resetThreadId();
10
+ });
11
+
12
+ describe('thread ID initialization', () => {
13
+ it('initializes once and copies the singleton bytes without aliasing', () => {
14
+ const getRandomValues = spyOn(crypto, 'getRandomValues').mockImplementation((array: Uint8Array<ArrayBuffer>) => {
15
+ array.set(THREAD_ID_BYTES);
16
+ return array;
17
+ });
18
+ _resetThreadId();
19
+
20
+ try {
21
+ const firstCopy = new Uint8Array(12).fill(0xaa);
22
+
23
+ copyThreadIdTo(firstCopy, 2);
24
+ firstCopy[2] = 0;
25
+
26
+ const secondCopy = new Uint8Array(THREAD_ID_BYTES.length);
27
+ copyThreadIdTo(secondCopy, 0);
28
+
29
+ expect(getRandomValues).toHaveBeenCalledTimes(1);
30
+ expect(Array.from(firstCopy)).toEqual([0xaa, 0xaa, 0, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xaa, 0xaa]);
31
+ expect(secondCopy).toEqual(THREAD_ID_BYTES);
32
+ expect(getThreadId()).toBe(THREAD_ID_BIGINT);
33
+ } finally {
34
+ getRandomValues.mockRestore();
35
+ }
36
+ });
37
+
38
+ it('retries entropy initialization after a provider failure instead of caching zeroes', () => {
39
+ let attempts = 0;
40
+ const getRandomValues = spyOn(crypto, 'getRandomValues').mockImplementation((array: Uint8Array<ArrayBuffer>) => {
41
+ attempts++;
42
+ if (attempts === 1) throw new Error('entropy temporarily unavailable');
43
+ array.set(THREAD_ID_BYTES);
44
+ return array;
45
+ });
46
+ _resetThreadId();
47
+
48
+ try {
49
+ expect(() => getThreadId()).toThrow('entropy temporarily unavailable');
50
+
51
+ const copied = new Uint8Array(THREAD_ID_BYTES.length);
52
+ copyThreadIdTo(copied, 0);
53
+
54
+ expect(getRandomValues).toHaveBeenCalledTimes(2);
55
+ expect(copied).toEqual(THREAD_ID_BYTES);
56
+ expect(getThreadId()).toBe(THREAD_ID_BIGINT);
57
+ expect(getThreadId()).not.toBe(0n);
58
+ } finally {
59
+ getRandomValues.mockRestore();
60
+ }
61
+ });
62
+ });