Skip to content

Commit b867eef

Browse files
authored
Version 1.0.44 (#1424)
* Support RecursiveAnchor and RecursiveRef for Draft 2019-19 * ChangeLog * Version
1 parent ada16a1 commit b867eef

124 files changed

Lines changed: 1356 additions & 1276 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

changelog/1.0.0.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
---
44

55
### Version Updates
6+
- [Revision 1.0.44](https://github.com/sinclairzx81/typebox/pull/1420)
7+
- Support RecursiveAnchor and RecursiveRef for Draft 2019-19
68
- [Revision 1.0.43](https://github.com/sinclairzx81/typebox/pull/1420)
79
- Fix Json Pointer | Prevent Sparse Array on Delete
810
- [Revision 1.0.42](https://github.com/sinclairzx81/typebox/pull/1418)

deno.jsonc

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
{
22
"tasks": {
3-
"bench": "deno run -A tasks.ts bench", // Benchmarks
4-
"build": "deno run -A tasks.ts build", // Build Project
5-
"clean": "deno run -A tasks.ts clean", // Clean Build Targets
6-
"fast": "deno run -A tasks.ts fast", // Interactive Tests
7-
"format": "deno run -A tasks.ts format", // Formats Code
8-
"local": "deno run -A tasks.ts local", // Build Local Project
9-
"metrics": "deno run -A tasks.ts metrics", // Compression Metrics
10-
"publish": "deno run -A tasks.ts publish", // Publish Package
11-
"report": "deno run -A tasks.ts report", // Test Converage
12-
"range": "deno run -A tasks.ts range", // TypeScript Compiler Ranges
13-
"start": "deno run -A tasks.ts start", // Run Example
14-
"syntax": "deno run -A tasks.ts syntax", // Build Parsers
15-
"test": "deno run -A tasks.ts test", // Test Project
16-
"turing": "deno run -A tasks.ts turing", // Turing Test
17-
"website": "deno run -A tasks.ts website" // Website Doc Server
3+
"bench": "deno run -A tasks.ts bench", // Benchmarks
4+
"build": "deno run -A tasks.ts build", // Build Project
5+
"clean": "deno run -A tasks.ts clean", // Clean Build Targets
6+
"fast": "deno run -A tasks.ts fast", // Interactive Tests
7+
"format": "deno run -A tasks.ts format", // Formats Code
8+
"local": "deno run -A tasks.ts local", // Build Local Project
9+
"metrics": "deno run -A tasks.ts metrics", // Compression Metrics
10+
"publish": "deno run -A tasks.ts publish", // Publish Package
11+
"report": "deno run -A tasks.ts report", // Test Converage
12+
"range": "deno run -A tasks.ts range", // TypeScript Compiler Ranges
13+
"start": "deno run -A tasks.ts start", // Run Example
14+
"syntax": "deno run -A tasks.ts syntax", // Build Parsers
15+
"test": "deno run -A tasks.ts test", // Test Project
16+
"turing": "deno run -A tasks.ts turing", // Turing Test
17+
"website": "deno run -A tasks.ts website" // Website Doc Server
1818
},
1919
"imports": {
2020
// --------------------------------------------------------------

src/schema/build.ts

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import { Guard } from '../guard/index.ts'
3636
import { Format } from '../format/index.ts'
3737

3838
import * as Engine from './engine/index.ts'
39-
import { type XSchema } from './types/index.ts'
39+
import * as Schema from './types/index.ts'
4040

4141
// ------------------------------------------------------------------
4242
// CreateCode
@@ -59,8 +59,9 @@ function CreateEvaluatedCheck(build: BuildResult, code: string): CheckFunction {
5959
// CreateDynamicCheck
6060
// ------------------------------------------------------------------
6161
function CreateDynamicCheck(build: BuildResult): CheckFunction {
62-
const context = new Engine.CheckContext(build.Context(), build.Schema())
63-
return (value: unknown) => Engine.CheckSchema(context, build.Schema(), value)
62+
const stack = new Engine.Stack(build.Context(), build.Schema())
63+
const context = new Engine.CheckContext()
64+
return (value: unknown) => Engine.CheckSchema(stack, context, build.Schema(), value)
6465
}
6566
// ------------------------------------------------------------------
6667
// CreateCheck
@@ -88,19 +89,19 @@ export interface EvaluateResult {
8889
// ------------------------------------------------------------------
8990
export class BuildResult {
9091
constructor(
91-
private readonly context: Record<PropertyKey, XSchema>,
92-
private readonly schema: XSchema,
92+
private readonly context: Record<PropertyKey, Schema.XSchema>,
93+
private readonly schema: Schema.XSchema,
9394
private readonly external: Engine.TExternal,
9495
private readonly functions: string[],
9596
private readonly call: string,
9697
private readonly useUnevaluated: boolean
9798
) { }
9899
/** Returns the Context used for this build */
99-
public Context(): Record<PropertyKey, XSchema> {
100+
public Context(): Record<PropertyKey, Schema.XSchema> {
100101
return this.context
101102
}
102103
/** Returns the Schema used for this build */
103-
public Schema(): XSchema {
104+
public Schema(): Schema.XSchema {
104105
return this.schema
105106
}
106107
/** Returns true if this build requires a Unevaluated context */
@@ -130,19 +131,20 @@ export class BuildResult {
130131
// Build
131132
// ------------------------------------------------------------------
132133
/** Builds a schema into a optimized runtime validator */
133-
export function Build(schema: XSchema): BuildResult
134+
export function Build(schema: Schema.XSchema): BuildResult
134135
/** Builds a schema into a optimized runtime validator */
135-
export function Build(context: Record<PropertyKey, XSchema>, schema: XSchema): BuildResult
136+
export function Build(context: Record<PropertyKey, Schema.XSchema>, schema: Schema.XSchema): BuildResult
136137
/** Builds a schema into a optimized runtime validator */
137138
export function Build(...args: unknown[]): BuildResult {
138-
const [context, schema] = Arguments.Match<[Record<PropertyKey, XSchema>, XSchema]>(args, {
139+
const [context, schema] = Arguments.Match<[Record<PropertyKey, Schema.XSchema>, Schema.XSchema]>(args, {
139140
2: (context, schema) => [context, schema],
140141
1: (schema) => [{}, schema]
141142
})
142143
Engine.ResetExternal()
143144
Engine.ResetFunctions()
144-
const build = new Engine.BuildContext(context, schema, Engine.HasUnevaluated(context, schema))
145-
const call = Engine.CreateFunction(build, schema, 'value')
145+
const stack = new Engine.Stack(context, schema)
146+
const build = new Engine.BuildContext(Engine.HasUnevaluated(context, schema))
147+
const call = Engine.CreateFunction(stack, build, schema, 'value')
146148
const functions = Engine.GetFunctions()
147149
const externals = Engine.GetExternal()
148150
return new BuildResult(context, schema, externals, functions, call, build.UseUnevaluated())

src/schema/check.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,21 +30,23 @@ THE SOFTWARE.
3030
// deno-lint-ignore-file
3131

3232
import { Arguments } from '../system/arguments/index.ts'
33-
import { CheckSchema, CheckContext } from './engine/index.ts'
34-
import { XSchema } from './types/index.ts'
33+
import * as Engine from './engine/index.ts'
34+
import * as Schema from './types/index.ts'
3535

3636
// ------------------------------------------------------------------
3737
// Check
3838
// ------------------------------------------------------------------
3939
/** Checks a value against the provided schema */
40-
export function Check(schema: XSchema, value: unknown): boolean
40+
export function Check(schema: Schema.XSchema, value: unknown): boolean
4141
/** Checks a value against the provided schema */
42-
export function Check(context: Record<PropertyKey, XSchema>, schema: XSchema, value: unknown): boolean
42+
export function Check(context: Record<PropertyKey, Schema.XSchema>, schema: Schema.XSchema, value: unknown): boolean
4343
/** Checks a value against the provided schema */
4444
export function Check(...args: unknown[]): boolean {
45-
const [context, schema, value] = Arguments.Match<[Record<PropertyKey, XSchema>, XSchema, unknown]>(args, {
45+
const [context, schema, value] = Arguments.Match<[Record<PropertyKey, Schema.XSchema>, Schema.XSchema, unknown]>(args, {
4646
3: (context, schema, value) => [context, schema, value],
4747
2: (schema, value) => [{}, schema, value]
4848
})
49-
return CheckSchema(new CheckContext(context, schema), schema, value)
49+
const stack = new Engine.Stack(context, schema)
50+
const checkContext = new Engine.CheckContext()
51+
return Engine.CheckSchema(stack, checkContext, schema, value)
5052
}

src/schema/engine/_context.ts

Lines changed: 11 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ THE SOFTWARE.
2828

2929
// deno-fmt-ignore-file
3030

31-
import * as S from '../types/index.ts'
31+
import * as Schema from '../types/index.ts'
3232
import type { TValidationError } from '../../error/index.ts'
3333
import { Guard as G, EmitGuard as E } from '../../guard/index.ts'
3434

@@ -37,8 +37,8 @@ import { Guard as G, EmitGuard as E } from '../../guard/index.ts'
3737
// ------------------------------------------------------------------
3838
function HasUnevaluatedFromObject(value: Record<PropertyKey, unknown>): boolean {
3939
return (
40-
S.IsUnevaluatedItems(value)
41-
|| S.IsUnevaluatedProperties(value)
40+
Schema.IsUnevaluatedItems(value)
41+
|| Schema.IsUnevaluatedProperties(value)
4242
|| G.Keys(value).some(key => HasUnevaluatedFromUnknown(value[key]))
4343
)
4444
}
@@ -55,29 +55,11 @@ function HasUnevaluatedFromUnknown(value: unknown) {
5555
export function HasUnevaluated(context: Record<PropertyKey, unknown>, schema: unknown): boolean {
5656
return HasUnevaluatedFromUnknown(schema) || G.Keys(context).some(key => HasUnevaluatedFromUnknown(context[key]))
5757
}
58-
59-
// ------------------------------------------------------------------
60-
// BaseContext
61-
// ------------------------------------------------------------------
62-
export class BaseContext {
63-
constructor(
64-
protected readonly context: Record<PropertyKey, S.XSchema>,
65-
protected readonly schema: S.XSchema,
66-
) { }
67-
public GetContext(): Record<PropertyKey, object | boolean> {
68-
return this.context
69-
}
70-
public GetSchema(): object | boolean {
71-
return this.schema
72-
}
73-
}
7458
// ------------------------------------------------------------------
7559
// BuildContext
7660
// ------------------------------------------------------------------
77-
export class BuildContext extends BaseContext {
78-
constructor(context: Record<PropertyKey, S.XSchema>, schema: S.XSchema, private readonly hasUnevaluated: boolean) {
79-
super(context, schema)
80-
}
61+
export class BuildContext {
62+
constructor(private readonly hasUnevaluated: boolean) {}
8163
public UseUnevaluated(): boolean {
8264
return this.hasUnevaluated
8365
}
@@ -87,21 +69,17 @@ export class BuildContext extends BaseContext {
8769
public AddKey(key: string): string {
8870
return E.Call(E.Member('context', 'AddKey'), [key])
8971
}
90-
public Clone(): string {
91-
return E.Call(E.Member('context', 'Clone'), [])
92-
}
9372
public Merge(results: string): string {
9473
return E.Call(E.Member('context', 'Merge'), [results])
9574
}
9675
}
9776
// ------------------------------------------------------------------
9877
// CheckContext
9978
// ------------------------------------------------------------------
100-
export class CheckContext extends BaseContext {
79+
export class CheckContext {
10180
private readonly indices: Set<number>
10281
private readonly keys: Set<string>
103-
constructor(context: Record<PropertyKey, S.XSchema>, schema: S.XSchema) {
104-
super(context, schema)
82+
constructor() {
10583
this.indices = new Set()
10684
this.keys = new Set()
10785
}
@@ -119,9 +97,6 @@ export class CheckContext extends BaseContext {
11997
public GetKeys(): Set<string> {
12098
return this.keys
12199
}
122-
public Clone() {
123-
return new CheckContext(this.context, this.schema)
124-
}
125100
public Merge(results: CheckContext[]): true {
126101
for (const context of results) {
127102
context.indices.forEach(value => this.indices.add(value))
@@ -135,8 +110,8 @@ export class CheckContext extends BaseContext {
135110
// ------------------------------------------------------------------
136111
export type ErrorContextCallback = (error: TValidationError) => unknown
137112
export class ErrorContext extends CheckContext {
138-
constructor(context: Record<PropertyKey, S.XSchema>, schema: S.XSchema, private readonly callback: ErrorContextCallback) {
139-
super(context, schema)
113+
constructor(private readonly callback: ErrorContextCallback) {
114+
super()
140115
}
141116
public AddError(error: TValidationError): false {
142117
this.callback(error)
@@ -148,8 +123,8 @@ export class ErrorContext extends CheckContext {
148123
// ------------------------------------------------------------------
149124
export class AccumulatedErrorContext extends ErrorContext {
150125
private readonly errors: TValidationError[]
151-
constructor(context: Record<PropertyKey, S.XSchema>, schema: S.XSchema) {
152-
super(context, schema, error => this.errors.push(error))
126+
constructor() {
127+
super(error => this.errors.push(error))
153128
this.errors = []
154129
}
155130
public override AddError(error: TValidationError): false {

src/schema/engine/_externals.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,9 @@ export function ResetExternal(): void {
5454
resetCount += 1
5555
}
5656
// ------------------------------------------------------------------
57-
// CreateExternalVariable
57+
// CreateVariable
5858
// ------------------------------------------------------------------
59-
export function CreateExternalVariable(value: unknown): string {
59+
export function CreateVariable(value: unknown): string {
6060
const call = `${state.identifier}[${state.variables.length}]`
6161
state.variables.push(value)
6262
return call

src/schema/engine/_functions.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,27 +28,28 @@ THE SOFTWARE.
2828

2929
// deno-fmt-ignore-file
3030

31-
import * as S from '../types/index.ts'
31+
import * as Schema from '../types/index.ts'
3232
import { Hashing } from '../../system/hashing/index.ts'
33+
import { Stack } from './_stack.ts'
34+
import { BuildContext } from './_context.ts'
3335
import { EmitGuard as E } from '../../guard/index.ts'
3436
import { BuildSchema } from './schema.ts'
35-
import { BuildContext } from './_context.ts'
3637

3738
const functions: Map<string, string> = new Map()
3839

3940
// ------------------------------------------------------------------
4041
// CreateCallExpression
4142
// ------------------------------------------------------------------
42-
function CreateCallExpression(context: BuildContext, schema: S.XSchema, hash: string, value: string): string {
43+
function CreateCallExpression(context: BuildContext, schema: Schema.XSchema, hash: string, value: string): string {
4344
return context.UseUnevaluated()
4445
? E.Call(`check_${hash}`, ['context', value])
4546
: E.Call(`check_${hash}`, [value])
4647
}
4748
// ------------------------------------------------------------------
4849
// CreateFunctionExpression
4950
// ------------------------------------------------------------------
50-
function CreateFunctionExpression(context: BuildContext, schema: S.XSchema, hash: string): string {
51-
const expression = BuildSchema(context, schema, 'value')
51+
function CreateFunctionExpression(stack: Stack, context: BuildContext, schema: Schema.XSchema, hash: string): string {
52+
const expression = BuildSchema(stack, context, schema, 'value')
5253
return context.UseUnevaluated()
5354
? E.ConstDeclaration(`check_${hash}`, E.ArrowFunction(['context', 'value'], expression))
5455
: E.ConstDeclaration(`check_${hash}`, E.ArrowFunction(['value'], expression))
@@ -68,11 +69,11 @@ export function GetFunctions(): string[] {
6869
// ------------------------------------------------------------------
6970
// CreateFunction
7071
// ------------------------------------------------------------------
71-
export function CreateFunction(context: BuildContext, schema: S.XSchema, value: string): string {
72-
const hash = Hashing.Hash(schema)
72+
export function CreateFunction(stack: Stack, context: BuildContext, schema: Schema.XSchema, value: string): string {
73+
const hash = Schema.IsSchemaObject(schema) ? Hashing.Hash({ __baseURL: stack.BaseURL().href, ...schema }) : Hashing.Hash(schema)
7374
const call = CreateCallExpression(context, schema, hash, value)
7475
if (functions.has(hash)) return call
7576
functions.set(hash, '')
76-
functions.set(hash, CreateFunctionExpression(context, schema, hash))
77+
functions.set(hash, CreateFunctionExpression(stack, context, schema, hash))
7778
return call
7879
}

src/schema/engine/_guard.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,27 +28,28 @@ THE SOFTWARE.
2828

2929
// deno-fmt-ignore-file
3030

31-
import * as S from '../types/index.ts'
32-
import * as V from './_externals.ts'
33-
import { EmitGuard as E } from '../../guard/index.ts'
31+
import * as Schema from '../types/index.ts'
32+
import * as Externals from './_externals.ts'
33+
import { Stack } from './_stack.ts'
3434
import { BuildContext, CheckContext, ErrorContext } from './_context.ts'
35+
import { EmitGuard as E } from '../../guard/index.ts'
3536

3637
// ------------------------------------------------------------------
3738
// Build
3839
// ------------------------------------------------------------------
39-
export function BuildGuard(context: BuildContext, schema: S.XGuard, value: string): string {
40-
return E.Call(E.Member(E.Member(V.CreateExternalVariable(schema), '~guard'), 'check'), [value])
40+
export function BuildGuard(stack: Stack, context: BuildContext, schema: Schema.XGuard, value: string): string {
41+
return E.Call(E.Member(E.Member(Externals.CreateVariable(schema), '~guard'), 'check'), [value])
4142
}
4243
// ------------------------------------------------------------------
4344
// Check
4445
// ------------------------------------------------------------------
45-
export function CheckGuard(context: CheckContext, schema: S.XGuard, value: unknown): boolean {
46+
export function CheckGuard(stack: Stack, context: CheckContext, schema: Schema.XGuard, value: unknown): boolean {
4647
return schema['~guard'].check(value)
4748
}
4849
// ------------------------------------------------------------------
4950
// Error
5051
// ------------------------------------------------------------------
51-
export function ErrorGuard(context: ErrorContext, schemaPath: string, instancePath: string, schema: S.XGuard, value: unknown): boolean {
52+
export function ErrorGuard(stack: Stack, context: ErrorContext, schemaPath: string, instancePath: string, schema: Schema.XGuard, value: unknown): boolean {
5253
return schema['~guard'].check(value) || context.AddError({
5354
keyword: '~guard',
5455
schemaPath,

src/schema/engine/_reducer.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@ THE SOFTWARE.
2929
// deno-fmt-ignore-file
3030

3131
import * as S from '../types/index.ts'
32-
import { EmitGuard as E } from '../../guard/index.ts'
32+
import { Stack } from './_stack.ts'
3333
import { BuildContext } from './_context.ts'
34+
import { EmitGuard as E } from '../../guard/index.ts'
3435
import { BuildSchema } from './schema.ts'
3536

3637
// ------------------------------------------------------------------
@@ -67,10 +68,10 @@ import { BuildSchema } from './schema.ts'
6768
// })()
6869
//
6970
// ------------------------------------------------------------------
70-
export function Reducer(context: BuildContext, schemas: S.XSchema[], value: string, check: string): string {
71+
export function Reducer(stack: Stack, context: BuildContext, schemas: S.XSchema[], value: string, check: string): string {
7172
const results = E.ConstDeclaration('results', '[]')
72-
const context_n = schemas.map((_schema, index) => E.ConstDeclaration(`context_${index}`, context.Clone()))
73-
const condition_n = schemas.map((schema, index) => E.ConstDeclaration(`condition_${index}`, E.Call(E.ArrowFunction(['context'], BuildSchema(context, schema, value)), [`context_${index}`])))
73+
const context_n = schemas.map((_schema, index) => E.ConstDeclaration(`context_${index}`, E.New('CheckContext', [])))
74+
const condition_n = schemas.map((schema, index) => E.ConstDeclaration(`condition_${index}`, E.Call(E.ArrowFunction(['context'], BuildSchema(stack, context, schema, value)), [`context_${index}`])))
7475
const checks = schemas.map((_schema, index) => E.If(`condition_${index}`, E.Call(E.Member('results', 'push'), [`context_${index}`])))
7576
const returns = E.Return(E.And(check, context.Merge('results')))
7677
return E.Call(E.ArrowFunction([], E.Statements([results, ...context_n, ...condition_n, ...checks, returns])), [])

0 commit comments

Comments
 (0)