Skip to content

Commit 8af419e

Browse files
authored
Retain Registry Kinds on Compile (#523)
1 parent 934dc9a commit 8af419e

File tree

5 files changed

+94
-5
lines changed

5 files changed

+94
-5
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@sinclair/typebox",
3-
"version": "0.30.3",
3+
"version": "0.30.4",
44
"description": "JSONSchema Type Builder with Static Type Resolution for TypeScript",
55
"keywords": [
66
"typescript",

src/compiler/compiler.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -545,9 +545,10 @@ export namespace TypeCompiler {
545545
export function Compile<T extends Types.TSchema>(schema: T, references: Types.TSchema[] = []): TypeCheck<T> {
546546
const generatedCode = Code(schema, references, { language: 'javascript' })
547547
const compiledFunction = globalThis.Function('kind', 'format', 'hash', generatedCode)
548+
const instances = new Map(state.instances)
548549
function typeRegistryFunction(kind: string, instance: number, value: unknown) {
549-
if (!Types.TypeRegistry.Has(kind) || !state.instances.has(instance)) return false
550-
const schema = state.instances.get(instance)
550+
if (!Types.TypeRegistry.Has(kind) || !instances.has(instance)) return false
551+
const schema = instances.get(instance)
551552
const checkFunc = Types.TypeRegistry.Get(kind)!
552553
return checkFunc(schema, value)
553554
}

test/runtime/compiler/kind.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,55 @@ describe('type/compiler/Kind', () => {
6969
Assert.IsEqual(stack[1], 'B')
7070
TypeRegistry.Delete('Kind')
7171
})
72+
// ------------------------------------------------------------
73+
// Instances Retain
74+
// ------------------------------------------------------------
75+
it('Should retain kind instances on subsequent compile', () => {
76+
let stack: string[] = []
77+
TypeRegistry.Set('Kind', (schema: unknown) => {
78+
// prettier-ignore
79+
return (typeof schema === 'object' && schema !== null && Kind in schema && schema[Kind] === 'Kind' && '$id' in schema && typeof schema.$id === 'string')
80+
? (() => { stack.push(schema.$id); return true })()
81+
: false
82+
})
83+
const A = { [Kind]: 'Kind', $id: 'A' } as TSchema
84+
const B = { [Kind]: 'Kind', $id: 'B' } as TSchema
85+
const C = { [Kind]: 'Kind', $id: 'C' } as TSchema
86+
const D = { [Kind]: 'Kind', $id: 'D' } as TSchema
87+
const T1 = Type.Object({ a: A, b: B })
88+
const T2 = Type.Object({ a: C, b: D })
89+
90+
// Compile T1 and run check, expect A and B
91+
const C1 = TypeCompiler.Compile(T1)
92+
const R1 = C1.Check({ a: null, b: null })
93+
Assert.IsTrue(R1)
94+
Assert.IsEqual(stack.length, 2)
95+
Assert.IsEqual(stack[0], 'A')
96+
Assert.IsEqual(stack[1], 'B')
97+
stack = []
98+
// compile T2 and force instance.clear()
99+
const C2 = TypeCompiler.Compile(T2)
100+
// run T1 check
101+
const R2 = C1.Check({ a: null, b: null })
102+
Assert.IsTrue(R2)
103+
Assert.IsEqual(stack.length, 2)
104+
Assert.IsEqual(stack[0], 'A')
105+
Assert.IsEqual(stack[1], 'B')
106+
stack = []
107+
// run T2 check
108+
const R3 = C2.Check({ a: null, b: null })
109+
Assert.IsTrue(R3)
110+
Assert.IsEqual(stack.length, 2)
111+
Assert.IsEqual(stack[0], 'C')
112+
Assert.IsEqual(stack[1], 'D')
113+
stack = []
114+
// run T1 check
115+
const R4 = C1.Check({ a: null, b: null })
116+
Assert.IsTrue(R4)
117+
Assert.IsEqual(stack.length, 2)
118+
Assert.IsEqual(stack[0], 'A')
119+
Assert.IsEqual(stack[1], 'B')
120+
stack = []
121+
TypeRegistry.Delete('Kind')
122+
})
72123
})

test/runtime/value/check/kind.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,41 @@ describe('value/check/Kind', () => {
6767
Assert.IsEqual(stack[1], 'B')
6868
TypeRegistry.Delete('Kind')
6969
})
70+
it('Should retain kind instances on subsequent check', () => {
71+
let stack: string[] = []
72+
TypeRegistry.Set('Kind', (schema: unknown) => {
73+
// prettier-ignore
74+
return (typeof schema === 'object' && schema !== null && Kind in schema && schema[Kind] === 'Kind' && '$id' in schema && typeof schema.$id === 'string')
75+
? (() => { stack.push(schema.$id); return true })()
76+
: false
77+
})
78+
const A = { [Kind]: 'Kind', $id: 'A' } as TSchema
79+
const B = { [Kind]: 'Kind', $id: 'B' } as TSchema
80+
const C = { [Kind]: 'Kind', $id: 'C' } as TSchema
81+
const D = { [Kind]: 'Kind', $id: 'D' } as TSchema
82+
const T1 = Type.Object({ a: A, b: B })
83+
const T2 = Type.Object({ a: C, b: D })
84+
// run T1 check
85+
const R2 = Value.Check(T1, { a: null, b: null })
86+
Assert.IsTrue(R2)
87+
Assert.IsEqual(stack.length, 2)
88+
Assert.IsEqual(stack[0], 'A')
89+
Assert.IsEqual(stack[1], 'B')
90+
stack = []
91+
// run T2 check
92+
const R3 = Value.Check(T2, { a: null, b: null })
93+
Assert.IsTrue(R3)
94+
Assert.IsEqual(stack.length, 2)
95+
Assert.IsEqual(stack[0], 'C')
96+
Assert.IsEqual(stack[1], 'D')
97+
stack = []
98+
// run T1 check
99+
const R4 = Value.Check(T1, { a: null, b: null })
100+
Assert.IsTrue(R4)
101+
Assert.IsEqual(stack.length, 2)
102+
Assert.IsEqual(stack[0], 'A')
103+
Assert.IsEqual(stack[1], 'B')
104+
stack = []
105+
TypeRegistry.Delete('Kind')
106+
})
70107
})

0 commit comments

Comments
 (0)