ata-validator 1.7.0 → 1.7.1

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.
@@ -0,0 +1,545 @@
1
+ 'use strict';
2
+
3
+ // Compiles interpreter Plans into a tree of specialized closures. No source
4
+ // generation, no `new Function`: this is plain closure composition, so it
5
+ // runs wherever the interpreter runs, CSP included. The payoff over eval()
6
+ // is that every keyword branch is decided once at compile time and every
7
+ // child call is a direct monomorphic call, which is the same advantage the
8
+ // code generator has, minus the codegen.
9
+ //
10
+ // Scope, deliberately narrow:
11
+ // - single schema resource only (no embedded `$id`, no external documents),
12
+ // so the base URI and the dynamic scope are compile-time constants and
13
+ // `$ref` / `$dynamicRef` targets resolve once, here;
14
+ // - no `unevaluatedProperties` / `unevaluatedItems` anywhere (annotation
15
+ // flow stays eval()'s job).
16
+ // Anything outside that gate keeps the generic evaluator. Error output must
17
+ // be byte-for-byte what eval() produces; tests/test_plan_compiler.js diffs
18
+ // the two over the official suite.
19
+ //
20
+ // Compiled signature: fn(data, errors, instancePath, schemaPath, stack) ->
21
+ // boolean. `errors` may be the NOERRORS sentinel for verdict-only runs, in
22
+ // which case a failed step returns immediately; when collecting, every step
23
+ // runs, exactly like eval().
24
+
25
+ function install(deps) {
26
+ const { Plan, NOERRORS, err, evalLeaf, evalLeafV, deepEqual, dataBits, escapePointer,
27
+ T_STRING, T_ARRAY, T_OBJECT, resolveRef, splitFragment, resolveUri } = deps;
28
+
29
+ const TRUE_FN = () => true;
30
+ const TRUE_PAIR = { v: TRUE_FN, c: TRUE_FN };
31
+ const FALSE_PAIR = {
32
+ v: () => false,
33
+ c: (data, errors, instancePath, schemaPath) => {
34
+ if (errors !== NOERRORS) errors.push(err('false schema', 'not', instancePath, schemaPath, {}, 'boolean schema is false'));
35
+ return false;
36
+ },
37
+ };
38
+
39
+ // Whether the whole tree reachable from `node` fits the compiler's scope.
40
+ // `base` is the base URI in effect, updated at compile time exactly the way
41
+ // eval() updates it at run time: the schema path is static, so it can be.
42
+ function compilable(interp, node, base, seen) {
43
+ if (node === true || node === false) return true;
44
+ if (!(node instanceof Plan)) return true;
45
+ const P = node;
46
+ if (P.nodeBase !== null && P.nodeBase !== base) base = P.nodeBase;
47
+ const key = P;
48
+ const prev = seen.get(key);
49
+ if (prev !== undefined) { if (prev === base || prev === true) return true; return false; }
50
+ seen.set(key, base);
51
+ if (P.hasUnevaluated) return false;
52
+ if (P.ref !== null) {
53
+ const t = resolveRef(P.ref, base, interp.state);
54
+ if (t.node === undefined || !compilable(interp, interp.node(t.node), t.base, seen)) return false;
55
+ }
56
+ if (P.dynamicRef !== null) {
57
+ // $dynamicRef stays compiled only in a single-resource schema, where
58
+ // the dynamic scope is a constant. Anything larger keeps eval().
59
+ if (interp.state.resources.size !== 1) return false;
60
+ const t = dynTarget(interp, P.dynamicRef);
61
+ if (t === undefined || !compilable(interp, interp.node(t), base, seen)) return false;
62
+ }
63
+ const kids = [];
64
+ if (P.properties !== null) for (const v of P.properties.values()) kids.push(v.node);
65
+ if (P.patternProperties !== null) for (const e of P.patternProperties) kids.push(e.node);
66
+ if (P.additionalProperties !== undefined) kids.push(P.additionalProperties);
67
+ if (P.propertyNames !== undefined) kids.push(P.propertyNames);
68
+ if (P.dependentSchemas !== null) for (const [, v] of P.dependentSchemas) kids.push(v);
69
+ if (P.propertyDependencies !== null) for (const [, m] of P.propertyDependencies) for (const v of m.values()) kids.push(v);
70
+ if (P.prefixItems !== null) for (const v of P.prefixItems) kids.push(v);
71
+ if (P.items !== undefined) kids.push(P.items);
72
+ if (P.contains !== undefined) kids.push(P.contains);
73
+ if (P.allOf !== null) for (const v of P.allOf) kids.push(v);
74
+ if (P.anyOf !== null) for (const v of P.anyOf) kids.push(v);
75
+ if (P.oneOf !== null) for (const v of P.oneOf) kids.push(v);
76
+ if (P.not !== undefined) kids.push(P.not);
77
+ if (P.if !== undefined) kids.push(P.if);
78
+ if (P.then !== undefined) kids.push(P.then);
79
+ if (P.else !== undefined) kids.push(P.else);
80
+ for (const k of kids) if (!compilable(interp, k, base, seen)) return false;
81
+ return true;
82
+ }
83
+
84
+ // Static $dynamicRef target: with a single resource the dynamic scope is
85
+ // always [rootBase], so the outermost-scope search collapses to a lookup.
86
+ function dynTarget(interp, ref) {
87
+ const base = interp.state.rootBase;
88
+ let { node } = resolveRef(ref, base, interp.state);
89
+ const [, fragment] = splitFragment(resolveUri(base, ref));
90
+ if (fragment && !fragment.startsWith('/')) {
91
+ const dyn = interp.state.dynamicAnchors.get(base);
92
+ const bookended = node !== undefined && dyn && dyn.get(fragment) === node;
93
+ if (bookended || !interp.bookending) {
94
+ if (dyn && dyn.has(fragment)) node = dyn.get(fragment);
95
+ }
96
+ }
97
+ return node;
98
+ }
99
+
100
+ function compileNode(interp, node, base, memo) {
101
+ if (node === true) return TRUE_PAIR;
102
+ if (node === false) return FALSE_PAIR;
103
+ if (!(node instanceof Plan)) return TRUE_PAIR;
104
+ const P = node;
105
+ if (P.nodeBase !== null && P.nodeBase !== base) base = P.nodeBase;
106
+ // A plan reached under two bases compiles once per base; nearly every
107
+ // plan only ever has one.
108
+ let perBase = memo.get(P);
109
+ if (perBase === undefined) { perBase = new Map(); memo.set(P, perBase); }
110
+ const cached = perBase.get(base);
111
+ if (cached !== undefined) return cached;
112
+ // Cycles: register trampolines before compiling children.
113
+ const box = { v: null, c: null };
114
+ const pair = {
115
+ v: (d, st) => box.v(d, st),
116
+ c: (d, e, ip, sp, st) => box.c(d, e, ip, sp, st),
117
+ };
118
+ perBase.set(base, pair);
119
+
120
+ const steps = []; // collect variant: (data, errors, ip, sp, stack)
121
+ const vsteps = []; // verdict variant: (data, stack), no strings at all
122
+
123
+ // $ref / $dynamicRef, resolved at compile time. The cycle guard mirrors
124
+ // eval(): a (schema, data) pair already on the stack is a fixed point.
125
+ if (P.ref !== null) {
126
+ const t = resolveRef(P.ref, base, interp.state);
127
+ const target = compileNode(interp, interp.node(t.node), t.base, memo);
128
+ const schema = P.schema;
129
+ steps.push((data, errors, instancePath, schemaPath, stack) => {
130
+ for (let i = stack.length - 2; i >= 0; i -= 2) {
131
+ if (stack[i] === schema && stack[i + 1] === data) return true;
132
+ }
133
+ stack.push(schema, data);
134
+ const ok = target.c(data, errors, instancePath, schemaPath + '/$ref', stack);
135
+ stack.length -= 2;
136
+ return ok;
137
+ });
138
+ vsteps.push((data, stack) => {
139
+ for (let i = stack.length - 2; i >= 0; i -= 2) {
140
+ if (stack[i] === schema && stack[i + 1] === data) return true;
141
+ }
142
+ stack.push(schema, data);
143
+ const ok = target.v(data, stack);
144
+ stack.length -= 2;
145
+ return ok;
146
+ });
147
+ }
148
+ if (P.dynamicRef !== null) {
149
+ const target = compileNode(interp, interp.node(dynTarget(interp, P.dynamicRef)), base, memo);
150
+ const schema = P.schema;
151
+ steps.push((data, errors, instancePath, schemaPath, stack) => {
152
+ for (let i = stack.length - 2; i >= 0; i -= 2) {
153
+ if (stack[i] === schema && stack[i + 1] === data) return true;
154
+ }
155
+ stack.push(schema, data);
156
+ const ok = target.c(data, errors, instancePath, schemaPath + '/$dynamicRef', stack);
157
+ stack.length -= 2;
158
+ return ok;
159
+ });
160
+ vsteps.push((data, stack) => {
161
+ for (let i = stack.length - 2; i >= 0; i -= 2) {
162
+ if (stack[i] === schema && stack[i + 1] === data) return true;
163
+ }
164
+ stack.push(schema, data);
165
+ const ok = target.v(data, stack);
166
+ stack.length -= 2;
167
+ return ok;
168
+ });
169
+ }
170
+
171
+ // Every value-level keyword in one step, reusing the leaf evaluator so
172
+ // the two paths cannot drift.
173
+ if (P.hasType || P.enum !== null || P.hasConst || P.hasNumber || P.hasString ||
174
+ P.minItems !== undefined || P.maxItems !== undefined || P.uniqueItems ||
175
+ P.required !== null || P.minProperties !== undefined || P.maxProperties !== undefined ||
176
+ P.dependentRequired !== null) {
177
+ steps.push((data, errors, instancePath, schemaPath) => evalLeaf(P, data, errors, instancePath, schemaPath));
178
+ vsteps.push((data) => evalLeafV(P, data));
179
+ }
180
+
181
+ // Arrays
182
+ if (P.prefixItems !== null) {
183
+ const fns = P.prefixItems.map((v) => compileNode(interp, v, base, memo));
184
+ steps.push((data, errors, instancePath, schemaPath, stack) => {
185
+ if (dataBits(data) !== T_ARRAY) return true;
186
+ let ok = true;
187
+ const n = Math.min(fns.length, data.length);
188
+ for (let i = 0; i < n; i++) {
189
+ if (!fns[i].c(data[i], errors, instancePath + '/' + i, schemaPath + '/prefixItems/' + i, stack)) {
190
+ ok = false;
191
+ if (errors === NOERRORS) return false;
192
+ }
193
+ }
194
+ return ok;
195
+ });
196
+ vsteps.push((data, stack) => {
197
+ if (dataBits(data) !== T_ARRAY) return true;
198
+ const n = Math.min(fns.length, data.length);
199
+ for (let i = 0; i < n; i++) if (!fns[i].v(data[i], stack)) return false;
200
+ return true;
201
+ });
202
+ }
203
+ if (P.items !== undefined) {
204
+ const fn = compileNode(interp, P.items, base, memo);
205
+ const start = P.prefixItems !== null ? P.prefixItems.length : 0;
206
+ steps.push((data, errors, instancePath, schemaPath, stack) => {
207
+ if (dataBits(data) !== T_ARRAY) return true;
208
+ let ok = true;
209
+ for (let i = start; i < data.length; i++) {
210
+ if (!fn.c(data[i], errors, instancePath + '/' + i, schemaPath + '/items', stack)) {
211
+ ok = false;
212
+ if (errors === NOERRORS) return false;
213
+ }
214
+ }
215
+ return ok;
216
+ });
217
+ const fv = fn.v;
218
+ vsteps.push((data, stack) => {
219
+ if (dataBits(data) !== T_ARRAY) return true;
220
+ for (let i = start; i < data.length; i++) if (!fv(data[i], stack)) return false;
221
+ return true;
222
+ });
223
+ }
224
+ if (P.contains !== undefined) {
225
+ const fn = compileNode(interp, P.contains, base, memo);
226
+ const minC = P.minContains !== undefined ? P.minContains : 1;
227
+ const maxC = P.maxContains;
228
+ steps.push((data, errors, instancePath, schemaPath, stack) => {
229
+ if (dataBits(data) !== T_ARRAY) return true;
230
+ let matched = 0;
231
+ for (let i = 0; i < data.length; i++) {
232
+ if (fn.v(data[i], stack)) matched++;
233
+ }
234
+ let ok = true;
235
+ if (matched < minC) {
236
+ if (errors !== NOERRORS) errors.push(err('contains', 'contains', instancePath, schemaPath + '/contains', { minContains: minC }, `must contain at least ${minC} valid item(s)`));
237
+ ok = false;
238
+ }
239
+ if (maxC !== undefined && matched > maxC) {
240
+ if (errors !== NOERRORS) errors.push(err('maxContains', 'maxContains', instancePath, schemaPath + '/maxContains', { limit: maxC }, `must NOT contain more than ${maxC} valid item(s)`));
241
+ ok = false;
242
+ }
243
+ return ok;
244
+ });
245
+ vsteps.push((data, stack) => {
246
+ if (dataBits(data) !== T_ARRAY) return true;
247
+ let matched = 0;
248
+ for (let i = 0; i < data.length; i++) {
249
+ if (fn.v(data[i], stack)) { matched++; if (maxC === undefined && matched >= minC) return true; }
250
+ }
251
+ return matched >= minC && (maxC === undefined || matched <= maxC);
252
+ });
253
+ }
254
+
255
+ // Objects
256
+ if (P.properties !== null || P.patternProperties !== null || P.additionalProperties !== undefined || P.propertyNames !== undefined) {
257
+ const props = P.properties;
258
+ const propFns = props !== null ? new Map() : null;
259
+ if (props !== null) {
260
+ for (const [key, entry] of props) propFns.set(key, { fn: compileNode(interp, entry.node, base, memo), seg: entry.seg, schemaSeg: entry.schemaSeg });
261
+ }
262
+ const patterns = P.patternProperties !== null
263
+ ? P.patternProperties.map((e) => ({ re: e.re, src: e.src, fn: compileNode(interp, e.node, base, memo) }))
264
+ : null;
265
+ const apFn = P.additionalProperties !== undefined ? compileNode(interp, P.additionalProperties, base, memo) : null;
266
+ const pnFn = P.propertyNames !== undefined ? compileNode(interp, P.propertyNames, base, memo) : null;
267
+ steps.push((data, errors, instancePath, schemaPath, stack) => {
268
+ if (dataBits(data) !== T_OBJECT) return true;
269
+ let ok = true;
270
+ const keys = Object.keys(data);
271
+ if (pnFn !== null) {
272
+ for (const key of keys) {
273
+ if (!pnFn.c(key, errors, instancePath + '/' + escapePointer(key), schemaPath + '/propertyNames', stack)) {
274
+ ok = false;
275
+ if (errors === NOERRORS) return false;
276
+ }
277
+ }
278
+ }
279
+ for (let k = 0; k < keys.length; k++) {
280
+ const key = keys[k];
281
+ let evaluated = false;
282
+ const prop = propFns !== null ? propFns.get(key) : undefined;
283
+ if (prop !== undefined) {
284
+ if (!prop.fn.c(data[key], errors, instancePath + prop.seg, schemaPath + prop.schemaSeg, stack)) {
285
+ ok = false;
286
+ if (errors === NOERRORS) return false;
287
+ }
288
+ evaluated = true;
289
+ }
290
+ if (patterns !== null) {
291
+ for (let pi = 0; pi < patterns.length; pi++) {
292
+ const pp = patterns[pi];
293
+ if (pp.re.test(key)) {
294
+ if (!pp.fn.c(data[key], errors, instancePath + '/' + escapePointer(key), schemaPath + '/patternProperties/' + escapePointer(pp.src), stack)) {
295
+ ok = false;
296
+ if (errors === NOERRORS) return false;
297
+ }
298
+ evaluated = true;
299
+ }
300
+ }
301
+ }
302
+ if (!evaluated && apFn !== null) {
303
+ if (!apFn.c(data[key], errors, instancePath + '/' + escapePointer(key), schemaPath + '/additionalProperties', stack)) {
304
+ ok = false;
305
+ if (errors === NOERRORS) return false;
306
+ }
307
+ }
308
+ }
309
+ return ok;
310
+ });
311
+ vsteps.push((data, stack) => {
312
+ if (dataBits(data) !== T_OBJECT) return true;
313
+ const keys = Object.keys(data);
314
+ if (pnFn !== null) {
315
+ for (const key of keys) if (!pnFn.v(key, stack)) return false;
316
+ }
317
+ for (let k = 0; k < keys.length; k++) {
318
+ const key = keys[k];
319
+ let evaluated = false;
320
+ const prop = propFns !== null ? propFns.get(key) : undefined;
321
+ if (prop !== undefined) {
322
+ if (!prop.fn.v(data[key], stack)) return false;
323
+ evaluated = true;
324
+ }
325
+ if (patterns !== null) {
326
+ for (let pi = 0; pi < patterns.length; pi++) {
327
+ const pp = patterns[pi];
328
+ if (pp.re.test(key)) {
329
+ if (!pp.fn.v(data[key], stack)) return false;
330
+ evaluated = true;
331
+ }
332
+ }
333
+ }
334
+ if (!evaluated && apFn !== null) {
335
+ if (!apFn.v(data[key], stack)) return false;
336
+ }
337
+ }
338
+ return true;
339
+ });
340
+ }
341
+ if (P.dependentSchemas !== null) {
342
+ const entries = P.dependentSchemas.map(([key, v]) => [key, compileNode(interp, v, base, memo), escapePointer(key)]);
343
+ steps.push((data, errors, instancePath, schemaPath, stack) => {
344
+ if (dataBits(data) !== T_OBJECT) return true;
345
+ let ok = true;
346
+ for (const [key, fn, ek] of entries) {
347
+ if (Object.hasOwn(data, key)) {
348
+ if (!fn.c(data, errors, instancePath, schemaPath + '/dependentSchemas/' + ek, stack)) {
349
+ ok = false;
350
+ if (errors === NOERRORS) return false;
351
+ }
352
+ }
353
+ }
354
+ return ok;
355
+ });
356
+ vsteps.push((data, stack) => {
357
+ if (dataBits(data) !== T_OBJECT) return true;
358
+ for (const [key, fn] of entries) {
359
+ if (Object.hasOwn(data, key) && !fn.v(data, stack)) return false;
360
+ }
361
+ return true;
362
+ });
363
+ }
364
+ if (P.propertyDependencies !== null) {
365
+ const entries = P.propertyDependencies.map(([key, choices]) => {
366
+ const m = new Map();
367
+ for (const [value, v] of choices) m.set(value, compileNode(interp, v, base, memo));
368
+ return [key, m];
369
+ });
370
+ steps.push((data, errors, instancePath, schemaPath, stack) => {
371
+ if (dataBits(data) !== T_OBJECT) return true;
372
+ let ok = true;
373
+ for (const [key, choices] of entries) {
374
+ if (!Object.hasOwn(data, key)) continue;
375
+ const value = data[key];
376
+ if (typeof value !== 'string') continue;
377
+ const fn = choices.get(value);
378
+ if (fn === undefined) continue;
379
+ const branchPath = schemaPath + '/propertyDependencies/' + escapePointer(key) + '/' + escapePointer(value);
380
+ if (!fn.c(data, errors, instancePath, branchPath, stack)) {
381
+ ok = false;
382
+ if (errors === NOERRORS) return false;
383
+ }
384
+ }
385
+ return ok;
386
+ });
387
+ vsteps.push((data, stack) => {
388
+ if (dataBits(data) !== T_OBJECT) return true;
389
+ for (const [key, choices] of entries) {
390
+ if (!Object.hasOwn(data, key)) continue;
391
+ const value = data[key];
392
+ if (typeof value !== 'string') continue;
393
+ const fn = choices.get(value);
394
+ if (fn !== undefined && !fn.v(data, stack)) return false;
395
+ }
396
+ return true;
397
+ });
398
+ }
399
+
400
+ // In-place applicators
401
+ if (P.allOf !== null) {
402
+ const fns = P.allOf.map((v) => compileNode(interp, v, base, memo));
403
+ steps.push((data, errors, instancePath, schemaPath, stack) => {
404
+ let ok = true;
405
+ for (let i = 0; i < fns.length; i++) {
406
+ if (!fns[i].c(data, errors, instancePath, schemaPath + '/allOf/' + i, stack)) {
407
+ ok = false;
408
+ if (errors === NOERRORS) return false;
409
+ }
410
+ }
411
+ return ok;
412
+ });
413
+ vsteps.push((data, stack) => {
414
+ for (let i = 0; i < fns.length; i++) if (!fns[i].v(data, stack)) return false;
415
+ return true;
416
+ });
417
+ }
418
+ if (P.anyOf !== null) {
419
+ const fns = P.anyOf.map((v) => compileNode(interp, v, base, memo));
420
+ steps.push((data, errors, instancePath, schemaPath, stack) => {
421
+ const scratch = errors === NOERRORS ? NOERRORS : [];
422
+ let any = false;
423
+ for (let i = 0; i < fns.length; i++) {
424
+ if (fns[i].c(data, scratch, instancePath, schemaPath + '/anyOf/' + i, stack)) any = true;
425
+ }
426
+ if (!any) {
427
+ if (errors !== NOERRORS) {
428
+ for (const e of scratch) errors.push(e);
429
+ errors.push(err('anyOf', 'anyOf', instancePath, schemaPath + '/anyOf', {}, 'must match a schema in anyOf'));
430
+ }
431
+ return false;
432
+ }
433
+ return true;
434
+ });
435
+ vsteps.push((data, stack) => {
436
+ for (let i = 0; i < fns.length; i++) if (fns[i].v(data, stack)) return true;
437
+ return false;
438
+ });
439
+ }
440
+ if (P.oneOf !== null) {
441
+ const fns = P.oneOf.map((v) => compileNode(interp, v, base, memo));
442
+ steps.push((data, errors, instancePath, schemaPath, stack) => {
443
+ const scratch = errors === NOERRORS ? NOERRORS : [];
444
+ let count = 0;
445
+ for (let i = 0; i < fns.length; i++) {
446
+ if (fns[i].c(data, scratch, instancePath, schemaPath + '/oneOf/' + i, stack)) count++;
447
+ }
448
+ if (count !== 1) {
449
+ if (errors !== NOERRORS) {
450
+ if (count === 0) for (const e of scratch) errors.push(e);
451
+ errors.push(err('oneOf', 'oneOf', instancePath, schemaPath + '/oneOf', { passingSchemas: count }, 'must match exactly one schema in oneOf'));
452
+ }
453
+ return false;
454
+ }
455
+ return true;
456
+ });
457
+ vsteps.push((data, stack) => {
458
+ let count = 0;
459
+ for (let i = 0; i < fns.length; i++) {
460
+ if (fns[i].v(data, stack)) { count++; if (count > 1) return false; }
461
+ }
462
+ return count === 1;
463
+ });
464
+ }
465
+ if (P.not !== undefined) {
466
+ const fn = compileNode(interp, P.not, base, memo);
467
+ steps.push((data, errors, instancePath, schemaPath, stack) => {
468
+ if (fn.v(data, stack)) {
469
+ if (errors !== NOERRORS) errors.push(err('not', 'not', instancePath, schemaPath + '/not', {}, 'must NOT be valid'));
470
+ return false;
471
+ }
472
+ return true;
473
+ });
474
+ vsteps.push((data, stack) => !fn.v(data, stack));
475
+ }
476
+ if (P.if !== undefined) {
477
+ const ifFn = compileNode(interp, P.if, base, memo);
478
+ const thenFn = P.then !== undefined ? compileNode(interp, P.then, base, memo) : null;
479
+ const elseFn = P.else !== undefined ? compileNode(interp, P.else, base, memo) : null;
480
+ steps.push((data, errors, instancePath, schemaPath, stack) => {
481
+ if (ifFn.v(data, stack)) {
482
+ if (thenFn !== null) return thenFn.c(data, errors, instancePath, schemaPath + '/then', stack);
483
+ } else if (elseFn !== null) {
484
+ return elseFn.c(data, errors, instancePath, schemaPath + '/else', stack);
485
+ }
486
+ return true;
487
+ });
488
+ vsteps.push((data, stack) => {
489
+ if (ifFn.v(data, stack)) {
490
+ if (thenFn !== null) return thenFn.v(data, stack);
491
+ } else if (elseFn !== null) {
492
+ return elseFn.v(data, stack);
493
+ }
494
+ return true;
495
+ });
496
+ }
497
+
498
+ let cfn;
499
+ if (steps.length === 0) cfn = TRUE_FN;
500
+ else if (steps.length === 1) cfn = steps[0];
501
+ else {
502
+ const arr = steps;
503
+ cfn = (d, e, ip, sp, st) => {
504
+ let ok = true;
505
+ for (let i = 0; i < arr.length; i++) {
506
+ if (!arr[i](d, e, ip, sp, st)) {
507
+ if (e === NOERRORS) return false;
508
+ ok = false;
509
+ }
510
+ }
511
+ return ok;
512
+ };
513
+ }
514
+ let vfn;
515
+ if (vsteps.length === 0) vfn = TRUE_FN;
516
+ else if (vsteps.length === 1) vfn = vsteps[0];
517
+ else if (vsteps.length === 2) {
518
+ const [a, b] = vsteps;
519
+ vfn = (d, st) => a(d, st) && b(d, st);
520
+ } else {
521
+ const arr = vsteps;
522
+ vfn = (d, st) => {
523
+ for (let i = 0; i < arr.length; i++) if (!arr[i](d, st)) return false;
524
+ return true;
525
+ };
526
+ }
527
+ box.c = cfn;
528
+ box.v = vfn;
529
+ pair.c = cfn;
530
+ pair.v = vfn;
531
+ perBase.set(base, pair);
532
+ return pair;
533
+ }
534
+
535
+ // Entry point: returns a compiled root function or null when the schema is
536
+ // outside the compiler's scope.
537
+ function compileInterpreter(interp) {
538
+ if (!compilable(interp, interp.rootNode, interp.state.rootBase, new Map())) return null;
539
+ return compileNode(interp, interp.rootNode, interp.state.rootBase, new Map());
540
+ }
541
+
542
+ return { compileInterpreter };
543
+ }
544
+
545
+ module.exports = { install };
package/lib/version.js CHANGED
@@ -7,4 +7,4 @@
7
7
  //
8
8
  // Kept in lockstep with package.json by `tests/test_version_sync.js`.
9
9
 
10
- module.exports = '1.7.0';
10
+ module.exports = '1.7.1';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ata-validator",
3
- "version": "1.7.0",
3
+ "version": "1.7.1",
4
4
  "description": "JSON Schema validation with first-class TypeScript and zero runtime cost. AOT compile to per-schema ESM modules with zero validator dependency. Generic Validator<T> for TypeBox/Zod/Valibot composition. Optional runtime API. Standard Schema V1 compatible.",
5
5
  "main": "index.js",
6
6
  "module": "index.mjs",
@@ -44,7 +44,7 @@
44
44
  "release:check": "node scripts/regen-safe-regex-source.js && node tests/test_pack_purity.js && node scripts/check-doc-coverage.js && node tests/test_error_codes_lock.js && node tests/test_safe_regex_source_sync.js && node tests/test_version_sync.js",
45
45
  "build": "cmake-js build --target ata",
46
46
  "rebuild": "cmake-js rebuild --target ata",
47
- "test": "node test.js && node tests/test_removed_aot_methods.js && node tests/test_no_native.js && node tests/test_no_eval.js && node tests/test_property_dependencies.js && node tests/test_v1_dialect.js && node tests/test_buffer_path_parity.js && node tests/test_buffer_gate.js && node tests/test_draft7_semantics.js && node tests/test_metaschema_ref.js && node tests/test_pure_js_unsupported.js && node tests/test_native_load_order.js && node tests/test_pack_purity.js && node tests/test_make_native_package.js && node tests/test_browser_nofs.js && node tests/test_browser_imports_guard.js && node tests/test_version_sync.js && node tests/test_native_loaded.js && node tests/test_safe_regex_source_sync.js && node tests/test_t_builder.js && node tests/test_async_refine.js && node tests/test_safe_regex.js && node tests/test_safe_regex_integration.js && node tests/test_aot_build.js && node tests/test_aot_differential.js && node tests/test_aot_cli_build.js && node tests/test_aot_cli_smoke.js && node tests/test_bundle_standalone.js && node tests/test_standalone_anyof.js && node tests/test_standalone_formats.js && node tests/test_aot_format_mode.js && node tests/test_aot_additional_props_errors.js && node tests/test_id_anchor_refs.js && node tests/test_engine_routing.js && node tests/test_engine_diagnostic.js && node tests/test_format_engine_parity.js && node tests/test_defs_pointer_alias.js && node tests/test_cross_doc_root_ref.js && node tests/test_codegen_entrypoint_agreement.js && node tests/test_pattern_properties_errors.js && node tests/test_no_input_mutation.js && node tests/test_typed_validator_runner.js && node tests/test_define_schema.js && node tests/test_error_codes_lock.js && node tests/test_error_code_lookup.js && node tests/test_error_order.js && node tests/test_nullable.js && node tests/test_validate_and_parse.js && node tests/test_validate_data.js && node tests/test_enrich_error.js && node tests/test_enrich_received.js && node tests/test_rich_errors_optout.js && node tests/test_error_messages.js && node tests/test_source_positions.js && node tests/fuzz_positions.js && node tests/test_data_positions.js && node tests/test_render_shared.js && node tests/test_renderers.js && node tests/test_runtime_error_dx.js && node tests/test_aot_error_dx.js && node tests/test_abort_early.js && node tests/test_branch_collapse.js && node tests/test_suggestions.js && node tests/test_cli_validate.js && node tests/test_cli_version.js && node benchmark/bench_aot_size.mjs",
47
+ "test": "node test.js && node tests/test_removed_aot_methods.js && node tests/test_no_native.js && node tests/test_no_eval.js && node tests/test_property_dependencies.js && node tests/test_v1_dialect.js && node tests/test_buffer_path_parity.js && node tests/test_buffer_gate.js && node tests/test_draft7_semantics.js && node tests/test_metaschema_ref.js && node tests/test_pure_js_unsupported.js && node tests/test_native_load_order.js && node tests/test_pack_purity.js && node tests/test_make_native_package.js && node tests/test_browser_nofs.js && node tests/test_browser_imports_guard.js && node tests/test_version_sync.js && node tests/test_native_loaded.js && node tests/test_safe_regex_source_sync.js && node tests/test_t_builder.js && node tests/test_async_refine.js && node tests/test_safe_regex.js && node tests/test_safe_regex_integration.js && node tests/test_aot_build.js && node tests/test_aot_differential.js && node tests/test_aot_cli_build.js && node tests/test_aot_cli_smoke.js && node tests/test_bundle_standalone.js && node tests/test_standalone_anyof.js && node tests/test_standalone_formats.js && node tests/test_aot_format_mode.js && node tests/test_aot_additional_props_errors.js && node tests/test_id_anchor_refs.js && node tests/test_engine_routing.js && node tests/test_engine_diagnostic.js && node tests/test_format_engine_parity.js && node tests/test_defs_pointer_alias.js && node tests/test_cross_doc_root_ref.js && node tests/test_codegen_entrypoint_agreement.js && node tests/test_pattern_properties_errors.js && node tests/test_no_input_mutation.js && node tests/test_typed_validator_runner.js && node tests/test_define_schema.js && node tests/test_error_codes_lock.js && node tests/test_error_code_lookup.js && node tests/test_error_order.js && node tests/test_lazy_errors.js && node tests/test_plan_compiler.js && node tests/test_nullable.js && node tests/test_validate_and_parse.js && node tests/test_validate_data.js && node tests/test_enrich_error.js && node tests/test_enrich_received.js && node tests/test_rich_errors_optout.js && node tests/test_error_messages.js && node tests/test_source_positions.js && node tests/fuzz_positions.js && node tests/test_data_positions.js && node tests/test_render_shared.js && node tests/test_renderers.js && node tests/test_runtime_error_dx.js && node tests/test_aot_error_dx.js && node tests/test_abort_early.js && node tests/test_branch_collapse.js && node tests/test_suggestions.js && node tests/test_cli_validate.js && node tests/test_cli_version.js && node benchmark/bench_aot_size.mjs",
48
48
  "bench:size": "node benchmark/bench_aot_size.mjs",
49
49
  "test:suite": "node tests/run_suite.js && node tests/run_suite.js draft7 && node tests/run_suite.js v1",
50
50
  "test:compat": "node tests/test_compat.js",
@@ -112,12 +112,12 @@
112
112
  "LICENSE"
113
113
  ],
114
114
  "optionalDependencies": {
115
- "@ata-validator/native-darwin-arm64": "1.7.0",
116
- "@ata-validator/native-linux-x64-gnu": "1.7.0",
117
- "@ata-validator/native-linux-arm64-gnu": "1.7.0",
118
- "@ata-validator/native-linux-x64-musl": "1.7.0",
119
- "@ata-validator/native-linux-arm64-musl": "1.7.0",
120
- "@ata-validator/native-win32-x64": "1.7.0"
115
+ "@ata-validator/native-darwin-arm64": "1.7.1",
116
+ "@ata-validator/native-linux-x64-gnu": "1.7.1",
117
+ "@ata-validator/native-linux-arm64-gnu": "1.7.1",
118
+ "@ata-validator/native-linux-x64-musl": "1.7.1",
119
+ "@ata-validator/native-linux-arm64-musl": "1.7.1",
120
+ "@ata-validator/native-win32-x64": "1.7.1"
121
121
  },
122
122
  "peerDependencies": {
123
123
  "yaml": "^2.0.0"