@smoothbricks/lmao 0.2.2 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/allocator.wasm +0 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/lib/JsBufferStrategy.d.ts +4 -3
- package/dist/lib/JsBufferStrategy.d.ts.map +1 -1
- package/dist/lib/JsBufferStrategy.js +18 -11
- package/dist/lib/arrow/lease.d.ts +10 -0
- package/dist/lib/arrow/lease.d.ts.map +1 -0
- package/dist/lib/arrow/lease.js +33 -0
- package/dist/lib/arrow/utils.d.ts +3 -4
- package/dist/lib/arrow/utils.d.ts.map +1 -1
- package/dist/lib/arrow/utils.js +12 -13
- package/dist/lib/arrow/vocabularyDictionary.d.ts +21 -0
- package/dist/lib/arrow/vocabularyDictionary.d.ts.map +1 -0
- package/dist/lib/arrow/vocabularyDictionary.js +95 -0
- package/dist/lib/bufferStrategy.d.ts +3 -2
- package/dist/lib/bufferStrategy.d.ts.map +1 -1
- package/dist/lib/cloudflare/traceRows.d.ts.map +1 -1
- package/dist/lib/cloudflare/traceRows.js +3 -2
- package/dist/lib/codegen/evaluatorGenerator.d.ts.map +1 -1
- package/dist/lib/codegen/evaluatorGenerator.js +12 -11
- package/dist/lib/codegen/fixedPositionWriterGenerator.d.ts +44 -82
- package/dist/lib/codegen/fixedPositionWriterGenerator.d.ts.map +1 -1
- package/dist/lib/codegen/fixedPositionWriterGenerator.js +223 -162
- package/dist/lib/codegen/spanLoggerClosureMaterializer.d.ts +63 -0
- package/dist/lib/codegen/spanLoggerClosureMaterializer.d.ts.map +1 -0
- package/dist/lib/codegen/spanLoggerClosureMaterializer.js +447 -0
- package/dist/lib/codegen/spanLoggerGenerator.d.ts +36 -19
- package/dist/lib/codegen/spanLoggerGenerator.d.ts.map +1 -1
- package/dist/lib/codegen/spanLoggerGenerator.js +164 -158
- package/dist/lib/convertToArrow.d.ts +7 -2
- package/dist/lib/convertToArrow.d.ts.map +1 -1
- package/dist/lib/convertToArrow.js +499 -285
- package/dist/lib/defineOpContext.js +1 -1
- package/dist/lib/enumMetadata.d.ts +19 -0
- package/dist/lib/enumMetadata.d.ts.map +1 -0
- package/dist/lib/enumMetadata.js +86 -0
- package/dist/lib/flushScheduler.d.ts.map +1 -1
- package/dist/lib/flushScheduler.js +13 -4
- package/dist/lib/library.d.ts +16 -98
- package/dist/lib/library.d.ts.map +1 -1
- package/dist/lib/library.js +32 -525
- package/dist/lib/logBinding.d.ts +21 -27
- package/dist/lib/logBinding.d.ts.map +1 -1
- package/dist/lib/op.d.ts +30 -30
- package/dist/lib/op.d.ts.map +1 -1
- package/dist/lib/op.js +15 -22
- package/dist/lib/opContext/createOpGroup.d.ts +1 -1
- package/dist/lib/opContext/createOpGroup.d.ts.map +1 -1
- package/dist/lib/opContext/createOpGroup.js +22 -29
- package/dist/lib/opContext/defineOp.d.ts +4 -4
- package/dist/lib/opContext/defineOp.d.ts.map +1 -1
- package/dist/lib/opContext/defineOp.js +53 -10
- package/dist/lib/opContext/opGroupTypes.d.ts +2 -2
- package/dist/lib/opContext/opTypes.d.ts +1 -1
- package/dist/lib/opContext/opTypes.d.ts.map +1 -1
- package/dist/lib/opContext/spanContextTypes.d.ts +29 -14
- package/dist/lib/opContext/spanContextTypes.d.ts.map +1 -1
- package/dist/lib/opContext/types.d.ts +4 -4
- package/dist/lib/opContext/types.d.ts.map +1 -1
- package/dist/lib/physicalLayoutPlan.d.ts +89 -0
- package/dist/lib/physicalLayoutPlan.d.ts.map +1 -0
- package/dist/lib/physicalLayoutPlan.js +442 -0
- package/dist/lib/resolveMessage.d.ts +9 -0
- package/dist/lib/resolveMessage.d.ts.map +1 -0
- package/dist/lib/resolveMessage.js +63 -0
- package/dist/lib/result.d.ts +5 -7
- package/dist/lib/result.d.ts.map +1 -1
- package/dist/lib/result.js +19 -26
- package/dist/lib/runtimeHint.d.ts +35 -0
- package/dist/lib/runtimeHint.d.ts.map +1 -0
- package/dist/lib/runtimeHint.js +79 -0
- package/dist/lib/schema/types.d.ts +1 -1
- package/dist/lib/schema/types.d.ts.map +1 -1
- package/dist/lib/span-buffer/aot/v1.d.ts +2 -0
- package/dist/lib/span-buffer/aot/v1.d.ts.map +1 -0
- package/dist/lib/span-buffer/aot/v1.js +24 -0
- package/dist/lib/spanBuffer.d.ts +33 -4
- package/dist/lib/spanBuffer.d.ts.map +1 -1
- package/dist/lib/spanBuffer.js +583 -91
- package/dist/lib/spanBufferStats.d.ts +1 -1
- package/dist/lib/spanBufferStats.d.ts.map +1 -1
- package/dist/lib/spanContext.d.ts +27 -51
- package/dist/lib/spanContext.d.ts.map +1 -1
- package/dist/lib/spanContext.js +822 -344
- package/dist/lib/sqlite/sqlite-common.d.ts.map +1 -1
- package/dist/lib/sqlite/sqlite-common.js +20 -21
- package/dist/lib/testing/bun-harness.d.ts +8 -3
- package/dist/lib/testing/bun-harness.d.ts.map +1 -1
- package/dist/lib/testing/bun-harness.js +30 -18
- package/dist/lib/testing/extractFacts.d.ts +1 -1
- package/dist/lib/testing/extractFacts.d.ts.map +1 -1
- package/dist/lib/testing/extractFacts.js +55 -63
- package/dist/lib/testing/facts.d.ts +1 -1
- package/dist/lib/testing/facts.d.ts.map +1 -1
- package/dist/lib/testing/queryable-span.d.ts +1 -1
- package/dist/lib/testing/queryable-span.d.ts.map +1 -1
- package/dist/lib/testing/queryable-span.js +26 -28
- package/dist/lib/testing/span-query.d.ts.map +1 -1
- package/dist/lib/testing/span-query.js +19 -22
- package/dist/lib/testing/stdio-replay.d.ts.map +1 -1
- package/dist/lib/testing/stdio-replay.js +19 -8
- package/dist/lib/threadId.d.ts.map +1 -1
- package/dist/lib/threadId.js +6 -3
- package/dist/lib/traceRoot.d.ts +30 -8
- package/dist/lib/traceRoot.d.ts.map +1 -1
- package/dist/lib/traceRoot.es.d.ts +17 -15
- package/dist/lib/traceRoot.es.d.ts.map +1 -1
- package/dist/lib/traceRoot.es.js +68 -34
- package/dist/lib/traceRoot.js +11 -0
- package/dist/lib/traceRoot.node.d.ts +17 -19
- package/dist/lib/traceRoot.node.d.ts.map +1 -1
- package/dist/lib/traceRoot.node.js +66 -38
- package/dist/lib/traceTopology.d.ts +42 -0
- package/dist/lib/traceTopology.d.ts.map +1 -0
- package/dist/lib/traceTopology.js +260 -0
- package/dist/lib/tracer.d.ts +9 -5
- package/dist/lib/tracer.d.ts.map +1 -1
- package/dist/lib/tracer.js +65 -71
- package/dist/lib/tracers/ArrayQueueTracer.d.ts +1 -1
- package/dist/lib/tracers/ArrayQueueTracer.js +1 -1
- package/dist/lib/tracers/StdioTracer.d.ts.map +1 -1
- package/dist/lib/tracers/StdioTracer.js +15 -13
- package/dist/lib/tracers/TestTracer.d.ts +4 -6
- package/dist/lib/tracers/TestTracer.d.ts.map +1 -1
- package/dist/lib/tracers/TestTracer.js +6 -8
- package/dist/lib/types.d.ts +49 -32
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/vocabularyRegistry.d.ts +25 -0
- package/dist/lib/vocabularyRegistry.d.ts.map +1 -0
- package/dist/lib/vocabularyRegistry.js +372 -0
- package/dist/lib/wasm/WasmBufferStrategy.d.ts +6 -10
- package/dist/lib/wasm/WasmBufferStrategy.d.ts.map +1 -1
- package/dist/lib/wasm/WasmBufferStrategy.js +44 -37
- package/dist/lib/wasm/wasmAllocator.d.ts +27 -22
- package/dist/lib/wasm/wasmAllocator.d.ts.map +1 -1
- package/dist/lib/wasm/wasmAllocator.js +66 -44
- package/dist/lib/wasm/wasmPhysicalLayout.d.ts +67 -0
- package/dist/lib/wasm/wasmPhysicalLayout.d.ts.map +1 -0
- package/dist/lib/wasm/wasmPhysicalLayout.js +179 -0
- package/dist/lib/wasm/wasmSpanBuffer.d.ts +79 -31
- package/dist/lib/wasm/wasmSpanBuffer.d.ts.map +1 -1
- package/dist/lib/wasm/wasmSpanBuffer.js +442 -272
- package/dist/lib/wasm/wasmTraceRoot.d.ts +24 -22
- package/dist/lib/wasm/wasmTraceRoot.d.ts.map +1 -1
- package/dist/lib/wasm/wasmTraceRoot.js +110 -71
- package/dist/vocabulary/register/v1.d.ts +2 -0
- package/dist/vocabulary/register/v1.d.ts.map +1 -0
- package/dist/vocabulary/register/v1.js +1 -0
- package/dist/wasm.d.ts +5 -0
- package/dist/wasm.d.ts.map +1 -0
- package/dist/wasm.js +4 -0
- package/package.json +54 -6
- package/src/index.ts +1 -0
- package/src/lib/JsBufferStrategy.ts +27 -9
- package/src/lib/__tests__/arrow-builder-integration/arrow-conversion.test.ts +335 -37
- package/src/lib/__tests__/arrow-builder-integration/binary-arrow-conversion.test.ts +97 -26
- package/src/lib/__tests__/arrow-builder-integration/binary-comparison.test.ts +75 -15
- package/src/lib/__tests__/arrow-builder-integration/binary-format-compliance.test.ts +30 -6
- package/src/lib/__tests__/arrow-builder-integration/buffer-chaining.test.ts +18 -21
- package/src/lib/__tests__/arrow-builder-integration/foundation.test.ts +5 -2
- package/src/lib/__tests__/arrow-builder-integration/integration.test.ts +25 -7
- package/src/lib/__tests__/arrow-builder-integration/lazy-columns.test.ts +3 -2
- package/src/lib/__tests__/buffer-overflow.test.ts +24 -18
- package/src/lib/__tests__/capability-span-context.test.ts +505 -0
- package/src/lib/__tests__/capacity-tuning.test.ts +5 -3
- package/src/lib/__tests__/eager-columns.test.ts +345 -0
- package/src/lib/__tests__/enum-metadata-aot.test.ts +153 -0
- package/src/lib/__tests__/enum-metadata.test.ts +177 -0
- package/src/lib/__tests__/fixtures/empty-vocabulary-runtime.fixture.ts +15 -0
- package/src/lib/__tests__/flushScheduler.test.ts +5 -1
- package/src/lib/__tests__/identity-view.property.test.ts +179 -0
- package/src/lib/__tests__/library.test.ts +19 -235
- package/src/lib/__tests__/message-buffer-families.test.ts +878 -0
- package/src/lib/__tests__/nested-library-tasks.test.ts +14 -15
- package/src/lib/__tests__/op-metadata.test.ts +1 -1
- package/src/lib/__tests__/op-type-safety.test.ts +5 -16
- package/src/lib/__tests__/physical-layout-plan.test.ts +333 -0
- package/src/lib/__tests__/remap-descriptor-integration.test.ts +381 -0
- package/src/lib/__tests__/root-context-construction.test.ts +414 -0
- package/src/lib/__tests__/span-auto-runtime.test.ts +386 -0
- package/src/lib/__tests__/span-buffer-segment-stats.test.ts +221 -0
- package/src/lib/__tests__/span-lifecycle.test.ts +53 -25
- package/src/lib/__tests__/spanbuffer-materializer-parity.test.ts +266 -0
- package/src/lib/__tests__/sync-async-trace.test.ts +24 -23
- package/src/lib/__tests__/tag-writer-aot.test.ts +214 -0
- package/src/lib/__tests__/test-helpers.ts +67 -12
- package/src/lib/__tests__/threadId.test.ts +62 -0
- package/src/lib/__tests__/timestamp.test.ts +221 -93
- package/src/lib/__tests__/traceTopology.property.test.ts +383 -0
- package/src/lib/__tests__/type-narrowing.test.ts +63 -0
- package/src/lib/__tests__/vocabulary-dense-decoding.test.ts +405 -0
- package/src/lib/__tests__/vocabularyRegistry.test.ts +313 -0
- package/src/lib/arrow/lease.ts +43 -0
- package/src/lib/arrow/utils.ts +10 -14
- package/src/lib/arrow/vocabularyDictionary.ts +123 -0
- package/src/lib/bufferStrategy.ts +9 -1
- package/src/lib/cloudflare/traceRows.ts +3 -2
- package/src/lib/codegen/__tests__/evaluatorGenerator.test.ts +21 -141
- package/src/lib/codegen/__tests__/fixedPositionWriter-parity.test.ts +273 -0
- package/src/lib/codegen/__tests__/fixedPositionWriter-uint64.test.ts +61 -34
- package/src/lib/codegen/__tests__/nullBitmap.test.ts +33 -37
- package/src/lib/codegen/__tests__/spanLoggerGenerator.test.ts +34 -18
- package/src/lib/codegen/__tests__/spanLoggerMaterializerParity.test.ts +503 -0
- package/src/lib/codegen/evaluatorGenerator.ts +18 -13
- package/src/lib/codegen/fixedPositionWriterGenerator.ts +329 -245
- package/src/lib/codegen/spanLoggerClosureMaterializer.ts +598 -0
- package/src/lib/codegen/spanLoggerGenerator.ts +241 -177
- package/src/lib/convertToArrow.ts +598 -311
- package/src/lib/defineOpContext.ts +1 -1
- package/src/lib/enumMetadata.ts +121 -0
- package/src/lib/flushScheduler.ts +11 -5
- package/src/lib/library.ts +37 -595
- package/src/lib/logBinding.ts +21 -27
- package/src/lib/op.ts +75 -18
- package/src/lib/opContext/__tests__/retry.test.ts +27 -21
- package/src/lib/opContext/createOpGroup.ts +33 -31
- package/src/lib/opContext/defineOp.ts +88 -11
- package/src/lib/opContext/opGroupTypes.ts +2 -2
- package/src/lib/opContext/opTypes.ts +1 -1
- package/src/lib/opContext/spanContextTypes.ts +98 -17
- package/src/lib/opContext/types.ts +7 -3
- package/src/lib/physicalLayoutPlan.ts +598 -0
- package/src/lib/resolveMessage.ts +67 -0
- package/src/lib/result.ts +20 -33
- package/src/lib/runtimeHint.ts +98 -0
- package/src/lib/schema/__tests__/featureFlags.test.ts +2 -1
- package/src/lib/schema/builder.ts +1 -1
- package/src/lib/schema/types.ts +1 -1
- package/src/lib/span-buffer/aot/v1.ts +26 -0
- package/src/lib/spanBuffer.ts +658 -92
- package/src/lib/spanBufferStats.ts +1 -1
- package/src/lib/spanContext.ts +1350 -861
- package/src/lib/sqlite/sqlite-common.ts +20 -31
- package/src/lib/testing/__tests__/topology-traversal.test.ts +174 -0
- package/src/lib/testing/__tests__/vitest-harness.test.ts +2 -1
- package/src/lib/testing/bun-harness.ts +94 -43
- package/src/lib/testing/extractFacts.ts +64 -78
- package/src/lib/testing/facts.ts +1 -1
- package/src/lib/testing/queryable-span.ts +23 -30
- package/src/lib/testing/span-query.ts +16 -20
- package/src/lib/testing/stdio-replay.ts +25 -8
- package/src/lib/testing/vitest-harness.ts +1 -1
- package/src/lib/threadId.ts +6 -3
- package/src/lib/traceRoot.es.ts +77 -42
- package/src/lib/traceRoot.node.ts +75 -46
- package/src/lib/traceRoot.ts +41 -14
- package/src/lib/traceTopology.ts +279 -0
- package/src/lib/tracer.ts +109 -98
- package/src/lib/tracers/ArrayQueueTracer.ts +1 -1
- package/src/lib/tracers/StdioTracer.ts +15 -13
- package/src/lib/tracers/TestTracer.ts +6 -8
- package/src/lib/tracers/__tests__/ArrayQueueTracer.test.ts +15 -10
- package/src/lib/tracers/__tests__/TestTracer.test.ts +23 -13
- package/src/lib/types.ts +64 -33
- package/src/lib/vocabularyRegistry.ts +439 -0
- package/src/lib/wasm/WasmBufferStrategy.ts +56 -48
- package/src/lib/wasm/__tests__/WasmBufferStrategy.test.ts +215 -11
- package/src/lib/wasm/__tests__/allocatorFreeBlockClamp.test.ts +86 -0
- package/src/lib/wasm/__tests__/wasm-identity-view.test.ts +311 -0
- package/src/lib/wasm/__tests__/wasm-integration.test.ts +417 -44
- package/src/lib/wasm/__tests__/wasm-message-buffer-families.test.ts +588 -0
- package/src/lib/wasm/__tests__/wasmAllocator.test.ts +100 -668
- package/src/lib/wasm/__tests__/wasmSpanBuffer.test.ts +419 -63
- package/src/lib/wasm/__tests__/wasmTraceRoot.test.ts +24 -29
- package/src/lib/wasm/__tests__/wasmTracer.test.ts.disabled +2 -2
- package/src/lib/wasm/wasmAllocator.ts +131 -96
- package/src/lib/wasm/wasmPhysicalLayout.ts +309 -0
- package/src/lib/wasm/wasmSpanBuffer.ts +597 -341
- package/src/lib/wasm/wasmTraceRoot.ts +140 -78
- package/src/vocabulary/register/v1.ts +1 -0
- package/src/wasm.ts +19 -0
- package/src/lib/__tests__/remapped-buffer-view-integration.test.ts +0 -319
- package/src/lib/__tests__/remapped-buffer-view.test.ts +0 -635
- package/src/lib/wasm/allocator.zig +0 -948
|
@@ -1,27 +1,17 @@
|
|
|
1
1
|
import { describe, expect, test } from 'bun:test';
|
|
2
|
-
import { createBuffer,
|
|
2
|
+
import { createBuffer, createTestSchema, createTestSpanContext } from '../../__tests__/test-helpers.js';
|
|
3
3
|
import type { OpContext } from '../../opContext/types.js';
|
|
4
|
+
import { resolveEntryType } from '../../resolveMessage.js';
|
|
4
5
|
import { S } from '../../schema/builder.js';
|
|
5
6
|
import type { FeatureFlagSchema } from '../../schema/defineFeatureFlags.js';
|
|
6
7
|
import { defineFeatureFlags } from '../../schema/defineFeatureFlags.js';
|
|
7
8
|
import { InMemoryFlagEvaluator } from '../../schema/evaluator.js';
|
|
8
9
|
import { ENTRY_TYPE_FF_ACCESS, ENTRY_TYPE_FF_USAGE } from '../../schema/systemSchema.js';
|
|
9
|
-
import type { LogSchema } from '../../schema/types.js';
|
|
10
|
-
import { createSpanContextClass, type SpanContextInstance } from '../../spanContext.js';
|
|
10
|
+
import type { LogSchema, SchemaFields } from '../../schema/types.js';
|
|
11
11
|
import type { AnySpanBuffer, SpanBuffer } from '../../types.js';
|
|
12
12
|
import { createEvaluatorClass, generateEvaluatorClass } from '../evaluatorGenerator.js';
|
|
13
|
-
import { createTagWriter } from '../fixedPositionWriterGenerator.js';
|
|
14
|
-
import { createSpanLogger } from '../spanLoggerGenerator.js';
|
|
15
13
|
|
|
16
|
-
/**
|
|
17
|
-
* Create a mock SpanContext for testing FeatureFlagEvaluator
|
|
18
|
-
*
|
|
19
|
-
* The evaluator needs:
|
|
20
|
-
* - _buffer with scopeValues and writeIndex
|
|
21
|
-
* - log with ffAccess, ffUsage, and _writeIndex
|
|
22
|
-
* - buffer getter that returns _buffer
|
|
23
|
-
*
|
|
24
|
-
*/
|
|
14
|
+
/** Create a real shared SpanContext for testing FeatureFlagEvaluator. */
|
|
25
15
|
type EvaluatorTestContext<TLogSchema extends LogSchema, TFlags extends FeatureFlagSchema> = OpContext<
|
|
26
16
|
TLogSchema,
|
|
27
17
|
TFlags,
|
|
@@ -29,96 +19,16 @@ type EvaluatorTestContext<TLogSchema extends LogSchema, TFlags extends FeatureFl
|
|
|
29
19
|
Record<string, never>
|
|
30
20
|
>;
|
|
31
21
|
|
|
32
|
-
function createMockSpanContext<
|
|
33
|
-
schema:
|
|
34
|
-
spanBuffer: SpanBuffer<
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const SpanContextClass = createSpanContextClass<EvaluatorTestContext<TLogSchema, TFlags>>(
|
|
39
|
-
schema,
|
|
40
|
-
createTestLogBinding(schema),
|
|
41
|
-
);
|
|
42
|
-
const ctx = new SpanContextClass(spanBuffer, schema, logger, tagWriter);
|
|
43
|
-
ctx.deps = {};
|
|
44
|
-
return ctx;
|
|
22
|
+
function createMockSpanContext<TFields extends SchemaFields, const TFlags extends FeatureFlagSchema>(
|
|
23
|
+
schema: LogSchema<TFields>,
|
|
24
|
+
spanBuffer: SpanBuffer<LogSchema<TFields>>,
|
|
25
|
+
_flags: TFlags,
|
|
26
|
+
) {
|
|
27
|
+
return createTestSpanContext<TFields, EvaluatorTestContext<LogSchema<TFields>, TFlags>>(schema, spanBuffer);
|
|
45
28
|
}
|
|
46
29
|
|
|
47
30
|
describe('EvaluatorGenerator', () => {
|
|
48
|
-
describe('generateEvaluatorClass', () => {
|
|
49
|
-
test('generates valid JavaScript class code', () => {
|
|
50
|
-
const schema = defineFeatureFlags({
|
|
51
|
-
debugMode: S.boolean().default(false).sync(),
|
|
52
|
-
maxRetries: S.number().default(3).sync(),
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
const code = generateEvaluatorClass(schema.schema);
|
|
56
|
-
|
|
57
|
-
expect(code).toContain('class GeneratedEvaluator extends WorkerSafeGeneratedEvaluator');
|
|
58
|
-
expect(code).toContain('Object.defineProperties(GeneratedEvaluator.prototype');
|
|
59
|
-
|
|
60
|
-
// Should describe the generated getters for each flag
|
|
61
|
-
expect(code).toContain("return this.getFlag('debugMode')");
|
|
62
|
-
expect(code).toContain("return this.getFlag('maxRetries')");
|
|
63
|
-
|
|
64
|
-
// Should have new API methods (not old ones)
|
|
65
|
-
expect(code).toContain('forContext(ctx)');
|
|
66
|
-
expect(code).toContain('super(spanContext, evaluator, SCHEMA, validateFlagValue, ENTRY_TYPE_FF_ACCESS);');
|
|
67
|
-
|
|
68
|
-
// Should NOT have old API methods
|
|
69
|
-
expect(code).not.toContain('withBuffer(');
|
|
70
|
-
expect(code).not.toContain('getContext()');
|
|
71
|
-
expect(code).not.toContain('new Function');
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
test('generates unique getter for each flag', () => {
|
|
75
|
-
const schema = defineFeatureFlags({
|
|
76
|
-
featureA: S.boolean().default(false).sync(),
|
|
77
|
-
featureB: S.boolean().default(false).sync(),
|
|
78
|
-
featureC: S.number().default(0).sync(),
|
|
79
|
-
featureD: S.enum(['a', 'b', 'c'] as const)
|
|
80
|
-
.default('a')
|
|
81
|
-
.sync(),
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
const code = generateEvaluatorClass(schema.schema);
|
|
85
|
-
|
|
86
|
-
expect(code).toContain('featureA: {');
|
|
87
|
-
expect(code).toContain('featureB: {');
|
|
88
|
-
expect(code).toContain('featureC: {');
|
|
89
|
-
expect(code).toContain('featureD: {');
|
|
90
|
-
|
|
91
|
-
// Each getter should call getFlag with the flag name
|
|
92
|
-
expect(code).toContain("this.getFlag('featureA')");
|
|
93
|
-
expect(code).toContain("this.getFlag('featureB')");
|
|
94
|
-
expect(code).toContain("this.getFlag('featureC')");
|
|
95
|
-
expect(code).toContain("this.getFlag('featureD')");
|
|
96
|
-
});
|
|
97
|
-
});
|
|
98
|
-
|
|
99
31
|
describe('createEvaluatorClass', () => {
|
|
100
|
-
test('creates a functional class constructor', () => {
|
|
101
|
-
const ffSchema = defineFeatureFlags({
|
|
102
|
-
debugMode: S.boolean().default(false).sync(),
|
|
103
|
-
});
|
|
104
|
-
const logSchema = createTestSchema({});
|
|
105
|
-
const spanBuffer = createBuffer(logSchema);
|
|
106
|
-
type Ctx = EvaluatorTestContext<typeof logSchema, typeof ffSchema.schema>;
|
|
107
|
-
const mockCtx = createMockSpanContext<typeof logSchema, typeof ffSchema.schema>(logSchema, spanBuffer);
|
|
108
|
-
|
|
109
|
-
const GeneratedClass = createEvaluatorClass<Ctx>(
|
|
110
|
-
ffSchema.schema,
|
|
111
|
-
(value, _schema, def) => value ?? def,
|
|
112
|
-
ENTRY_TYPE_FF_ACCESS,
|
|
113
|
-
);
|
|
114
|
-
|
|
115
|
-
expect(typeof GeneratedClass).toBe('function');
|
|
116
|
-
|
|
117
|
-
const evaluator = new InMemoryFlagEvaluator<Ctx>(ffSchema.schema, { debugMode: true });
|
|
118
|
-
const instance = new GeneratedClass(mockCtx, evaluator);
|
|
119
|
-
expect(instance).toBeDefined();
|
|
120
|
-
});
|
|
121
|
-
|
|
122
32
|
test('caches generated classes by schema', () => {
|
|
123
33
|
const schema = defineFeatureFlags({
|
|
124
34
|
testFlag: S.boolean().default(false).sync(),
|
|
@@ -158,7 +68,7 @@ describe('EvaluatorGenerator', () => {
|
|
|
158
68
|
const logSchema = createTestSchema({});
|
|
159
69
|
const spanBuffer = createBuffer(logSchema);
|
|
160
70
|
type Ctx = EvaluatorTestContext<typeof logSchema, typeof ffSchema.schema>;
|
|
161
|
-
const mockCtx = createMockSpanContext
|
|
71
|
+
const mockCtx = createMockSpanContext(logSchema, spanBuffer, ffSchema.schema);
|
|
162
72
|
|
|
163
73
|
const GeneratedClass = createEvaluatorClass<Ctx>(
|
|
164
74
|
ffSchema.schema,
|
|
@@ -184,7 +94,7 @@ describe('EvaluatorGenerator', () => {
|
|
|
184
94
|
const logSchema = createTestSchema({});
|
|
185
95
|
const spanBuffer = createBuffer(logSchema);
|
|
186
96
|
type Ctx = EvaluatorTestContext<typeof logSchema, typeof ffSchema.schema>;
|
|
187
|
-
const mockCtx = createMockSpanContext
|
|
97
|
+
const mockCtx = createMockSpanContext(logSchema, spanBuffer, ffSchema.schema);
|
|
188
98
|
|
|
189
99
|
const GeneratedClass = createEvaluatorClass<Ctx>(
|
|
190
100
|
ffSchema.schema,
|
|
@@ -206,7 +116,7 @@ describe('EvaluatorGenerator', () => {
|
|
|
206
116
|
const logSchema = createTestSchema({});
|
|
207
117
|
const spanBuffer = createBuffer(logSchema);
|
|
208
118
|
type Ctx = EvaluatorTestContext<typeof logSchema, typeof ffSchema.schema>;
|
|
209
|
-
const mockCtx = createMockSpanContext
|
|
119
|
+
const mockCtx = createMockSpanContext(logSchema, spanBuffer, ffSchema.schema);
|
|
210
120
|
|
|
211
121
|
const GeneratedClass = createEvaluatorClass<Ctx>(
|
|
212
122
|
ffSchema.schema,
|
|
@@ -219,7 +129,7 @@ describe('EvaluatorGenerator', () => {
|
|
|
219
129
|
|
|
220
130
|
// Create a new SpanContext for child span
|
|
221
131
|
const childBuffer = createBuffer(logSchema);
|
|
222
|
-
const childCtx = createMockSpanContext
|
|
132
|
+
const childCtx = createMockSpanContext(logSchema, childBuffer, ffSchema.schema);
|
|
223
133
|
|
|
224
134
|
const childInstance = instance.forContext(childCtx);
|
|
225
135
|
|
|
@@ -229,14 +139,11 @@ describe('EvaluatorGenerator', () => {
|
|
|
229
139
|
});
|
|
230
140
|
|
|
231
141
|
test('span context scope getter returns the typed buffer scope contract', () => {
|
|
232
|
-
const ffSchema = defineFeatureFlags({
|
|
233
|
-
debugMode: S.boolean().default(false).sync(),
|
|
234
|
-
});
|
|
235
142
|
const logSchema = createTestSchema({
|
|
236
143
|
requestId: S.category(),
|
|
237
144
|
});
|
|
238
145
|
const spanBuffer = createBuffer(logSchema);
|
|
239
|
-
const mockCtx =
|
|
146
|
+
const mockCtx = createTestSpanContext(logSchema, spanBuffer);
|
|
240
147
|
|
|
241
148
|
spanBuffer._scopeValues = Object.freeze({ requestId: 'req-123' });
|
|
242
149
|
|
|
@@ -258,7 +165,7 @@ describe('EvaluatorGenerator', () => {
|
|
|
258
165
|
const logSchema = createTestSchema({});
|
|
259
166
|
const spanBuffer = createBuffer(logSchema);
|
|
260
167
|
type Ctx = EvaluatorTestContext<typeof logSchema, typeof ffSchema.schema>;
|
|
261
|
-
const mockCtx = createMockSpanContext
|
|
168
|
+
const mockCtx = createMockSpanContext(logSchema, spanBuffer, ffSchema.schema);
|
|
262
169
|
|
|
263
170
|
let evalCount = 0;
|
|
264
171
|
const trackingEvaluator = new InMemoryFlagEvaluator<Ctx>(ffSchema.schema, { debugMode: true });
|
|
@@ -296,7 +203,7 @@ describe('EvaluatorGenerator', () => {
|
|
|
296
203
|
const logSchema = createTestSchema({});
|
|
297
204
|
const spanBuffer = createBuffer(logSchema);
|
|
298
205
|
type Ctx = EvaluatorTestContext<typeof logSchema, typeof ffSchema.schema>;
|
|
299
|
-
const mockCtx = createMockSpanContext
|
|
206
|
+
const mockCtx = createMockSpanContext(logSchema, spanBuffer, ffSchema.schema);
|
|
300
207
|
|
|
301
208
|
const GeneratedClass = createEvaluatorClass<Ctx>(
|
|
302
209
|
ffSchema.schema,
|
|
@@ -325,7 +232,7 @@ describe('EvaluatorGenerator', () => {
|
|
|
325
232
|
});
|
|
326
233
|
const spanBuffer = createBuffer(logSchema);
|
|
327
234
|
type Ctx = EvaluatorTestContext<typeof logSchema, typeof ffSchema.schema>;
|
|
328
|
-
const mockCtx = createMockSpanContext
|
|
235
|
+
const mockCtx = createMockSpanContext(logSchema, spanBuffer, ffSchema.schema);
|
|
329
236
|
|
|
330
237
|
const GeneratedClass = createEvaluatorClass<Ctx>(
|
|
331
238
|
ffSchema.schema,
|
|
@@ -346,7 +253,7 @@ describe('EvaluatorGenerator', () => {
|
|
|
346
253
|
// Context should be applied via with(context)
|
|
347
254
|
let usageIdx = -1;
|
|
348
255
|
for (let i = 0; i < spanBuffer._writeIndex; i++) {
|
|
349
|
-
if (spanBuffer
|
|
256
|
+
if (resolveEntryType(spanBuffer, i) === ENTRY_TYPE_FF_USAGE) {
|
|
350
257
|
usageIdx = i;
|
|
351
258
|
break;
|
|
352
259
|
}
|
|
@@ -376,7 +283,7 @@ describe('EvaluatorGenerator', () => {
|
|
|
376
283
|
|
|
377
284
|
const createInstance = () => {
|
|
378
285
|
const spanBuffer = createBuffer(logSchema);
|
|
379
|
-
const mockCtx = createMockSpanContext
|
|
286
|
+
const mockCtx = createMockSpanContext(logSchema, spanBuffer, schema.schema);
|
|
380
287
|
return new GeneratedClass(mockCtx, mockEvaluator);
|
|
381
288
|
};
|
|
382
289
|
|
|
@@ -414,33 +321,6 @@ describe('EvaluatorGenerator', () => {
|
|
|
414
321
|
expect(descriptor?.enumerable).toBe(false);
|
|
415
322
|
expect(descriptor?.configurable).toBe(true);
|
|
416
323
|
});
|
|
417
|
-
|
|
418
|
-
test('no Proxy in generated class', () => {
|
|
419
|
-
const schema = defineFeatureFlags({
|
|
420
|
-
testFlag: S.boolean().default(false).sync(),
|
|
421
|
-
});
|
|
422
|
-
|
|
423
|
-
const code = generateEvaluatorClass(schema.schema);
|
|
424
|
-
|
|
425
|
-
// Generated code should not contain Proxy
|
|
426
|
-
expect(code).not.toContain('new Proxy');
|
|
427
|
-
expect(code).not.toContain('Proxy(');
|
|
428
|
-
});
|
|
429
|
-
|
|
430
|
-
test('runtime path stays worker-safe', () => {
|
|
431
|
-
const schema = defineFeatureFlags({
|
|
432
|
-
testFlag: S.boolean().default(false).sync(),
|
|
433
|
-
});
|
|
434
|
-
|
|
435
|
-
const GeneratedClass = createEvaluatorClass(
|
|
436
|
-
schema.schema,
|
|
437
|
-
(value, _schema, def) => value ?? def,
|
|
438
|
-
ENTRY_TYPE_FF_ACCESS,
|
|
439
|
-
);
|
|
440
|
-
|
|
441
|
-
expect(() => GeneratedClass).not.toThrow();
|
|
442
|
-
expect(GeneratedClass.toString()).not.toContain('new Function');
|
|
443
|
-
});
|
|
444
324
|
});
|
|
445
325
|
});
|
|
446
326
|
|
|
@@ -506,7 +386,7 @@ function countEntryType(buffer: AnySpanBuffer, entryType: number): number {
|
|
|
506
386
|
while (current) {
|
|
507
387
|
const writeIndex = current._writeIndex;
|
|
508
388
|
for (let i = 0; i < writeIndex; i++) {
|
|
509
|
-
if (current
|
|
389
|
+
if (resolveEntryType(current, i) === entryType) {
|
|
510
390
|
count++;
|
|
511
391
|
}
|
|
512
392
|
}
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compiled vs closure-composed fixed-position writer parity.
|
|
3
|
+
*
|
|
4
|
+
* getResultWriterClass selects between the compiled renderer (new Function)
|
|
5
|
+
* and the closure-composed materializer via activeMaterializerMode(). This
|
|
6
|
+
* suite drives identical write scripts through both classes against real
|
|
7
|
+
* SpanBuffers and byte-compares every touched lane (values, null bitmaps,
|
|
8
|
+
* message lanes). TagWriter ships closure-only, so its closure class is
|
|
9
|
+
* compared against a compiled reference built from the still-exported
|
|
10
|
+
* generateFixedPositionWriterClass source.
|
|
11
|
+
*
|
|
12
|
+
* Both materializers run under bun via the explicit override hook
|
|
13
|
+
* (setMaterializerModeOverride); afterEach restores probe-based selection.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { afterEach, describe, expect, it } from 'bun:test';
|
|
17
|
+
import { activeMaterializerMode, bufferHelpers, setMaterializerModeOverride } from '@smoothbricks/arrow-builder';
|
|
18
|
+
import {
|
|
19
|
+
createTestOpMetadata,
|
|
20
|
+
createTestSchema,
|
|
21
|
+
createTestSpanContext,
|
|
22
|
+
createTestTraceRoot,
|
|
23
|
+
} from '../../__tests__/test-helpers.js';
|
|
24
|
+
import { resolveEnumLookupDescriptor } from '../../enumMetadata.js';
|
|
25
|
+
import type { MessageLayoutFamily } from '../../runtimeHint.js';
|
|
26
|
+
import { S } from '../../schema/builder.js';
|
|
27
|
+
import type { LogSchema, SchemaFields } from '../../schema/types.js';
|
|
28
|
+
import { createSpanBuffer, getSpanBufferClass } from '../../spanBuffer.js';
|
|
29
|
+
import type { AnySpanBuffer } from '../../types.js';
|
|
30
|
+
import {
|
|
31
|
+
generateFixedPositionWriterClass,
|
|
32
|
+
getResultWriterClass,
|
|
33
|
+
getTagWriterClass,
|
|
34
|
+
type WriterState,
|
|
35
|
+
} from '../fixedPositionWriterGenerator.js';
|
|
36
|
+
|
|
37
|
+
afterEach(() => {
|
|
38
|
+
setMaterializerModeOverride(undefined);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
// Fixtures
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
44
|
+
|
|
45
|
+
// >256 values force the Uint16 enum index lane, the widest special case.
|
|
46
|
+
const wideEnumValues = Array.from({ length: 300 }, (_, i) => `value_${i}`);
|
|
47
|
+
|
|
48
|
+
// Every value family the writer generator can route to a SpanBuffer setter.
|
|
49
|
+
function createParityFields() {
|
|
50
|
+
return {
|
|
51
|
+
status: S.enum(['ok', 'err']),
|
|
52
|
+
wide: S.enum(wideEnumValues),
|
|
53
|
+
cat: S.category(),
|
|
54
|
+
txt: S.text(),
|
|
55
|
+
num: S.number(),
|
|
56
|
+
bool: S.boolean(),
|
|
57
|
+
bin: S.binary(),
|
|
58
|
+
obj: S.object<{ a: number }>(),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const USER_LANES = ['status', 'wide', 'cat', 'txt', 'num', 'bool', 'bin', 'obj'] as const;
|
|
63
|
+
const SYSTEM_LANES = ['uint64_value', 'line'] as const;
|
|
64
|
+
|
|
65
|
+
// SpanBuffer classes still require string codegen, so buffers and contexts are
|
|
66
|
+
// created under the default (compiled) mode; only writer-class creation runs
|
|
67
|
+
// under the closure override.
|
|
68
|
+
function createBufferPair<T extends SchemaFields>(schema: LogSchema<T>, family: MessageLayoutFamily) {
|
|
69
|
+
const BufferClass = getSpanBufferClass(schema, family);
|
|
70
|
+
const bufferA = createSpanBuffer(schema, createTestTraceRoot('a'), createTestOpMetadata(), 8, BufferClass);
|
|
71
|
+
const bufferB = createSpanBuffer(schema, createTestTraceRoot('b'), createTestOpMetadata(), 8, BufferClass);
|
|
72
|
+
return {
|
|
73
|
+
bufferA,
|
|
74
|
+
bufferB,
|
|
75
|
+
contextA: createTestSpanContext(schema, bufferA),
|
|
76
|
+
contextB: createTestSpanContext(schema, bufferB),
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function withClosureMode<T>(create: () => T): T {
|
|
81
|
+
setMaterializerModeOverride('closure');
|
|
82
|
+
try {
|
|
83
|
+
return create();
|
|
84
|
+
} finally {
|
|
85
|
+
setMaterializerModeOverride(undefined);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// ---------------------------------------------------------------------------
|
|
90
|
+
// Reflect helpers (schema-dynamic methods; repo lint bans unsafe assertions)
|
|
91
|
+
// ---------------------------------------------------------------------------
|
|
92
|
+
|
|
93
|
+
function constructWriter(ctor: unknown, state: WriterState): object {
|
|
94
|
+
if (typeof ctor !== 'function') throw new Error('writer constructor is not callable');
|
|
95
|
+
const instance: unknown = Reflect.construct(ctor, [state]);
|
|
96
|
+
if (typeof instance !== 'object' || instance === null) throw new Error('writer construction failed');
|
|
97
|
+
return instance;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function call(writer: object, method: string, value: unknown): unknown {
|
|
101
|
+
const fn = Reflect.get(writer, method);
|
|
102
|
+
if (typeof fn !== 'function') throw new Error(`missing writer method ${JSON.stringify(method)}`);
|
|
103
|
+
return Reflect.apply(fn, writer, [value]);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function prototypeOf(ctor: unknown): object {
|
|
107
|
+
if (typeof ctor !== 'function') throw new Error('expected a constructor');
|
|
108
|
+
const proto: unknown = Reflect.get(ctor, 'prototype');
|
|
109
|
+
if (typeof proto !== 'object' || proto === null) throw new Error('expected a prototype object');
|
|
110
|
+
return proto;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function nameOf(ctor: unknown): string {
|
|
114
|
+
if (typeof ctor !== 'function') throw new Error('expected a constructor');
|
|
115
|
+
return ctor.name;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// ---------------------------------------------------------------------------
|
|
119
|
+
// Write scripts (identical for both materializers)
|
|
120
|
+
// ---------------------------------------------------------------------------
|
|
121
|
+
|
|
122
|
+
function runFieldScript(writer: object): void {
|
|
123
|
+
// Invalid enum values encode to ordinal 0 before the valid overwrite.
|
|
124
|
+
expect(call(writer, 'status', 'not-a-value')).toBe(writer);
|
|
125
|
+
call(writer, 'status', 'err');
|
|
126
|
+
call(writer, 'wide', 'value_299');
|
|
127
|
+
call(writer, 'cat', 'checkout');
|
|
128
|
+
call(writer, 'txt', 'unique text \u2713');
|
|
129
|
+
call(writer, 'num', 42.5);
|
|
130
|
+
call(writer, 'bool', true);
|
|
131
|
+
call(writer, 'bin', Uint8Array.of(1, 2, 3));
|
|
132
|
+
call(writer, 'obj', { a: 7 });
|
|
133
|
+
call(writer, 'uint64_value', 123456789n);
|
|
134
|
+
// Bulk set: null/undefined entries are skipped, unknown keys ignored.
|
|
135
|
+
call(writer, 'with', { status: 'ok', num: 7, cat: null, txt: undefined, notAColumn: 'ignored' });
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function runResultScript(writer: object): void {
|
|
139
|
+
runFieldScript(writer);
|
|
140
|
+
call(writer, 'message', 'span message');
|
|
141
|
+
call(writer, 'line', 1234);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// ---------------------------------------------------------------------------
|
|
145
|
+
// Lane comparison
|
|
146
|
+
// ---------------------------------------------------------------------------
|
|
147
|
+
|
|
148
|
+
function expectIdenticalLanes(actual: AnySpanBuffer, expected: AnySpanBuffer, lanes: readonly string[]): void {
|
|
149
|
+
for (const lane of lanes) {
|
|
150
|
+
const actualValues = actual.getColumnIfAllocated(lane);
|
|
151
|
+
const expectedValues = expected.getColumnIfAllocated(lane);
|
|
152
|
+
expect(actualValues?.constructor).toBe(expectedValues?.constructor);
|
|
153
|
+
expect(actualValues).toEqual(expectedValues);
|
|
154
|
+
expect(actual.getNullsIfAllocated(lane)).toEqual(expected.getNullsIfAllocated(lane));
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// ---------------------------------------------------------------------------
|
|
159
|
+
// ResultWriter parity (compiled vs closure)
|
|
160
|
+
// ---------------------------------------------------------------------------
|
|
161
|
+
|
|
162
|
+
describe('ResultWriter compiled/closure parity', () => {
|
|
163
|
+
const families: readonly MessageLayoutFamily[] = ['mixed', 'dynamic-only', 'static-only'];
|
|
164
|
+
|
|
165
|
+
for (const family of families) {
|
|
166
|
+
it(`writes byte-identical lanes for the ${family} message layout family`, () => {
|
|
167
|
+
expect(activeMaterializerMode()).toBe('compiled');
|
|
168
|
+
const schema = createTestSchema(createParityFields());
|
|
169
|
+
const { bufferA, bufferB, contextA, contextB } = createBufferPair(schema, family);
|
|
170
|
+
|
|
171
|
+
const Compiled = getResultWriterClass(schema, family, 'current');
|
|
172
|
+
const Closure = withClosureMode(() => getResultWriterClass(schema, family, 'current'));
|
|
173
|
+
expect(Closure).not.toBe(Compiled);
|
|
174
|
+
expect(nameOf(Closure)).toBe(nameOf(Compiled));
|
|
175
|
+
|
|
176
|
+
const compiledWriter = constructWriter(Compiled, contextA);
|
|
177
|
+
const closureWriter = constructWriter(Closure, contextB);
|
|
178
|
+
expect(Reflect.ownKeys(closureWriter)).toEqual(Reflect.ownKeys(compiledWriter));
|
|
179
|
+
|
|
180
|
+
runResultScript(compiledWriter);
|
|
181
|
+
runResultScript(closureWriter);
|
|
182
|
+
|
|
183
|
+
expectIdenticalLanes(bufferB, bufferA, [...USER_LANES, ...SYSTEM_LANES]);
|
|
184
|
+
if (family === 'static-only') {
|
|
185
|
+
expect(bufferA._terminalMessage).toBe('span message');
|
|
186
|
+
expect(bufferB._terminalMessage).toBe(bufferA._terminalMessage);
|
|
187
|
+
expect(bufferB.message_values).toBeUndefined();
|
|
188
|
+
expect(bufferA.message_values).toBeUndefined();
|
|
189
|
+
} else {
|
|
190
|
+
expect(bufferA.message_values?.[1]).toBe('span message');
|
|
191
|
+
expect(bufferB.message_values).toEqual(bufferA.message_values);
|
|
192
|
+
expect(bufferB._terminalMessage).toBe(bufferA._terminalMessage);
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
it('installs class-member-equivalent prototype descriptors', () => {
|
|
198
|
+
const schema = createTestSchema(createParityFields());
|
|
199
|
+
const Compiled = getResultWriterClass(schema, 'mixed', 'current');
|
|
200
|
+
const Closure = withClosureMode(() => getResultWriterClass(schema, 'mixed', 'current'));
|
|
201
|
+
|
|
202
|
+
const compiledProto = prototypeOf(Compiled);
|
|
203
|
+
const closureProto = prototypeOf(Closure);
|
|
204
|
+
const members = [...schema._columns.map(([fieldName]) => fieldName), 'with', 'message', 'line', 'uint64_value'];
|
|
205
|
+
|
|
206
|
+
for (const member of members) {
|
|
207
|
+
const compiledDescriptor = Object.getOwnPropertyDescriptor(compiledProto, member);
|
|
208
|
+
const closureDescriptor = Object.getOwnPropertyDescriptor(closureProto, member);
|
|
209
|
+
if (!compiledDescriptor || !closureDescriptor) {
|
|
210
|
+
throw new Error(`missing prototype member ${JSON.stringify(member)}`);
|
|
211
|
+
}
|
|
212
|
+
expect(closureDescriptor.writable).toBe(compiledDescriptor.writable);
|
|
213
|
+
expect(closureDescriptor.configurable).toBe(compiledDescriptor.configurable);
|
|
214
|
+
expect(closureDescriptor.enumerable).toBe(compiledDescriptor.enumerable);
|
|
215
|
+
expect(typeof closureDescriptor.value).toBe(typeof compiledDescriptor.value);
|
|
216
|
+
if (typeof closureDescriptor.value === 'function' && typeof compiledDescriptor.value === 'function') {
|
|
217
|
+
expect(closureDescriptor.value.name).toBe(compiledDescriptor.value.name);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
it('caches classes per materializer mode and restores on override reset', () => {
|
|
223
|
+
const schema = createTestSchema({ n: S.number() });
|
|
224
|
+
const compiled = getResultWriterClass(schema);
|
|
225
|
+
expect(getResultWriterClass(schema)).toBe(compiled);
|
|
226
|
+
|
|
227
|
+
setMaterializerModeOverride('closure');
|
|
228
|
+
const closure = getResultWriterClass(schema);
|
|
229
|
+
expect(getResultWriterClass(schema)).toBe(closure);
|
|
230
|
+
expect(closure).not.toBe(compiled);
|
|
231
|
+
|
|
232
|
+
setMaterializerModeOverride(undefined);
|
|
233
|
+
expect(getResultWriterClass(schema)).toBe(compiled);
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
// ---------------------------------------------------------------------------
|
|
238
|
+
// TagWriter parity (shipped closure class vs compiled-source reference)
|
|
239
|
+
// ---------------------------------------------------------------------------
|
|
240
|
+
|
|
241
|
+
describe('TagWriter closure vs compiled-source reference parity', () => {
|
|
242
|
+
it('writes byte-identical row-0 lanes', () => {
|
|
243
|
+
const schema = createTestSchema(createParityFields());
|
|
244
|
+
const enumLookup = resolveEnumLookupDescriptor(schema);
|
|
245
|
+
const { bufferA, bufferB, contextA, contextB } = createBufferPair(schema, 'mixed');
|
|
246
|
+
|
|
247
|
+
// Compiled reference assembled here (tests run under bun where string
|
|
248
|
+
// codegen is allowed); production tag writers never eval.
|
|
249
|
+
const classCode = generateFixedPositionWriterClass(
|
|
250
|
+
schema,
|
|
251
|
+
0,
|
|
252
|
+
'GeneratedTagWriter',
|
|
253
|
+
undefined,
|
|
254
|
+
[],
|
|
255
|
+
enumLookup,
|
|
256
|
+
).trim();
|
|
257
|
+
const factory = new Function('helpers', 'enumLookup', classCode);
|
|
258
|
+
const CompiledTag: unknown = factory(bufferHelpers, enumLookup);
|
|
259
|
+
|
|
260
|
+
const ClosureTag = withClosureMode(() => getTagWriterClass(schema));
|
|
261
|
+
expect(getTagWriterClass(schema)).toBe(ClosureTag);
|
|
262
|
+
expect(nameOf(ClosureTag)).toBe(nameOf(CompiledTag));
|
|
263
|
+
|
|
264
|
+
const compiledWriter = constructWriter(CompiledTag, contextA);
|
|
265
|
+
const closureWriter = constructWriter(ClosureTag, contextB);
|
|
266
|
+
expect(Reflect.ownKeys(closureWriter)).toEqual(Reflect.ownKeys(compiledWriter));
|
|
267
|
+
|
|
268
|
+
runFieldScript(compiledWriter);
|
|
269
|
+
runFieldScript(closureWriter);
|
|
270
|
+
|
|
271
|
+
expectIdenticalLanes(bufferB, bufferA, [...USER_LANES, 'uint64_value']);
|
|
272
|
+
});
|
|
273
|
+
});
|