@smoothbricks/lmao 0.1.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 (447) hide show
  1. package/README.md +269 -0
  2. package/dist/allocator.wasm +0 -0
  3. package/dist/bun/preload.d.ts +11 -0
  4. package/dist/bun/preload.d.ts.map +1 -0
  5. package/dist/bun/preload.js +10 -0
  6. package/dist/bun/trace-preload.d.ts +8 -0
  7. package/dist/bun/trace-preload.d.ts.map +1 -0
  8. package/dist/bun/trace-preload.js +12 -0
  9. package/dist/es.d.ts +8 -0
  10. package/dist/es.d.ts.map +1 -0
  11. package/dist/es.js +9 -0
  12. package/dist/index.d.ts +41 -0
  13. package/dist/index.d.ts.map +1 -0
  14. package/dist/index.js +84 -0
  15. package/dist/lib/JsBufferStrategy.d.ts +49 -0
  16. package/dist/lib/JsBufferStrategy.d.ts.map +1 -0
  17. package/dist/lib/JsBufferStrategy.js +60 -0
  18. package/dist/lib/archive/chunkCompaction.d.ts +15 -0
  19. package/dist/lib/archive/chunkCompaction.d.ts.map +1 -0
  20. package/dist/lib/archive/chunkCompaction.js +24 -0
  21. package/dist/lib/archive/chunkEnvelope.d.ts +21 -0
  22. package/dist/lib/archive/chunkEnvelope.d.ts.map +1 -0
  23. package/dist/lib/archive/chunkEnvelope.js +55 -0
  24. package/dist/lib/archive/chunkRouting.d.ts +10 -0
  25. package/dist/lib/archive/chunkRouting.d.ts.map +1 -0
  26. package/dist/lib/archive/chunkRouting.js +47 -0
  27. package/dist/lib/archive/chunkStats.d.ts +12 -0
  28. package/dist/lib/archive/chunkStats.d.ts.map +1 -0
  29. package/dist/lib/archive/chunkStats.js +10 -0
  30. package/dist/lib/archive/index.d.ts +5 -0
  31. package/dist/lib/archive/index.d.ts.map +1 -0
  32. package/dist/lib/archive/index.js +4 -0
  33. package/dist/lib/arrow/capacityStats.d.ts +9 -0
  34. package/dist/lib/arrow/capacityStats.d.ts.map +1 -0
  35. package/dist/lib/arrow/capacityStats.js +231 -0
  36. package/dist/lib/arrow/dictionaries.d.ts +27 -0
  37. package/dist/lib/arrow/dictionaries.d.ts.map +1 -0
  38. package/dist/lib/arrow/dictionaries.js +135 -0
  39. package/dist/lib/arrow/flechette.d.ts +40 -0
  40. package/dist/lib/arrow/flechette.d.ts.map +1 -0
  41. package/dist/lib/arrow/flechette.js +67 -0
  42. package/dist/lib/arrow/utils.d.ts +38 -0
  43. package/dist/lib/arrow/utils.d.ts.map +1 -0
  44. package/dist/lib/arrow/utils.js +112 -0
  45. package/dist/lib/buffer/Nanoseconds.d.ts +109 -0
  46. package/dist/lib/buffer/Nanoseconds.d.ts.map +1 -0
  47. package/dist/lib/buffer/Nanoseconds.js +86 -0
  48. package/dist/lib/bufferStrategy.d.ts +95 -0
  49. package/dist/lib/bufferStrategy.d.ts.map +1 -0
  50. package/dist/lib/bufferStrategy.js +1 -0
  51. package/dist/lib/capacityTuning.d.ts +50 -0
  52. package/dist/lib/capacityTuning.d.ts.map +1 -0
  53. package/dist/lib/capacityTuning.js +65 -0
  54. package/dist/lib/codegen/evaluatorGenerator.d.ts +35 -0
  55. package/dist/lib/codegen/evaluatorGenerator.d.ts.map +1 -0
  56. package/dist/lib/codegen/evaluatorGenerator.js +199 -0
  57. package/dist/lib/codegen/fixedPositionWriterGenerator.d.ts +139 -0
  58. package/dist/lib/codegen/fixedPositionWriterGenerator.d.ts.map +1 -0
  59. package/dist/lib/codegen/fixedPositionWriterGenerator.js +289 -0
  60. package/dist/lib/codegen/spanLoggerGenerator.d.ts +115 -0
  61. package/dist/lib/codegen/spanLoggerGenerator.d.ts.map +1 -0
  62. package/dist/lib/codegen/spanLoggerGenerator.js +575 -0
  63. package/dist/lib/convertToArrow.d.ts +40 -0
  64. package/dist/lib/convertToArrow.d.ts.map +1 -0
  65. package/dist/lib/convertToArrow.js +1467 -0
  66. package/dist/lib/defineOpContext.d.ts +96 -0
  67. package/dist/lib/defineOpContext.d.ts.map +1 -0
  68. package/dist/lib/defineOpContext.js +227 -0
  69. package/dist/lib/errors/Blocked.d.ts +113 -0
  70. package/dist/lib/errors/Blocked.d.ts.map +1 -0
  71. package/dist/lib/errors/Blocked.js +68 -0
  72. package/dist/lib/errors/CodeError.d.ts +101 -0
  73. package/dist/lib/errors/CodeError.d.ts.map +1 -0
  74. package/dist/lib/errors/CodeError.js +42 -0
  75. package/dist/lib/errors/RetriesExhausted.d.ts +67 -0
  76. package/dist/lib/errors/RetriesExhausted.d.ts.map +1 -0
  77. package/dist/lib/errors/RetriesExhausted.js +31 -0
  78. package/dist/lib/errors/Transient.d.ts +115 -0
  79. package/dist/lib/errors/Transient.d.ts.map +1 -0
  80. package/dist/lib/errors/Transient.js +54 -0
  81. package/dist/lib/errors/index.d.ts +14 -0
  82. package/dist/lib/errors/index.d.ts.map +1 -0
  83. package/dist/lib/errors/index.js +16 -0
  84. package/dist/lib/errors/retry-policy.d.ts +60 -0
  85. package/dist/lib/errors/retry-policy.d.ts.map +1 -0
  86. package/dist/lib/errors/retry-policy.js +54 -0
  87. package/dist/lib/flushScheduler.d.ts +162 -0
  88. package/dist/lib/flushScheduler.d.ts.map +1 -0
  89. package/dist/lib/flushScheduler.js +388 -0
  90. package/dist/lib/library.d.ts +149 -0
  91. package/dist/lib/library.d.ts.map +1 -0
  92. package/dist/lib/library.js +588 -0
  93. package/dist/lib/logApi.d.ts +61 -0
  94. package/dist/lib/logApi.d.ts.map +1 -0
  95. package/dist/lib/logApi.js +12 -0
  96. package/dist/lib/logBinding.d.ts +63 -0
  97. package/dist/lib/logBinding.d.ts.map +1 -0
  98. package/dist/lib/logBinding.js +1 -0
  99. package/dist/lib/op.d.ts +105 -0
  100. package/dist/lib/op.d.ts.map +1 -0
  101. package/dist/lib/op.js +59 -0
  102. package/dist/lib/opContext/contextTypes.d.ts +88 -0
  103. package/dist/lib/opContext/contextTypes.d.ts.map +1 -0
  104. package/dist/lib/opContext/contextTypes.js +34 -0
  105. package/dist/lib/opContext/createOpGroup.d.ts +57 -0
  106. package/dist/lib/opContext/createOpGroup.d.ts.map +1 -0
  107. package/dist/lib/opContext/createOpGroup.js +341 -0
  108. package/dist/lib/opContext/defineOp.d.ts +83 -0
  109. package/dist/lib/opContext/defineOp.d.ts.map +1 -0
  110. package/dist/lib/opContext/defineOp.js +197 -0
  111. package/dist/lib/opContext/featureFlagTypes.d.ts +58 -0
  112. package/dist/lib/opContext/featureFlagTypes.d.ts.map +1 -0
  113. package/dist/lib/opContext/featureFlagTypes.js +1 -0
  114. package/dist/lib/opContext/index.d.ts +13 -0
  115. package/dist/lib/opContext/index.d.ts.map +1 -0
  116. package/dist/lib/opContext/index.js +15 -0
  117. package/dist/lib/opContext/opGroupTypes.d.ts +250 -0
  118. package/dist/lib/opContext/opGroupTypes.d.ts.map +1 -0
  119. package/dist/lib/opContext/opGroupTypes.js +31 -0
  120. package/dist/lib/opContext/opTypes.d.ts +48 -0
  121. package/dist/lib/opContext/opTypes.d.ts.map +1 -0
  122. package/dist/lib/opContext/opTypes.js +7 -0
  123. package/dist/lib/opContext/spanContextTypes.d.ts +347 -0
  124. package/dist/lib/opContext/spanContextTypes.d.ts.map +1 -0
  125. package/dist/lib/opContext/spanContextTypes.js +1 -0
  126. package/dist/lib/opContext/types.d.ts +297 -0
  127. package/dist/lib/opContext/types.d.ts.map +1 -0
  128. package/dist/lib/opContext/types.js +16 -0
  129. package/dist/lib/result.d.ts +308 -0
  130. package/dist/lib/result.d.ts.map +1 -0
  131. package/dist/lib/result.js +359 -0
  132. package/dist/lib/schema/LogSchema.d.ts +62 -0
  133. package/dist/lib/schema/LogSchema.d.ts.map +1 -0
  134. package/dist/lib/schema/LogSchema.js +134 -0
  135. package/dist/lib/schema/builder.d.ts +12 -0
  136. package/dist/lib/schema/builder.d.ts.map +1 -0
  137. package/dist/lib/schema/builder.js +169 -0
  138. package/dist/lib/schema/defineFeatureFlags.d.ts +60 -0
  139. package/dist/lib/schema/defineFeatureFlags.d.ts.map +1 -0
  140. package/dist/lib/schema/defineFeatureFlags.js +29 -0
  141. package/dist/lib/schema/defineLogSchema.d.ts +87 -0
  142. package/dist/lib/schema/defineLogSchema.d.ts.map +1 -0
  143. package/dist/lib/schema/defineLogSchema.js +171 -0
  144. package/dist/lib/schema/evaluator.d.ts +267 -0
  145. package/dist/lib/schema/evaluator.d.ts.map +1 -0
  146. package/dist/lib/schema/evaluator.js +169 -0
  147. package/dist/lib/schema/extend.d.ts +14 -0
  148. package/dist/lib/schema/extend.d.ts.map +1 -0
  149. package/dist/lib/schema/extend.js +51 -0
  150. package/dist/lib/schema/systemSchema.d.ts +112 -0
  151. package/dist/lib/schema/systemSchema.d.ts.map +1 -0
  152. package/dist/lib/schema/systemSchema.js +260 -0
  153. package/dist/lib/schema/typeGuards.d.ts +52 -0
  154. package/dist/lib/schema/typeGuards.d.ts.map +1 -0
  155. package/dist/lib/schema/typeGuards.js +127 -0
  156. package/dist/lib/schema/types.d.ts +156 -0
  157. package/dist/lib/schema/types.d.ts.map +1 -0
  158. package/dist/lib/schema/types.js +4 -0
  159. package/dist/lib/spanBuffer.d.ts +133 -0
  160. package/dist/lib/spanBuffer.d.ts.map +1 -0
  161. package/dist/lib/spanBuffer.js +442 -0
  162. package/dist/lib/spanBufferHelpers.d.ts +53 -0
  163. package/dist/lib/spanBufferHelpers.d.ts.map +1 -0
  164. package/dist/lib/spanBufferHelpers.js +65 -0
  165. package/dist/lib/spanBufferStats.d.ts +38 -0
  166. package/dist/lib/spanBufferStats.d.ts.map +1 -0
  167. package/dist/lib/spanBufferStats.js +1 -0
  168. package/dist/lib/spanContext.d.ts +141 -0
  169. package/dist/lib/spanContext.d.ts.map +1 -0
  170. package/dist/lib/spanContext.js +763 -0
  171. package/dist/lib/sqlite/index.d.ts +14 -0
  172. package/dist/lib/sqlite/index.d.ts.map +1 -0
  173. package/dist/lib/sqlite/index.js +12 -0
  174. package/dist/lib/sqlite/sqlite-async-writer.d.ts +24 -0
  175. package/dist/lib/sqlite/sqlite-async-writer.d.ts.map +1 -0
  176. package/dist/lib/sqlite/sqlite-async-writer.js +65 -0
  177. package/dist/lib/sqlite/sqlite-common.d.ts +37 -0
  178. package/dist/lib/sqlite/sqlite-common.d.ts.map +1 -0
  179. package/dist/lib/sqlite/sqlite-common.js +207 -0
  180. package/dist/lib/sqlite/sqlite-d1.d.ts +25 -0
  181. package/dist/lib/sqlite/sqlite-d1.d.ts.map +1 -0
  182. package/dist/lib/sqlite/sqlite-d1.js +67 -0
  183. package/dist/lib/sqlite/sqlite-db.d.ts +29 -0
  184. package/dist/lib/sqlite/sqlite-db.d.ts.map +1 -0
  185. package/dist/lib/sqlite/sqlite-db.js +1 -0
  186. package/dist/lib/sqlite/sqlite-node.d.ts +16 -0
  187. package/dist/lib/sqlite/sqlite-node.d.ts.map +1 -0
  188. package/dist/lib/sqlite/sqlite-node.js +68 -0
  189. package/dist/lib/sqlite/sqlite-writer.d.ts +39 -0
  190. package/dist/lib/sqlite/sqlite-writer.d.ts.map +1 -0
  191. package/dist/lib/sqlite/sqlite-writer.js +78 -0
  192. package/dist/lib/testing/bun-harness.d.ts +150 -0
  193. package/dist/lib/testing/bun-harness.d.ts.map +1 -0
  194. package/dist/lib/testing/bun-harness.js +729 -0
  195. package/dist/lib/testing/extractFacts.d.ts +73 -0
  196. package/dist/lib/testing/extractFacts.d.ts.map +1 -0
  197. package/dist/lib/testing/extractFacts.js +237 -0
  198. package/dist/lib/testing/facts.d.ts +235 -0
  199. package/dist/lib/testing/facts.d.ts.map +1 -0
  200. package/dist/lib/testing/facts.js +209 -0
  201. package/dist/lib/testing/index.d.ts +58 -0
  202. package/dist/lib/testing/index.d.ts.map +1 -0
  203. package/dist/lib/testing/index.js +74 -0
  204. package/dist/lib/testing/queryable-span.d.ts +39 -0
  205. package/dist/lib/testing/queryable-span.d.ts.map +1 -0
  206. package/dist/lib/testing/queryable-span.js +58 -0
  207. package/dist/lib/testing/span-query.d.ts +21 -0
  208. package/dist/lib/testing/span-query.d.ts.map +1 -0
  209. package/dist/lib/testing/span-query.js +47 -0
  210. package/dist/lib/testing/stdio-replay.d.ts +4 -0
  211. package/dist/lib/testing/stdio-replay.d.ts.map +1 -0
  212. package/dist/lib/testing/stdio-replay.js +42 -0
  213. package/dist/lib/testing/trace-query.d.ts +59 -0
  214. package/dist/lib/testing/trace-query.d.ts.map +1 -0
  215. package/dist/lib/testing/trace-query.js +462 -0
  216. package/dist/lib/testing/vitest-harness.d.ts +135 -0
  217. package/dist/lib/testing/vitest-harness.d.ts.map +1 -0
  218. package/dist/lib/testing/vitest-harness.js +486 -0
  219. package/dist/lib/threadId.d.ts +58 -0
  220. package/dist/lib/threadId.d.ts.map +1 -0
  221. package/dist/lib/threadId.js +123 -0
  222. package/dist/lib/traceContext.d.ts +116 -0
  223. package/dist/lib/traceContext.d.ts.map +1 -0
  224. package/dist/lib/traceContext.js +37 -0
  225. package/dist/lib/traceId.d.ts +78 -0
  226. package/dist/lib/traceId.d.ts.map +1 -0
  227. package/dist/lib/traceId.js +87 -0
  228. package/dist/lib/traceRoot.d.ts +133 -0
  229. package/dist/lib/traceRoot.d.ts.map +1 -0
  230. package/dist/lib/traceRoot.es.d.ts +75 -0
  231. package/dist/lib/traceRoot.es.d.ts.map +1 -0
  232. package/dist/lib/traceRoot.es.js +129 -0
  233. package/dist/lib/traceRoot.js +19 -0
  234. package/dist/lib/traceRoot.node.d.ts +77 -0
  235. package/dist/lib/traceRoot.node.d.ts.map +1 -0
  236. package/dist/lib/traceRoot.node.js +133 -0
  237. package/dist/lib/traceRoot.universal.d.ts +3 -0
  238. package/dist/lib/traceRoot.universal.d.ts.map +1 -0
  239. package/dist/lib/traceRoot.universal.js +17 -0
  240. package/dist/lib/tracer.d.ts +296 -0
  241. package/dist/lib/tracer.d.ts.map +1 -0
  242. package/dist/lib/tracer.js +346 -0
  243. package/dist/lib/tracers/ArrayQueueTracer.d.ts +56 -0
  244. package/dist/lib/tracers/ArrayQueueTracer.d.ts.map +1 -0
  245. package/dist/lib/tracers/ArrayQueueTracer.js +67 -0
  246. package/dist/lib/tracers/CompositeTracer.d.ts +24 -0
  247. package/dist/lib/tracers/CompositeTracer.d.ts.map +1 -0
  248. package/dist/lib/tracers/CompositeTracer.js +57 -0
  249. package/dist/lib/tracers/NoOpTracer.d.ts +58 -0
  250. package/dist/lib/tracers/NoOpTracer.d.ts.map +1 -0
  251. package/dist/lib/tracers/NoOpTracer.js +41 -0
  252. package/dist/lib/tracers/SQLiteTracer.d.ts +42 -0
  253. package/dist/lib/tracers/SQLiteTracer.d.ts.map +1 -0
  254. package/dist/lib/tracers/SQLiteTracer.js +84 -0
  255. package/dist/lib/tracers/StdioTracer.d.ts +83 -0
  256. package/dist/lib/tracers/StdioTracer.d.ts.map +1 -0
  257. package/dist/lib/tracers/StdioTracer.js +270 -0
  258. package/dist/lib/tracers/TestTracer.d.ts +95 -0
  259. package/dist/lib/tracers/TestTracer.d.ts.map +1 -0
  260. package/dist/lib/tracers/TestTracer.js +87 -0
  261. package/dist/lib/tracers/index.d.ts +12 -0
  262. package/dist/lib/tracers/index.d.ts.map +1 -0
  263. package/dist/lib/tracers/index.js +11 -0
  264. package/dist/lib/types.d.ts +366 -0
  265. package/dist/lib/types.d.ts.map +1 -0
  266. package/dist/lib/types.js +1 -0
  267. package/dist/lib/utf8Cache.d.ts +111 -0
  268. package/dist/lib/utf8Cache.d.ts.map +1 -0
  269. package/dist/lib/utf8Cache.js +177 -0
  270. package/dist/lib/wasm/WasmBufferStrategy.d.ts +88 -0
  271. package/dist/lib/wasm/WasmBufferStrategy.d.ts.map +1 -0
  272. package/dist/lib/wasm/WasmBufferStrategy.js +138 -0
  273. package/dist/lib/wasm/wasmAllocator.d.ts +109 -0
  274. package/dist/lib/wasm/wasmAllocator.d.ts.map +1 -0
  275. package/dist/lib/wasm/wasmAllocator.js +227 -0
  276. package/dist/lib/wasm/wasmSpanBuffer.d.ts +123 -0
  277. package/dist/lib/wasm/wasmSpanBuffer.d.ts.map +1 -0
  278. package/dist/lib/wasm/wasmSpanBuffer.js +772 -0
  279. package/dist/lib/wasm/wasmTraceRoot.d.ts +167 -0
  280. package/dist/lib/wasm/wasmTraceRoot.d.ts.map +1 -0
  281. package/dist/lib/wasm/wasmTraceRoot.js +264 -0
  282. package/dist/node.d.ts +7 -0
  283. package/dist/node.d.ts.map +1 -0
  284. package/dist/node.js +8 -0
  285. package/dist/testing.d.ts +18 -0
  286. package/dist/testing.d.ts.map +1 -0
  287. package/dist/testing.js +17 -0
  288. package/package.json +193 -0
  289. package/src/bun/preload.ts +11 -0
  290. package/src/bun/trace-preload.ts +14 -0
  291. package/src/es.ts +11 -0
  292. package/src/index.ts +194 -0
  293. package/src/lib/JsBufferStrategy.ts +102 -0
  294. package/src/lib/__tests__/arrow-builder-integration/arrow-conversion.test.ts +485 -0
  295. package/src/lib/__tests__/arrow-builder-integration/binary-arrow-conversion.test.ts +390 -0
  296. package/src/lib/__tests__/arrow-builder-integration/binary-comparison.test.ts +647 -0
  297. package/src/lib/__tests__/arrow-builder-integration/binary-format-compliance.test.ts +292 -0
  298. package/src/lib/__tests__/arrow-builder-integration/buffer-chaining.test.ts +354 -0
  299. package/src/lib/__tests__/arrow-builder-integration/foundation.test.ts +127 -0
  300. package/src/lib/__tests__/arrow-builder-integration/integration.test.ts +392 -0
  301. package/src/lib/__tests__/arrow-builder-integration/lazy-columns.test.ts +389 -0
  302. package/src/lib/__tests__/arrow-conversion-algorithms.test.ts +54 -0
  303. package/src/lib/__tests__/arrow-test-helpers.ts +71 -0
  304. package/src/lib/__tests__/binary-e2e.test.ts +203 -0
  305. package/src/lib/__tests__/buffer-overflow-op-api.test.ts +608 -0
  306. package/src/lib/__tests__/buffer-overflow.test.ts +612 -0
  307. package/src/lib/__tests__/capacity-tuning.test.ts +544 -0
  308. package/src/lib/__tests__/effective-schema.test.ts +439 -0
  309. package/src/lib/__tests__/flechette.test.ts +42 -0
  310. package/src/lib/__tests__/flushScheduler.test.ts +537 -0
  311. package/src/lib/__tests__/integration.test.ts +600 -0
  312. package/src/lib/__tests__/library.test.ts +934 -0
  313. package/src/lib/__tests__/nested-library-tasks.test.ts +849 -0
  314. package/src/lib/__tests__/op-context-binding.test.ts +135 -0
  315. package/src/lib/__tests__/op-metadata.test.ts +198 -0
  316. package/src/lib/__tests__/op-type-safety.test.ts +71 -0
  317. package/src/lib/__tests__/package-exports.test.ts +57 -0
  318. package/src/lib/__tests__/remapped-buffer-view-integration.test.ts +319 -0
  319. package/src/lib/__tests__/remapped-buffer-view.test.ts +635 -0
  320. package/src/lib/__tests__/scope-attributes.test.ts +348 -0
  321. package/src/lib/__tests__/span-lifecycle.test.ts +680 -0
  322. package/src/lib/__tests__/sync-async-trace.test.ts +435 -0
  323. package/src/lib/__tests__/test-helpers.ts +318 -0
  324. package/src/lib/__tests__/timestamp.test.ts +259 -0
  325. package/src/lib/__tests__/trace-archive-primitives.test.ts +98 -0
  326. package/src/lib/__tests__/traceContext-type-enforcement.test.ts +271 -0
  327. package/src/lib/__tests__/tracer.test.ts +211 -0
  328. package/src/lib/__tests__/type-narrowing.test.ts +137 -0
  329. package/src/lib/archive/chunkCompaction.ts +44 -0
  330. package/src/lib/archive/chunkEnvelope.ts +79 -0
  331. package/src/lib/archive/chunkRouting.ts +70 -0
  332. package/src/lib/archive/chunkStats.ts +25 -0
  333. package/src/lib/archive/index.ts +4 -0
  334. package/src/lib/arrow/capacityStats.ts +340 -0
  335. package/src/lib/arrow/dictionaries.ts +159 -0
  336. package/src/lib/arrow/flechette.ts +114 -0
  337. package/src/lib/arrow/utils.ts +126 -0
  338. package/src/lib/buffer/Nanoseconds.ts +131 -0
  339. package/src/lib/bufferStrategy.ts +106 -0
  340. package/src/lib/capacityTuning.ts +102 -0
  341. package/src/lib/codegen/__tests__/__snapshots__/evaluatorGenerator.test.ts.snap +160 -0
  342. package/src/lib/codegen/__tests__/__snapshots__/scopeGenerator.test.ts.snap +196 -0
  343. package/src/lib/codegen/__tests__/__snapshots__/spanLoggerGenerator.test.ts.snap +1965 -0
  344. package/src/lib/codegen/__tests__/evaluatorGenerator.test.ts +516 -0
  345. package/src/lib/codegen/__tests__/nullBitmap.test.ts +207 -0
  346. package/src/lib/codegen/__tests__/spanLoggerGenerator.test.ts +237 -0
  347. package/src/lib/codegen/evaluatorGenerator.ts +309 -0
  348. package/src/lib/codegen/fixedPositionWriterGenerator.ts +444 -0
  349. package/src/lib/codegen/spanLoggerGenerator.ts +715 -0
  350. package/src/lib/convertToArrow.ts +1805 -0
  351. package/src/lib/defineOpContext.ts +398 -0
  352. package/src/lib/errors/Blocked.ts +165 -0
  353. package/src/lib/errors/CodeError.ts +132 -0
  354. package/src/lib/errors/RetriesExhausted.ts +78 -0
  355. package/src/lib/errors/Transient.ts +168 -0
  356. package/src/lib/errors/__tests__/Blocked-config.test.ts +152 -0
  357. package/src/lib/errors/__tests__/Transient.test.ts +129 -0
  358. package/src/lib/errors/__tests__/retry-policy.test.ts +85 -0
  359. package/src/lib/errors/index.ts +24 -0
  360. package/src/lib/errors/retry-policy.ts +87 -0
  361. package/src/lib/flushScheduler.ts +509 -0
  362. package/src/lib/library.ts +682 -0
  363. package/src/lib/logApi.ts +70 -0
  364. package/src/lib/logBinding.ts +67 -0
  365. package/src/lib/op.ts +103 -0
  366. package/src/lib/opContext/__tests__/retry.test.ts +764 -0
  367. package/src/lib/opContext/contextTypes.ts +130 -0
  368. package/src/lib/opContext/createOpGroup.ts +456 -0
  369. package/src/lib/opContext/defineOp.ts +281 -0
  370. package/src/lib/opContext/featureFlagTypes.ts +54 -0
  371. package/src/lib/opContext/index.ts +16 -0
  372. package/src/lib/opContext/opGroupTypes.ts +342 -0
  373. package/src/lib/opContext/opTypes.ts +80 -0
  374. package/src/lib/opContext/spanContextTypes.ts +398 -0
  375. package/src/lib/opContext/types.ts +403 -0
  376. package/src/lib/result.ts +550 -0
  377. package/src/lib/schema/LogSchema.ts +153 -0
  378. package/src/lib/schema/__tests__/defineLogSchema.test.ts +342 -0
  379. package/src/lib/schema/__tests__/featureFlags.test.ts +443 -0
  380. package/src/lib/schema/builder.ts +201 -0
  381. package/src/lib/schema/defineFeatureFlags.ts +91 -0
  382. package/src/lib/schema/defineLogSchema.ts +291 -0
  383. package/src/lib/schema/evaluator.ts +404 -0
  384. package/src/lib/schema/extend.ts +69 -0
  385. package/src/lib/schema/systemSchema.ts +339 -0
  386. package/src/lib/schema/typeGuards.ts +163 -0
  387. package/src/lib/schema/types.ts +265 -0
  388. package/src/lib/spanBuffer.ts +571 -0
  389. package/src/lib/spanBufferHelpers.ts +73 -0
  390. package/src/lib/spanBufferStats.ts +40 -0
  391. package/src/lib/spanContext.ts +1566 -0
  392. package/src/lib/sqlite/__tests__/sqlite-common.test.ts +89 -0
  393. package/src/lib/sqlite/index.ts +26 -0
  394. package/src/lib/sqlite/sqlite-async-writer.ts +101 -0
  395. package/src/lib/sqlite/sqlite-common.ts +309 -0
  396. package/src/lib/sqlite/sqlite-d1.ts +104 -0
  397. package/src/lib/sqlite/sqlite-db.ts +32 -0
  398. package/src/lib/sqlite/sqlite-node.ts +83 -0
  399. package/src/lib/sqlite/sqlite-writer.ts +128 -0
  400. package/src/lib/testing/TRACE-TESTING.md +100 -0
  401. package/src/lib/testing/__tests__/bun-harness.test.ts +108 -0
  402. package/src/lib/testing/__tests__/extractFacts.test.ts +279 -0
  403. package/src/lib/testing/__tests__/facts.test.ts +324 -0
  404. package/src/lib/testing/__tests__/vitest-harness.test.ts +32 -0
  405. package/src/lib/testing/bun-harness.ts +990 -0
  406. package/src/lib/testing/extractFacts.ts +362 -0
  407. package/src/lib/testing/facts.ts +470 -0
  408. package/src/lib/testing/index.ts +141 -0
  409. package/src/lib/testing/queryable-span.ts +108 -0
  410. package/src/lib/testing/span-query.ts +65 -0
  411. package/src/lib/testing/stdio-replay.ts +50 -0
  412. package/src/lib/testing/trace-query.ts +329 -0
  413. package/src/lib/testing/vitest-harness.ts +691 -0
  414. package/src/lib/threadId.ts +135 -0
  415. package/src/lib/traceContext.ts +182 -0
  416. package/src/lib/traceId.ts +142 -0
  417. package/src/lib/traceRoot.es.ts +157 -0
  418. package/src/lib/traceRoot.node.ts +170 -0
  419. package/src/lib/traceRoot.ts +154 -0
  420. package/src/lib/traceRoot.universal.ts +22 -0
  421. package/src/lib/tracer.ts +896 -0
  422. package/src/lib/tracers/ArrayQueueTracer.ts +76 -0
  423. package/src/lib/tracers/CompositeTracer.ts +76 -0
  424. package/src/lib/tracers/NoOpTracer.ts +73 -0
  425. package/src/lib/tracers/SQLiteTracer.ts +115 -0
  426. package/src/lib/tracers/StdioTracer.ts +380 -0
  427. package/src/lib/tracers/TestTracer.ts +146 -0
  428. package/src/lib/tracers/__tests__/ArrayQueueTracer.test.ts +184 -0
  429. package/src/lib/tracers/__tests__/NoOpTracer.test.ts +204 -0
  430. package/src/lib/tracers/__tests__/StdioTracer.test.ts +313 -0
  431. package/src/lib/tracers/__tests__/TestTracer.test.ts +200 -0
  432. package/src/lib/tracers/index.ts +12 -0
  433. package/src/lib/types.ts +498 -0
  434. package/src/lib/utf8Cache.ts +201 -0
  435. package/src/lib/wasm/WasmBufferStrategy.ts +219 -0
  436. package/src/lib/wasm/__tests__/WasmBufferStrategy.test.ts +256 -0
  437. package/src/lib/wasm/__tests__/wasm-integration.test.ts +476 -0
  438. package/src/lib/wasm/__tests__/wasmAllocator.test.ts +699 -0
  439. package/src/lib/wasm/__tests__/wasmSpanBuffer.test.ts +449 -0
  440. package/src/lib/wasm/__tests__/wasmTraceRoot.test.ts +390 -0
  441. package/src/lib/wasm/__tests__/wasmTracer.test.ts.disabled +444 -0
  442. package/src/lib/wasm/allocator.zig +945 -0
  443. package/src/lib/wasm/wasmAllocator.ts +469 -0
  444. package/src/lib/wasm/wasmSpanBuffer.ts +1014 -0
  445. package/src/lib/wasm/wasmTraceRoot.ts +315 -0
  446. package/src/node.ts +10 -0
  447. package/src/testing.ts +18 -0
@@ -0,0 +1,699 @@
1
+ import { beforeEach, describe, expect, it } from 'bun:test';
2
+ import { createWasmAllocator, SizeClass, type WasmAllocator } from '../wasmAllocator.js';
3
+
4
+ describe('WasmAllocator', () => {
5
+ let allocator: WasmAllocator;
6
+
7
+ beforeEach(async () => {
8
+ allocator = await createWasmAllocator({ capacity: 64 });
9
+ });
10
+
11
+ describe('instantiation', () => {
12
+ it('creates allocator with default options', async () => {
13
+ const alloc = await createWasmAllocator();
14
+ expect(alloc).toBeDefined();
15
+ expect(alloc.memory).toBeInstanceOf(WebAssembly.Memory);
16
+ expect(alloc.u8).toBeInstanceOf(Uint8Array);
17
+ expect(alloc.u32).toBeInstanceOf(Uint32Array);
18
+ expect(alloc.i64).toBeInstanceOf(BigInt64Array);
19
+ expect(alloc.f64).toBeInstanceOf(Float64Array);
20
+ });
21
+
22
+ it('creates allocator with custom capacity', async () => {
23
+ const alloc = await createWasmAllocator({ capacity: 128 });
24
+ expect(alloc.capacity).toBe(128);
25
+ });
26
+ });
27
+
28
+ describe('init', () => {
29
+ it('initializes freelists to empty', async () => {
30
+ // Create fresh allocator
31
+ const alloc = await createWasmAllocator({ capacity: 64 });
32
+
33
+ // All freelists should be empty after init
34
+ for (const tier of [8, 16, 32, 64, 128, 256, 512]) {
35
+ for (const sc of [SizeClass.SpanSystem, SizeClass.Col1B, SizeClass.Col4B, SizeClass.Col8B]) {
36
+ const len = alloc.getFreelistLen(sc, tier);
37
+ expect(len).toBe(0);
38
+ }
39
+ }
40
+ });
41
+
42
+ it('stores default capacity', () => {
43
+ expect(allocator.capacity).toBe(64);
44
+ });
45
+
46
+ it('can create allocator with different default capacity', async () => {
47
+ const alloc128 = await createWasmAllocator({ capacity: 128 });
48
+ expect(alloc128.capacity).toBe(128);
49
+ });
50
+ });
51
+
52
+ describe('allocSpanSystem', () => {
53
+ it('returns valid offset greater than header size (192 bytes)', () => {
54
+ const offset = allocator.allocSpanSystem();
55
+ expect(offset).toBeGreaterThanOrEqual(192);
56
+ });
57
+
58
+ it('returns different offsets for multiple allocations', () => {
59
+ const offset1 = allocator.allocSpanSystem();
60
+ const offset2 = allocator.allocSpanSystem();
61
+ expect(offset1).not.toBe(offset2);
62
+ });
63
+
64
+ it('returns 8-byte aligned offsets', () => {
65
+ const offset = allocator.allocSpanSystem();
66
+ expect(offset % 8).toBe(0);
67
+ });
68
+
69
+ it('increments alloc count', () => {
70
+ const before = allocator.getAllocCount();
71
+ allocator.allocSpanSystem();
72
+ expect(allocator.getAllocCount()).toBe(before + 1);
73
+ });
74
+ });
75
+
76
+ describe('freelist reuse', () => {
77
+ it('reuses freed SpanSystem offset', () => {
78
+ const offset1 = allocator.allocSpanSystem();
79
+ allocator.freeSpanSystem(offset1);
80
+ const offset2 = allocator.allocSpanSystem();
81
+ expect(offset2).toBe(offset1);
82
+ });
83
+
84
+ it('reuses freed 1B column offset', () => {
85
+ const offset1 = allocator.alloc1B();
86
+ allocator.free1B(offset1);
87
+ const offset2 = allocator.alloc1B();
88
+ expect(offset2).toBe(offset1);
89
+ });
90
+
91
+ it('reuses freed 4B column offset', () => {
92
+ const offset1 = allocator.alloc4B();
93
+ allocator.free4B(offset1);
94
+ const offset2 = allocator.alloc4B();
95
+ expect(offset2).toBe(offset1);
96
+ });
97
+
98
+ it('reuses freed 8B column offset', () => {
99
+ const offset1 = allocator.alloc8B();
100
+ allocator.free8B(offset1);
101
+ const offset2 = allocator.alloc8B();
102
+ expect(offset2).toBe(offset1);
103
+ });
104
+
105
+ it('reuses freed identity block offset', () => {
106
+ const offset1 = allocator.allocIdentityChild();
107
+ allocator.freeIdentity(offset1);
108
+ const offset2 = allocator.allocIdentityChild();
109
+ expect(offset2).toBe(offset1);
110
+ });
111
+
112
+ it('increments free count', () => {
113
+ const offset = allocator.allocSpanSystem();
114
+ const before = allocator.getFreeCount();
115
+ allocator.freeSpanSystem(offset);
116
+ expect(allocator.getFreeCount()).toBe(before + 1);
117
+ });
118
+ });
119
+
120
+ describe('reset', () => {
121
+ it('clears freelists and resets bump ptr to header', () => {
122
+ // Allocate some blocks
123
+ allocator.allocSpanSystem();
124
+ allocator.alloc1B();
125
+ allocator.alloc4B();
126
+ allocator.alloc8B();
127
+
128
+ const bumpBefore = allocator.getBumpPtr();
129
+ expect(bumpBefore).toBeGreaterThan(192);
130
+
131
+ // Reset
132
+ allocator.reset();
133
+
134
+ // Bump ptr should be back at header (192 bytes)
135
+ expect(allocator.getBumpPtr()).toBe(192);
136
+ expect(allocator.getAllocCount()).toBe(0);
137
+ expect(allocator.getFreeCount()).toBe(0);
138
+ });
139
+ });
140
+
141
+ describe('span lifecycle', () => {
142
+ it('spanStart writes entry_type=1 at row 0', () => {
143
+ const systemPtr = allocator.allocSpanSystem();
144
+ const identityPtr = allocator.allocIdentityChild();
145
+ const traceRootPtr = allocator.alloc8B();
146
+ allocator.initTraceRoot(traceRootPtr);
147
+
148
+ allocator.spanStart(systemPtr, identityPtr, traceRootPtr);
149
+
150
+ expect(allocator.readEntryType(systemPtr, 0)).toBe(1); // SPAN_START
151
+ });
152
+
153
+ it('spanStart sets entry_type=4 (SPAN_EXCEPTION) at row 1 as placeholder', () => {
154
+ const systemPtr = allocator.allocSpanSystem();
155
+ const identityPtr = allocator.allocIdentityChild();
156
+ const traceRootPtr = allocator.alloc8B();
157
+ allocator.initTraceRoot(traceRootPtr);
158
+
159
+ allocator.spanStart(systemPtr, identityPtr, traceRootPtr);
160
+
161
+ expect(allocator.readEntryType(systemPtr, 1)).toBe(4); // SPAN_EXCEPTION placeholder
162
+ });
163
+
164
+ it('spanStart sets writeIndex to 2', () => {
165
+ const systemPtr = allocator.allocSpanSystem();
166
+ const identityPtr = allocator.allocIdentityChild();
167
+ const traceRootPtr = allocator.alloc8B();
168
+ allocator.initTraceRoot(traceRootPtr);
169
+
170
+ allocator.spanStart(systemPtr, identityPtr, traceRootPtr);
171
+
172
+ expect(allocator.readWriteIndex(identityPtr)).toBe(2);
173
+ });
174
+
175
+ it('spanEndOk writes entry_type=2 at row 1', () => {
176
+ const systemPtr = allocator.allocSpanSystem();
177
+ const identityPtr = allocator.allocIdentityChild();
178
+ const traceRootPtr = allocator.alloc8B();
179
+ allocator.initTraceRoot(traceRootPtr);
180
+
181
+ allocator.spanStart(systemPtr, identityPtr, traceRootPtr);
182
+ allocator.spanEndOk(systemPtr, traceRootPtr);
183
+
184
+ expect(allocator.readEntryType(systemPtr, 1)).toBe(2); // SPAN_OK
185
+ });
186
+
187
+ it('spanEndErr writes entry_type=3 at row 1', () => {
188
+ const systemPtr = allocator.allocSpanSystem();
189
+ const identityPtr = allocator.allocIdentityChild();
190
+ const traceRootPtr = allocator.alloc8B();
191
+ allocator.initTraceRoot(traceRootPtr);
192
+
193
+ allocator.spanStart(systemPtr, identityPtr, traceRootPtr);
194
+ allocator.spanEndErr(systemPtr, traceRootPtr);
195
+
196
+ expect(allocator.readEntryType(systemPtr, 1)).toBe(3); // SPAN_ERR
197
+ });
198
+
199
+ it('spanStart writes timestamp at row 0', () => {
200
+ const systemPtr = allocator.allocSpanSystem();
201
+ const identityPtr = allocator.allocIdentityChild();
202
+ const traceRootPtr = allocator.alloc8B();
203
+ allocator.initTraceRoot(traceRootPtr);
204
+
205
+ allocator.spanStart(systemPtr, identityPtr, traceRootPtr);
206
+
207
+ const timestamp = allocator.readTimestamp(systemPtr, 0);
208
+ expect(timestamp).toBeGreaterThan(0n);
209
+ });
210
+
211
+ it('spanEndOk writes timestamp at row 1', () => {
212
+ const systemPtr = allocator.allocSpanSystem();
213
+ const identityPtr = allocator.allocIdentityChild();
214
+ const traceRootPtr = allocator.alloc8B();
215
+ allocator.initTraceRoot(traceRootPtr);
216
+
217
+ allocator.spanStart(systemPtr, identityPtr, traceRootPtr);
218
+ allocator.spanEndOk(systemPtr, traceRootPtr);
219
+
220
+ const timestamp = allocator.readTimestamp(systemPtr, 1);
221
+ expect(timestamp).toBeGreaterThan(0n);
222
+ });
223
+ });
224
+
225
+ describe('writeLogEntry', () => {
226
+ it('writes log entry and returns row index', () => {
227
+ const systemPtr = allocator.allocSpanSystem();
228
+ const identityPtr = allocator.allocIdentityChild();
229
+ const traceRootPtr = allocator.alloc8B();
230
+ allocator.initTraceRoot(traceRootPtr);
231
+ allocator.spanStart(systemPtr, identityPtr, traceRootPtr);
232
+
233
+ // _writeIndex starts at 2 after spanStart
234
+ const rowIdx = allocator.writeLogEntry(systemPtr, identityPtr, traceRootPtr, 6); // INFO = 6
235
+
236
+ expect(rowIdx).toBe(2);
237
+ expect(allocator.readEntryType(systemPtr, 2)).toBe(6);
238
+ expect(allocator.readWriteIndex(identityPtr)).toBe(3);
239
+ });
240
+
241
+ it('increments writeIndex for each log entry', () => {
242
+ const systemPtr = allocator.allocSpanSystem();
243
+ const identityPtr = allocator.allocIdentityChild();
244
+ const traceRootPtr = allocator.alloc8B();
245
+ allocator.initTraceRoot(traceRootPtr);
246
+ allocator.spanStart(systemPtr, identityPtr, traceRootPtr);
247
+
248
+ const idx1 = allocator.writeLogEntry(systemPtr, identityPtr, traceRootPtr, 6);
249
+ const idx2 = allocator.writeLogEntry(systemPtr, identityPtr, traceRootPtr, 7);
250
+ const idx3 = allocator.writeLogEntry(systemPtr, identityPtr, traceRootPtr, 8);
251
+
252
+ expect(idx1).toBe(2);
253
+ expect(idx2).toBe(3);
254
+ expect(idx3).toBe(4);
255
+ expect(allocator.readWriteIndex(identityPtr)).toBe(5);
256
+ });
257
+ });
258
+
259
+ describe('column writes', () => {
260
+ it('writeColF64 allocates and writes value', () => {
261
+ let colOffset = 0;
262
+ colOffset = allocator.writeColF64(colOffset, 0, 3.14);
263
+
264
+ expect(colOffset).toBeGreaterThan(0);
265
+ expect(allocator.readColF64(colOffset, 0)).toBeCloseTo(3.14);
266
+ expect(allocator.readColIsValid(colOffset, 0)).toBe(1);
267
+ });
268
+
269
+ it('writeColF64 writes to existing column', () => {
270
+ let colOffset = allocator.writeColF64(0, 0, 1.0);
271
+ colOffset = allocator.writeColF64(colOffset, 1, 2.0);
272
+ allocator.writeColF64(colOffset, 2, 3.0);
273
+
274
+ expect(allocator.readColF64(colOffset, 0)).toBeCloseTo(1.0);
275
+ expect(allocator.readColF64(colOffset, 1)).toBeCloseTo(2.0);
276
+ expect(allocator.readColF64(colOffset, 2)).toBeCloseTo(3.0);
277
+ });
278
+
279
+ it('writeColU32 allocates and writes value', () => {
280
+ let colOffset = 0;
281
+ colOffset = allocator.writeColU32(colOffset, 0, 42);
282
+
283
+ expect(colOffset).toBeGreaterThan(0);
284
+ // Read via u32 view
285
+ const nullBitmapSize = Math.ceil(64 / 8); // capacity / 8
286
+ const valueOffset = (colOffset + nullBitmapSize) / 4; // convert to u32 index
287
+ expect(allocator.u32[valueOffset]).toBe(42);
288
+ });
289
+
290
+ it('writeColU8 allocates and writes value', () => {
291
+ let colOffset = 0;
292
+ colOffset = allocator.writeColU8(colOffset, 0, 255);
293
+
294
+ expect(colOffset).toBeGreaterThan(0);
295
+ // Read via u8 view
296
+ const nullBitmapSize = Math.ceil(64 / 8); // capacity / 8
297
+ expect(allocator.u8[colOffset + nullBitmapSize]).toBe(255);
298
+ });
299
+
300
+ it('writeColF64 sets null bit (validity)', () => {
301
+ const colOffset = allocator.writeColF64(0, 5, 99.9);
302
+
303
+ // Check that row 5 is marked valid
304
+ expect(allocator.readColIsValid(colOffset, 5)).toBe(1);
305
+ // Check that row 0 is not valid (we didn't write to it)
306
+ expect(allocator.readColIsValid(colOffset, 0)).toBe(0);
307
+ });
308
+ });
309
+
310
+ describe('TraceRoot', () => {
311
+ it('initTraceRoot sets wall clock and monotonic time', () => {
312
+ const traceRootPtr = allocator.alloc8B(); // 8B column is large enough for 16 bytes
313
+ const before = Date.now();
314
+
315
+ allocator.initTraceRoot(traceRootPtr);
316
+
317
+ // Read wall clock (first 8 bytes as i64 nanoseconds)
318
+ const wallClockNanos = allocator.i64[traceRootPtr / 8];
319
+ const wallClockMs = Number(wallClockNanos / 1_000_000n);
320
+
321
+ expect(wallClockMs).toBeGreaterThanOrEqual(before);
322
+ expect(wallClockMs).toBeLessThan(before + 1000); // Within 1 second
323
+
324
+ // Read monotonic time (next 8 bytes as f64 milliseconds)
325
+ const monotonicMs = allocator.f64[(traceRootPtr + 8) / 8];
326
+ expect(monotonicMs).toBeGreaterThan(0);
327
+ });
328
+ });
329
+
330
+ describe('identity block', () => {
331
+ it('allocIdentityChild returns valid offset', () => {
332
+ const identityPtr = allocator.allocIdentityChild();
333
+ expect(identityPtr).toBeGreaterThanOrEqual(192);
334
+ });
335
+
336
+ it('allocIdentityChild returns unique span_id for each allocation', () => {
337
+ const id1 = allocator.allocIdentityChild();
338
+ const id2 = allocator.allocIdentityChild();
339
+
340
+ const spanId1 = allocator.readIdentitySpanId(id1);
341
+ const spanId2 = allocator.readIdentitySpanId(id2);
342
+
343
+ expect(spanId1).toBeGreaterThan(0);
344
+ expect(spanId2).toBeGreaterThan(spanId1);
345
+ });
346
+
347
+ it('allocIdentityRootForJsWrite stores trace_id', () => {
348
+ const traceId = 'test-trace-id-123';
349
+ const traceIdBytes = new TextEncoder().encode(traceId);
350
+
351
+ const packed = allocator.allocIdentityRootForJsWrite(traceIdBytes.length);
352
+ const identityPtr = Number(packed >> 32n);
353
+ const traceIdOffset = Number(packed & 0xffffffffn);
354
+
355
+ allocator.u8.set(traceIdBytes, traceIdOffset);
356
+
357
+ expect(allocator.readIdentityTraceIdLen(identityPtr)).toBe(traceIdBytes.length);
358
+
359
+ const storedTraceIdPtr = allocator.getIdentityTraceIdPtr(identityPtr);
360
+ const storedBytes = allocator.u8.slice(storedTraceIdPtr, storedTraceIdPtr + traceIdBytes.length);
361
+ const storedTraceId = new TextDecoder().decode(storedBytes);
362
+ expect(storedTraceId).toBe(traceId);
363
+ });
364
+ });
365
+
366
+ describe('block sizes', () => {
367
+ it('reports correct span system size for capacity 64', () => {
368
+ // capacity × 9 bytes (timestamp + entry_type, writeIndex moved to identity)
369
+ // 64 × 9 = 576, aligned to 8 = 576
370
+ expect(allocator.getSpanSystemSize()).toBe(576);
371
+ });
372
+
373
+ it('reports correct 1B column size for capacity 64', () => {
374
+ // ceil(capacity/8) + capacity × 1
375
+ // ceil(64/8) + 64 = 8 + 64 = 72
376
+ expect(allocator.getCol1BSize()).toBe(72);
377
+ });
378
+
379
+ it('reports correct 4B column size for capacity 64', () => {
380
+ // ceil(capacity/8) + capacity × 4
381
+ // 8 + 256 = 264
382
+ expect(allocator.getCol4BSize()).toBe(264);
383
+ });
384
+
385
+ it('reports correct 8B column size for capacity 64', () => {
386
+ // ceil(capacity/8) + capacity × 8
387
+ // 8 + 512 = 520
388
+ expect(allocator.getCol8BSize()).toBe(520);
389
+ });
390
+ });
391
+
392
+ describe('freelist statistics', () => {
393
+ it('getFreelistLen returns 0 for empty freelist', () => {
394
+ // Fresh allocator, no frees yet
395
+ expect(allocator.getFreelistLen(SizeClass.SpanSystem)).toBe(0);
396
+ expect(allocator.getFreelistLen(SizeClass.Col1B)).toBe(0);
397
+ expect(allocator.getFreelistLen(SizeClass.Col4B)).toBe(0);
398
+ expect(allocator.getFreelistLen(SizeClass.Col8B)).toBe(0);
399
+ });
400
+
401
+ it('getFreelistLen increments on free at max tier', async () => {
402
+ // Use max tier (512) to avoid buddy split/merge behavior
403
+ const alloc = await createWasmAllocator({ capacity: 512 });
404
+
405
+ // Allocate 2 blocks at max tier (bump allocates directly, no split)
406
+ const offset1 = alloc.allocSpanSystem(512);
407
+ const offset2 = alloc.allocSpanSystem(512);
408
+
409
+ expect(alloc.getFreelistLen(SizeClass.SpanSystem, 512)).toBe(0);
410
+
411
+ alloc.freeSpanSystem(offset1, 512);
412
+ expect(alloc.getFreelistLen(SizeClass.SpanSystem, 512)).toBe(1);
413
+
414
+ alloc.freeSpanSystem(offset2, 512);
415
+ // No merge at max tier, both should be in freelist
416
+ expect(alloc.getFreelistLen(SizeClass.SpanSystem, 512)).toBe(2);
417
+ });
418
+
419
+ it('getFreelistReuseCount increments on alloc from freelist', async () => {
420
+ // Use max tier (512) to avoid buddy split/merge behavior
421
+ const alloc = await createWasmAllocator({ capacity: 512 });
422
+
423
+ // Allocate 2 blocks at max tier
424
+ const offset1 = alloc.allocSpanSystem(512);
425
+ const offset2 = alloc.allocSpanSystem(512);
426
+
427
+ // Free both (no merge at max tier)
428
+ alloc.freeSpanSystem(offset1, 512);
429
+ alloc.freeSpanSystem(offset2, 512);
430
+
431
+ expect(alloc.getFreelistLen(SizeClass.SpanSystem, 512)).toBe(2);
432
+ expect(alloc.getFreelistReuseCount(SizeClass.SpanSystem, 512)).toBe(0);
433
+
434
+ // Alloc from freelist - should increment reuse count
435
+ alloc.allocSpanSystem(512);
436
+ expect(alloc.getFreelistReuseCount(SizeClass.SpanSystem, 512)).toBe(1);
437
+
438
+ alloc.allocSpanSystem(512);
439
+ // Freelist empty now, so reuse count stays at previous HEAD value
440
+ expect(alloc.getFreelistReuseCount(SizeClass.SpanSystem, 512)).toBe(0); // empty freelist returns 0
441
+ });
442
+
443
+ it('cascading stats accumulate correctly', async () => {
444
+ // Use fresh allocator to avoid interference from other tests
445
+ const freshAlloc = await createWasmAllocator({ capacity: 64 });
446
+
447
+ // Allocate 6 blocks - keep every other one to prevent merge on free
448
+ const offsets: number[] = [];
449
+ const keepers: number[] = [];
450
+ for (let i = 0; i < 12; i++) {
451
+ const offset = freshAlloc.alloc8B();
452
+ if (i % 2 === 0) {
453
+ offsets.push(offset);
454
+ } else {
455
+ keepers.push(offset);
456
+ }
457
+ }
458
+
459
+ // Free the 6 non-adjacent blocks (they can't merge because keepers are between them)
460
+ for (const offset of offsets) {
461
+ freshAlloc.free8B(offset);
462
+ }
463
+
464
+ expect(freshAlloc.getFreelistLen(SizeClass.Col8B)).toBe(6);
465
+
466
+ // Allocate 4 back
467
+ freshAlloc.alloc8B();
468
+ freshAlloc.alloc8B();
469
+ freshAlloc.alloc8B();
470
+ freshAlloc.alloc8B();
471
+
472
+ expect(freshAlloc.getFreelistLen(SizeClass.Col8B)).toBe(2); // 6 - 4 = 2 remaining
473
+ expect(freshAlloc.getFreelistReuseCount(SizeClass.Col8B)).toBe(4); // 4 reuses
474
+ });
475
+ });
476
+
477
+ describe('buddy allocation', () => {
478
+ it('splits larger tier block when current tier freelist is empty', async () => {
479
+ // Create allocator
480
+ const alloc = await createWasmAllocator({ capacity: 32 });
481
+
482
+ // Allocate at capacity 64 (tier 3) and free it
483
+ const largeOffset = alloc.allocSpanSystem(64);
484
+ alloc.freeSpanSystem(largeOffset, 64);
485
+
486
+ // Freelist for tier 2 is empty, but tier 3 has a block
487
+ // Buddy split should occur when allocating at capacity 32
488
+ const offset1 = alloc.allocSpanSystem(32);
489
+ expect(offset1).toBe(largeOffset); // First half of split block
490
+
491
+ // Second half should now be in freelist at tier 2 (capacity 32)
492
+ expect(alloc.getFreelistLen(SizeClass.SpanSystem, 32)).toBe(1);
493
+
494
+ // Split count should be 1
495
+ expect(alloc.getFreelistSplitCount(SizeClass.SpanSystem, 32)).toBe(1);
496
+
497
+ // Allocate again - should get second half from freelist
498
+ const offset2 = alloc.allocSpanSystem(32);
499
+ expect(offset2).toBe(largeOffset + alloc.getSpanSystemSize(32));
500
+ });
501
+
502
+ describe('buddy merge', () => {
503
+ it('basic freelist push/pop at max tier works correctly', async () => {
504
+ // Use max tier (512) to avoid split behavior
505
+ const alloc = await createWasmAllocator({ capacity: 512 });
506
+
507
+ // Allocate at max capacity (tier 6) - bump allocates directly
508
+ const offset = alloc.allocSpanSystem(512);
509
+ expect(alloc.getFreelistLen(SizeClass.SpanSystem, 512)).toBe(0); // Just allocated, freelist empty
510
+
511
+ alloc.freeSpanSystem(offset, 512);
512
+ expect(alloc.getFreelistLen(SizeClass.SpanSystem, 512)).toBe(1); // Freed, freelist has 1
513
+
514
+ // Allocate again - should get same offset from freelist
515
+ const offset2 = alloc.allocSpanSystem(512);
516
+ expect(offset2).toBe(offset);
517
+ expect(alloc.getFreelistLen(SizeClass.SpanSystem, 512)).toBe(0); // Popped, freelist empty
518
+ });
519
+
520
+ it('free at tier 6 (max) pushes correctly', async () => {
521
+ const alloc = await createWasmAllocator({ capacity: 512 });
522
+
523
+ // Allocate at max capacity (tier 6)
524
+ const offset = alloc.allocSpanSystem(512);
525
+ expect(alloc.getFreelistLen(SizeClass.SpanSystem, 512)).toBe(0);
526
+
527
+ // Free at capacity 512 (tier 6) - should NOT try to merge (no higher tier)
528
+ alloc.freeSpanSystem(offset, 512);
529
+ expect(alloc.getFreelistLen(SizeClass.SpanSystem, 512)).toBe(1);
530
+ });
531
+
532
+ it('adjacent blocks cascade merge to max tier', async () => {
533
+ const alloc = await createWasmAllocator({ capacity: 32 });
534
+
535
+ // Allocate two tier-3 blocks
536
+ const block1 = alloc.allocSpanSystem(64);
537
+ const block2 = alloc.allocSpanSystem(64);
538
+
539
+ // Verify they're adjacent
540
+ expect(block2).toBe(block1 + alloc.getSpanSystemSize(64));
541
+
542
+ // Free both - should cascade merge all the way to max tier
543
+ alloc.freeSpanSystem(block1, 64);
544
+ alloc.freeSpanSystem(block2, 64);
545
+
546
+ // After cascade, only max tier should have the block
547
+ expect(alloc.getFreelistLen(SizeClass.SpanSystem, 64)).toBe(0);
548
+ expect(alloc.getFreelistLen(SizeClass.SpanSystem, 512)).toBe(1);
549
+ });
550
+
551
+ it('merges adjacent blocks when both are freed (cascading)', async () => {
552
+ // Create allocator
553
+ const alloc = await createWasmAllocator({ capacity: 32 });
554
+
555
+ // Allocate two capacity-32 blocks (which splits all the way from max tier)
556
+ const child1 = alloc.allocSpanSystem(32);
557
+ const child2 = alloc.allocSpanSystem(32);
558
+
559
+ // Verify they're adjacent
560
+ expect(child2).toBe(child1 + alloc.getSpanSystemSize(32));
561
+
562
+ // Free both - they should merge and cascade up to max tier
563
+ alloc.freeSpanSystem(child2, 32);
564
+ expect(alloc.getFreelistLen(SizeClass.SpanSystem, 32)).toBe(1); // child2 in tier-2
565
+
566
+ alloc.freeSpanSystem(child1, 32);
567
+
568
+ // After merge cascade, tier-2 should be empty
569
+ expect(alloc.getFreelistLen(SizeClass.SpanSystem, 32)).toBe(0);
570
+
571
+ // The merge cascades all the way to max tier (512) because there are
572
+ // sibling blocks at each tier from the original split
573
+ expect(alloc.getFreelistLen(SizeClass.SpanSystem, 512)).toBe(1);
574
+ });
575
+
576
+ it('merges regardless of free order', async () => {
577
+ // Create allocator
578
+ const alloc = await createWasmAllocator({ capacity: 32 });
579
+
580
+ // Allocate two capacity-32 blocks
581
+ const child1 = alloc.allocSpanSystem(32);
582
+ const child2 = alloc.allocSpanSystem(32);
583
+
584
+ // Free in opposite order (child1 first instead of child2)
585
+ alloc.freeSpanSystem(child1, 32);
586
+ expect(alloc.getFreelistLen(SizeClass.SpanSystem, 32)).toBe(1);
587
+
588
+ alloc.freeSpanSystem(child2, 32);
589
+
590
+ // After merge cascade, tier-2 should be empty
591
+ expect(alloc.getFreelistLen(SizeClass.SpanSystem, 32)).toBe(0);
592
+
593
+ // Cascades to max tier
594
+ expect(alloc.getFreelistLen(SizeClass.SpanSystem, 512)).toBe(1);
595
+ });
596
+
597
+ it('cascading merge: all the way to max tier', async () => {
598
+ // Create allocator
599
+ const alloc = await createWasmAllocator({ capacity: 16 });
600
+
601
+ // Allocate 4 blocks at capacity 16 (splits from max tier)
602
+ const blockSize16 = alloc.getSpanSystemSize(16);
603
+
604
+ const blocks = [
605
+ alloc.allocSpanSystem(16),
606
+ alloc.allocSpanSystem(16),
607
+ alloc.allocSpanSystem(16),
608
+ alloc.allocSpanSystem(16),
609
+ ];
610
+
611
+ // Verify offsets are sequential
612
+ expect(blocks[1]).toBe(blocks[0] + blockSize16);
613
+ expect(blocks[2]).toBe(blocks[0] + blockSize16 * 2);
614
+ expect(blocks[3]).toBe(blocks[0] + blockSize16 * 3);
615
+
616
+ // Free all 4 blocks - should cascade merge all the way to max tier
617
+ for (const offset of blocks) {
618
+ alloc.freeSpanSystem(offset, 16);
619
+ }
620
+
621
+ // After full cascade, should end up at max tier (512)
622
+ expect(alloc.getFreelistLen(SizeClass.SpanSystem, 512)).toBe(1);
623
+ });
624
+
625
+ it('partial merge when not all siblings freed', async () => {
626
+ const alloc = await createWasmAllocator({ capacity: 16 });
627
+
628
+ // Allocate 4 blocks at capacity 16
629
+ const blocks = [
630
+ alloc.allocSpanSystem(16),
631
+ alloc.allocSpanSystem(16),
632
+ alloc.allocSpanSystem(16),
633
+ alloc.allocSpanSystem(16),
634
+ ];
635
+
636
+ // Free only first two - should merge to tier-2 (capacity 32) but stop there
637
+ // because blocks[2] and [3] are still allocated
638
+ alloc.freeSpanSystem(blocks[0], 16);
639
+ alloc.freeSpanSystem(blocks[1], 16);
640
+
641
+ // Tier-1 (16) should be empty (merged)
642
+ expect(alloc.getFreelistLen(SizeClass.SpanSystem, 16)).toBe(0);
643
+
644
+ // Since blocks[2] and [3] are still allocated, merge should stop
645
+ // somewhere in the middle, not reach max tier
646
+ expect(alloc.getFreelistLen(SizeClass.SpanSystem, 512)).toBe(0);
647
+ });
648
+
649
+ it('merge count accumulates correctly', async () => {
650
+ const alloc = await createWasmAllocator({ capacity: 32 });
651
+
652
+ // Allocate and free at max tier to get a clean baseline
653
+ const block1 = alloc.allocSpanSystem(512);
654
+ const block2 = alloc.allocSpanSystem(512);
655
+ alloc.freeSpanSystem(block1, 512);
656
+ alloc.freeSpanSystem(block2, 512);
657
+
658
+ // Now tier-6 has 2 blocks (no merge possible at max tier)
659
+ expect(alloc.getFreelistLen(SizeClass.SpanSystem, 512)).toBe(2);
660
+
661
+ // Merge count at max tier should still be 0 (no merges at max tier)
662
+ expect(alloc.getFreelistMergeCount(SizeClass.SpanSystem, 512)).toBe(0);
663
+ });
664
+ });
665
+ });
666
+
667
+ describe('memory growth', () => {
668
+ it('grows memory when bump allocation exceeds current size', async () => {
669
+ // Start with minimal memory (17 pages = ~1MB)
670
+ const alloc = await createWasmAllocator({ initialPages: 17, capacity: 512 });
671
+
672
+ const initialBump = alloc.getBumpPtr();
673
+ const blockSize = alloc.getSpanSystemSize(); // 512 * 9 = 4608 bytes per block
674
+
675
+ // Allocate enough blocks to exceed initial memory
676
+ // 17 pages = 17 * 64KB = 1,114,112 bytes
677
+ // Each block is ~4608 bytes, so ~242 blocks to fill initial memory
678
+ const blocksToAllocate = 300; // More than fits in initial memory
679
+
680
+ const offsets: number[] = [];
681
+ for (let i = 0; i < blocksToAllocate; i++) {
682
+ const offset = alloc.allocSpanSystem();
683
+ expect(offset).toBeGreaterThan(0); // Should not fail
684
+ offsets.push(offset);
685
+ }
686
+
687
+ // Bump pointer should have grown well beyond initial memory
688
+ const finalBump = alloc.getBumpPtr();
689
+ const totalAllocated = finalBump - initialBump;
690
+
691
+ // We should have allocated roughly blocksToAllocate * blockSize bytes
692
+ expect(totalAllocated).toBeGreaterThan(blocksToAllocate * blockSize * 0.9);
693
+
694
+ // Memory should have grown (check that last offset is valid by writing to it)
695
+ const lastOffset = offsets[offsets.length - 1];
696
+ expect(lastOffset).toBeGreaterThan(17 * 65536); // Beyond initial 17 pages
697
+ });
698
+ });
699
+ });