@sourcemeta/blaze 14.20.2 → 15.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +75 -4
- package/index.d.mts +5 -0
- package/index.mjs +428 -172
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -18,10 +18,10 @@ npm install --save @sourcemeta/blaze
|
|
|
18
18
|
|
|
19
19
|
## Usage
|
|
20
20
|
|
|
21
|
-
Blaze evaluates pre-compiled schema templates. Compile your JSON
|
|
22
|
-
Schema
|
|
23
|
-
[
|
|
24
|
-
|
|
21
|
+
Blaze evaluates pre-compiled schema templates. Compile your JSON Schema using
|
|
22
|
+
the [JSON Schema CLI](https://github.com/sourcemeta/jsonschema) (see the
|
|
23
|
+
[`compile`](https://github.com/sourcemeta/jsonschema/blob/main/docs/compile.markdown)
|
|
24
|
+
command):
|
|
25
25
|
|
|
26
26
|
```sh
|
|
27
27
|
npm install --global @sourcemeta/jsonschema
|
|
@@ -67,3 +67,74 @@ const result = evaluator.validate(instance,
|
|
|
67
67
|
});
|
|
68
68
|
console.log(result); // true or false
|
|
69
69
|
```
|
|
70
|
+
|
|
71
|
+
### Parsing large integers
|
|
72
|
+
|
|
73
|
+
JavaScript's
|
|
74
|
+
[`JSON.parse`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse)
|
|
75
|
+
silently truncates integers that exceed
|
|
76
|
+
[`Number.MAX_SAFE_INTEGER`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER)
|
|
77
|
+
to IEEE 754 double-precision floats. If your schemas or instances contain large
|
|
78
|
+
integers, pass `Blaze.reviver` to `JSON.parse` to preserve them as
|
|
79
|
+
[`BigInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt)
|
|
80
|
+
values. This relies on the
|
|
81
|
+
[`JSON.parse` source text
|
|
82
|
+
access](https://github.com/tc39/proposal-json-parse-with-source) proposal
|
|
83
|
+
(Stage 4, shipped in all major engines):
|
|
84
|
+
|
|
85
|
+
```javascript
|
|
86
|
+
const template =
|
|
87
|
+
JSON.parse(readFileSync("template.json", "utf-8"), Blaze.reviver);
|
|
88
|
+
const evaluator = new Blaze(template);
|
|
89
|
+
|
|
90
|
+
const instance =
|
|
91
|
+
JSON.parse(readFileSync("instance.json", "utf-8"), Blaze.reviver);
|
|
92
|
+
console.log(evaluator.validate(instance));
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
The evaluator handles `BigInt` values natively in all numeric instructions.
|
|
96
|
+
Without a reviver, large integers are silently truncated and validation may
|
|
97
|
+
produce incorrect results for affected values.
|
|
98
|
+
|
|
99
|
+
## Why compile separately?
|
|
100
|
+
|
|
101
|
+
Unlike validators that compile and evaluate in a single step, Blaze separates
|
|
102
|
+
the two. You compile your schemas ahead of time using the [JSON Schema
|
|
103
|
+
CLI](https://github.com/sourcemeta/jsonschema) (`jsonschema compile
|
|
104
|
+
schema.json`) on CI or at build time.
|
|
105
|
+
|
|
106
|
+
The compilation step analyses the schema, resolves all references, and produces
|
|
107
|
+
a set of optimised low-level instructions serialised as JSON that every
|
|
108
|
+
evaluator can rely on. This evaluator package then executes those instructions
|
|
109
|
+
against your data, with no knowledge of JSON Schema itself.
|
|
110
|
+
|
|
111
|
+
- **Consistent validation across languages.** The same compiled schema produces
|
|
112
|
+
identical results whether evaluated in JavaScript, Python, Java, or C++ (we
|
|
113
|
+
are working hard increase the number of ports) so you never have to rely on
|
|
114
|
+
multiple implementations with different interpretations of the standard
|
|
115
|
+
|
|
116
|
+
- **No schema processing at startup.** The evaluator loads pre-compiled
|
|
117
|
+
instructions. There is no reference resolution, or vocabulary processing at
|
|
118
|
+
runtime
|
|
119
|
+
|
|
120
|
+
- **Schema governance.** Compiled schemas can be managed, versioned, and
|
|
121
|
+
distributed centrally via [Sourcemeta One](https://one.sourcemeta.com),
|
|
122
|
+
ensuring all consumers validate against the same compiled artifact
|
|
123
|
+
|
|
124
|
+
## Limitations
|
|
125
|
+
|
|
126
|
+
**No arbitrary-precision real number support.** Large integers can be preserved
|
|
127
|
+
as `BigInt` using a reviver (see above), but JavaScript has no equivalent type
|
|
128
|
+
for arbitrary-precision real numbers. `JSON.parse` truncates values like
|
|
129
|
+
`0.1000000000000000000000000000000001` to IEEE 754 doubles, and there is no
|
|
130
|
+
reviver-based workaround:
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
$ node --eval "console.log(JSON.parse('0.1000000000000000000000000000000001'))"
|
|
134
|
+
0.1
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Numeric keywords like `multipleOf` that depend on exact decimal arithmetic may
|
|
138
|
+
produce incorrect results for real values that lose precision during parsing.
|
|
139
|
+
The TC39 [Decimal proposal](https://github.com/tc39/proposal-decimal) (Stage 2)
|
|
140
|
+
aims to address this in the future.
|
package/index.d.mts
CHANGED
|
@@ -10,6 +10,11 @@ export type EvaluationCallback = (
|
|
|
10
10
|
) => void;
|
|
11
11
|
|
|
12
12
|
export declare class Blaze {
|
|
13
|
+
static reviver(
|
|
14
|
+
key: string,
|
|
15
|
+
value: unknown,
|
|
16
|
+
context: { source: string }
|
|
17
|
+
): unknown;
|
|
13
18
|
constructor(template: Template);
|
|
14
19
|
validate(instance: unknown, callback?: EvaluationCallback): boolean;
|
|
15
20
|
}
|
package/index.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
const JSON_VERSION =
|
|
1
|
+
const JSON_VERSION = 4;
|
|
2
2
|
const DEPTH_LIMIT = 300;
|
|
3
|
-
const ANNOTATION_EMIT =
|
|
4
|
-
const ANNOTATION_TO_PARENT =
|
|
5
|
-
const ANNOTATION_BASENAME_TO_PARENT =
|
|
6
|
-
const CONTROL_GROUP_START =
|
|
7
|
-
const CONTROL_EVALUATE_END =
|
|
3
|
+
const ANNOTATION_EMIT = 49;
|
|
4
|
+
const ANNOTATION_TO_PARENT = 50;
|
|
5
|
+
const ANNOTATION_BASENAME_TO_PARENT = 51;
|
|
6
|
+
const CONTROL_GROUP_START = 92;
|
|
7
|
+
const CONTROL_EVALUATE_END = 96;
|
|
8
8
|
const URI_REGEX = /^[a-zA-Z][a-zA-Z0-9+\-.]*:[^\s]*$/;
|
|
9
9
|
|
|
10
10
|
function buildJsonPointer(tokens, length) {
|
|
@@ -33,6 +33,7 @@ function jsonTypeOf(value) {
|
|
|
33
33
|
switch (typeof value) {
|
|
34
34
|
case 'boolean': return Type.Boolean;
|
|
35
35
|
case 'number': return Number.isInteger(value) ? Type.Integer : Type.Real;
|
|
36
|
+
case 'bigint': return Type.Integer;
|
|
36
37
|
case 'string': return Type.String;
|
|
37
38
|
case 'object': return Array.isArray(value) ? Type.Array : Type.Object;
|
|
38
39
|
default: return Type.Null;
|
|
@@ -40,7 +41,8 @@ function jsonTypeOf(value) {
|
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
function isIntegral(value) {
|
|
43
|
-
return typeof value === '
|
|
44
|
+
return typeof value === 'bigint' ||
|
|
45
|
+
(typeof value === 'number' && Number.isFinite(value) && Math.floor(value) === value);
|
|
44
46
|
}
|
|
45
47
|
|
|
46
48
|
function resolveInstance(instance, relativeInstanceLocation) {
|
|
@@ -150,7 +152,7 @@ function prepareInstruction(instruction) {
|
|
|
150
152
|
function resolveJumpTargets(instructions, targets) {
|
|
151
153
|
for (let index = 0; index < instructions.length; index++) {
|
|
152
154
|
const instruction = instructions[index];
|
|
153
|
-
if (instruction[0] ===
|
|
155
|
+
if (instruction[0] === 98) {
|
|
154
156
|
const targetIndex = instruction[5];
|
|
155
157
|
if (targetIndex < targets.length) {
|
|
156
158
|
instruction[5] = targets[targetIndex];
|
|
@@ -185,7 +187,7 @@ function collectAnchorNames(targets, result) {
|
|
|
185
187
|
function collectAnchorNamesFromInstructions(instructions, result) {
|
|
186
188
|
for (let index = 0; index < instructions.length; index++) {
|
|
187
189
|
const instruction = instructions[index];
|
|
188
|
-
if (instruction[0] ===
|
|
190
|
+
if (instruction[0] === 97 && typeof instruction[5] === 'string') {
|
|
189
191
|
result.add(instruction[5]);
|
|
190
192
|
}
|
|
191
193
|
if (instruction[6]) {
|
|
@@ -250,7 +252,7 @@ function compileInstructionToCode(instruction, captures, visited, budget) {
|
|
|
250
252
|
if (cr.length !== 0) return null;
|
|
251
253
|
switch (op) {
|
|
252
254
|
case 11: return '{if(_es(' + tv + ')!==' + cv + ')return false;}';
|
|
253
|
-
case
|
|
255
|
+
case 42: return 'if(' + tv + '!=null&&typeof ' + tv + "==='object'&&!Array.isArray(" + tv + ')){' + emitResolve('t', tv, cr) + 'if(t!==void 0&&_es(t)!==' + cv + ')return false;}';
|
|
254
256
|
default: return null;
|
|
255
257
|
}
|
|
256
258
|
}
|
|
@@ -286,49 +288,52 @@ function compileInstructionToCode(instruction, captures, visited, budget) {
|
|
|
286
288
|
case 25: { var r=R('t'); return r?r+TO+'return true;var s=0;for(var k in t)s++;return s>'+value+';':null; }
|
|
287
289
|
case 26: { if(typeof value==='string'||typeof value==='number'||typeof value==='boolean'||value===null){var r=R('t');return r?r+'return t==='+JSON.stringify(value)+';':null;}return fb(26); }
|
|
288
290
|
case 27: return fb(27); case 28: return fb(28);
|
|
289
|
-
case 29: { var r=R('t'); return r?r+"
|
|
290
|
-
case 30: { var r=R('t'); return r?r+"
|
|
291
|
-
case 31: { var r=R('t'); return r?r+"
|
|
292
|
-
case 32: { var r=R('t'); return r?r+"
|
|
293
|
-
case 33: return fb(33); case 34: return fb(34);
|
|
294
|
-
case
|
|
295
|
-
case 37: return fb(37);
|
|
296
|
-
case 38: { var r=R('t'); return r?IO+r+'if(t===void 0)return true;return _es(t)==='+value+';':null; }
|
|
291
|
+
case 29: { var r=R('t'),v=typeof value==='bigint'?value+'n':value; return r?r+"var tt=typeof t;if(tt!=='number'&&tt!=='bigint')return true;return t>="+v+';':null; }
|
|
292
|
+
case 30: { var r=R('t'),v=typeof value==='bigint'?value+'n':value; return r?r+"var tt=typeof t;if(tt!=='number'&&tt!=='bigint')return true;return t<="+v+';':null; }
|
|
293
|
+
case 31: { var r=R('t'),v=typeof value==='bigint'?value+'n':value; return r?r+"var tt=typeof t;if(tt!=='number'&&tt!=='bigint')return true;return t>"+v+';':null; }
|
|
294
|
+
case 32: { var r=R('t'),v=typeof value==='bigint'?value+'n':value; return r?r+"var tt=typeof t;if(tt!=='number'&&tt!=='bigint')return true;return t<"+v+';':null; }
|
|
295
|
+
case 33: return fb(33); case 34: return fb(34);
|
|
296
|
+
case 35: return fb(35); case 36: return fb(36); case 37: return fb(37); case 38: return fb(38);
|
|
297
297
|
case 39: return fb(39);
|
|
298
|
-
case 40: { var r=R('t'); return r?IO+r+'if(t===void 0)return true;return('+value+'
|
|
299
|
-
case 41: return fb(41);
|
|
300
|
-
case
|
|
301
|
-
case
|
|
302
|
-
case
|
|
303
|
-
case
|
|
304
|
-
case
|
|
305
|
-
case
|
|
306
|
-
case 53: return
|
|
307
|
-
case 54:
|
|
308
|
-
case 55: { var r=R('t'); if(!r)return null; var c=r+
|
|
309
|
-
case 56: { var r=R('t'); if(!r)return null;
|
|
310
|
-
case 57:
|
|
311
|
-
case
|
|
312
|
-
case
|
|
313
|
-
case
|
|
314
|
-
case
|
|
315
|
-
case
|
|
316
|
-
case
|
|
298
|
+
case 40: { var r=R('t'); return r?IO+r+'if(t===void 0)return true;var a=_jt(t);return a==='+value+'||('+value+'===2&&_ii(t));':null; }
|
|
299
|
+
case 41: return fb(41);
|
|
300
|
+
case 42: { var r=R('t'); return r?IO+r+'if(t===void 0)return true;return _es(t)==='+value+';':null; }
|
|
301
|
+
case 43: return fb(43);
|
|
302
|
+
case 44: { var r=R('t'); return r?IO+r+'if(t===void 0)return true;return('+value+'&(1<<_es(t)))!==0;':null; }
|
|
303
|
+
case 45: return fb(45); case 46: return fb(46); case 47: return fb(47);
|
|
304
|
+
case 48: return fb(48);
|
|
305
|
+
case 49: return 'return true;'; case 50: return 'return true;'; case 51: return 'return true;'; case 52: return 'return true;';
|
|
306
|
+
case 53: { var r=R('t'); if(!r)return null; if(!children||children.length===0)return 'return false;'; var c=r; for(var j=0;j<children.length;j++)c+='if(!'+cc(children[j],'t')+')return true;'; return c+'return false;'; }
|
|
307
|
+
case 54: return fb(54);
|
|
308
|
+
case 55: { var r=R('t'); if(!r)return null; if(!children||children.length===0)return 'return true;'; if(value){var c=r+'var __r=false;';for(var j=0;j<children.length;j++)c+='if('+cc(children[j],'t')+')__r=true;';return c+'return __r;';} var c=r;for(var j=0;j<children.length;j++)c+='if('+cc(children[j],'t')+')return true;';return c+'return false;'; }
|
|
309
|
+
case 56: { var r=R('t'); if(!r)return null; if(!children||children.length===0)return 'return true;'; return r+seq(children,'t')+'return true;'; }
|
|
310
|
+
case 57: { var r=R('t'); if(!r)return null; if(!children||children.length===0)return 'return false;'; var c=r+'var __r=true,__m=false;';for(var j=0;j<children.length;j++){c+='if('+cc(children[j],'t')+'){if(__m){__r=false;'+(!value?'return false;':'')+ '}else __m=true;}';}return c+'return __r&&__m;'; }
|
|
311
|
+
case 58: return fb(58);
|
|
312
|
+
case 59: { var r=R('t'); if(!r)return null; var c=r+'if(_jt(t)!=='+value+')return true;'; if(children&&children.length>0)c+=seq(children,'t'); return c+'return true;'; }
|
|
313
|
+
case 60: { var r=R('t'); if(!r)return null; var c=r+TO+'return true;if(!Object.hasOwn(t,'+JSON.stringify(value)+'))return true;'; if(children&&children.length>0)c+=seq(children,'t'); return c+'return true;'; }
|
|
314
|
+
case 61: { var r=R('t'); if(!r)return null; var c=r+'if(!Array.isArray(t)||t.length<='+value+')return true;'; if(children&&children.length>0)c+=seq(children,'t'); return c+'return true;'; }
|
|
315
|
+
case 62: return fb(62); case 63: return fb(63);
|
|
316
|
+
case 64: { var r=R('t'); if(!r)return null; if(!children||children.length===0)return r+'return true;'; var mi=captures.length; captures.push(value); var gf=''; for(var gi=0;gi<children.length;gi++){var gc=children[gi][6]; if(gc&&gc.length>0){gf+='function(i,d,_t,_v){'+lb(gc,'i')+'return true;},';}else{gf+='null,';}} return r+TO+'return true;var __cg=['+gf+'];for(var k in t){var __mi=_c['+mi+'][k];if(__mi!==void 0){var __cf=__cg[__mi];if(__cf&&!__cf(t,d,_t,_v))return false;}}return true;'; }
|
|
317
|
+
case 65: { var r=R('t'); if(!r)return null; if(!children||children.length===0)return r+'return true;'; var mi=captures.length; captures.push(value); var gf=''; for(var gi=0;gi<children.length;gi++){var gc=children[gi][6]; if(gc&&gc.length>0){gf+='function(i,d,_t,_v){'+lb(gc,'i')+'return true;},';}else{gf+='null,';}} return r+TO+'return true;var __cg=['+gf+'];for(var k in t){var __mi=_c['+mi+'][k];if(__mi===void 0)return false;var __cf=__cg[__mi];if(__cf&&!__cf(t,d,_t,_v))return false;}return true;'; }
|
|
318
|
+
case 66: { var r=R('t'); if(!r)return null; if(!children||children.length===0)return r+'return true;'; return r+TO+'return true;for(var k in t){'+lb(children,'t[k]')+'}return true;'; }
|
|
319
|
+
case 67: return fb(67); case 68: return fb(68); case 69: return fb(69); case 70: return fb(70); case 71: return fb(71);
|
|
317
320
|
case 72: return fb(72); case 73: return fb(73); case 74: return fb(74); case 75: return fb(75);
|
|
318
|
-
case 76: { var r=R('t');
|
|
319
|
-
case 77:
|
|
320
|
-
case
|
|
321
|
-
case
|
|
322
|
-
case
|
|
323
|
-
case
|
|
324
|
-
case
|
|
325
|
-
case
|
|
326
|
-
case
|
|
327
|
-
case
|
|
328
|
-
case
|
|
329
|
-
case
|
|
330
|
-
case
|
|
331
|
-
case
|
|
321
|
+
case 76: { var r=R('t'); return r?r+TO+'return true;for(var k in t){if(_es(t[k])!=='+value+')return false;}return true;':null; }
|
|
322
|
+
case 77: return fb(77); case 78: return fb(78); case 79: return fb(79); case 80: return fb(80);
|
|
323
|
+
case 81: { var r=R('t'); if(!r)return null; if(!children||children.length===0)return r+'return true;'; return r+'if(!Array.isArray(t))return true;for(var j=0;j<t.length;j++){'+lb(children,'t[j]')+'}return true;'; }
|
|
324
|
+
case 82: { var r=R('t'); if(!r)return null; if(!children||children.length===0)return r+'return true;'; return r+'if(!Array.isArray(t)||'+value+'>=t.length)return true;for(var j='+value+';j<t.length;j++){'+lb(children,'t[j]')+'}return true;'; }
|
|
325
|
+
case 83: return fb(83);
|
|
326
|
+
case 84: { var r=R('t'); return r?r+'if(!Array.isArray(t))return true;for(var j=0;j<t.length;j++){var a=_jt(t[j]);if(a!=='+value+'&&!('+value+'===2&&_ii(t[j])))return false;}return true;':null; }
|
|
327
|
+
case 85: { var r=R('t'); return r?r+'if(!Array.isArray(t))return true;for(var j=0;j<t.length;j++){if(_es(t[j])!=='+value+')return false;}return true;':null; }
|
|
328
|
+
case 86: { var r=R('t'); return r?r+'if(!Array.isArray(t))return true;for(var j=0;j<t.length;j++){if(('+value+'&(1<<_es(t[j])))===0)return false;}return true;':null; }
|
|
329
|
+
case 87: return fb(87); case 88: return fb(88); case 89: return fb(89); case 90: return fb(90); case 91: return fb(91);
|
|
330
|
+
case 92: { if(!children||children.length===0)return 'return true;'; var c=''; for(var j=0;j<children.length;j++){var r2=compileInstructionToCode(children[j],captures,visited,budget); if(r2===null){var ci=captures.length;captures.push(children[j]);c+='if(!_e(_c['+ci+'],i,d+1,_t,_v))return false;';}else{budget[0]-=r2.length;c+='if(!(function(i,d,_t,_v){'+r2+'})(i,d+1,_t,_v))return false;';}} return c+'return true;'; }
|
|
331
|
+
case 93: { var r=R('t'); if(!r)return null; var c=r+TO+'return true;if(!Object.hasOwn(t,'+JSON.stringify(value)+'))return true;'; if(children&&children.length>0)c+=seq(children,'i'); return c+'return true;'; }
|
|
332
|
+
case 94: { var c=IO+'if(!Object.hasOwn(i,'+JSON.stringify(value)+'))return true;'; if(children&&children.length>0)c+=seq(children,'i'); return c+'return true;'; }
|
|
333
|
+
case 95: { var c='if(_jt(i)!=='+value+')return true;'; if(children&&children.length>0)c+=seq(children,'i'); return c+'return true;'; }
|
|
334
|
+
case 96: return 'return true;';
|
|
335
|
+
case 97: return fb(97);
|
|
336
|
+
case 98: { if(!value)return 'return true;'; if(visited&&visited.has(instruction))return fb(98); if(!visited)visited=new Set(); visited.add(instruction); var r=R('t'); if(!r)return fb(98); var c=r; for(var j=0;j<value.length;j++){var r2=compileInstructionToCode(value[j],captures,visited,budget); if(r2===null){var ci=captures.length;captures.push(value[j]);c+='if(!_e(_c['+ci+'],t,d+1,_t,_v))return false;';}else{budget[0]-=r2.length;c+='if(!(function(i,d,_t,_v){'+r2+'})(t,d+1,_t,_v))return false;';}} return c+'return true;'; }
|
|
332
337
|
default: return null;
|
|
333
338
|
}
|
|
334
339
|
}
|
|
@@ -366,7 +371,35 @@ function generateNativeValidator(template) {
|
|
|
366
371
|
}
|
|
367
372
|
}
|
|
368
373
|
|
|
374
|
+
function sourceToBigInt(source) {
|
|
375
|
+
// Plain integer like "99999999999999999999999999999999999"
|
|
376
|
+
if (/^-?[0-9]+$/.test(source)) return BigInt(source);
|
|
377
|
+
// Exponential notation like "9.9999999999999999e+34". Parse the coefficient
|
|
378
|
+
// and exponent to reconstruct the exact integer, as `BigInt` cannot parse
|
|
379
|
+
// exponential notation directly
|
|
380
|
+
const match = source.match(/^(-?)([0-9]+)\.?([0-9]*)[eE][+]?([0-9]+)$/);
|
|
381
|
+
if (!match) return null;
|
|
382
|
+
const exponent = parseInt(match[4]) - match[3].length;
|
|
383
|
+
if (exponent < 0) return null;
|
|
384
|
+
return BigInt(match[1] + match[2] + match[3]) * (10n ** BigInt(exponent));
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
function reviver(_key, value, context) {
|
|
388
|
+
// On older engines, `JSON.parse` calls the reviver with only two arguments
|
|
389
|
+
if (context === undefined) return value;
|
|
390
|
+
if (typeof value !== 'number') return value;
|
|
391
|
+
const source = context.source;
|
|
392
|
+
// Only convert when `JSON.parse` actually truncated the value, avoiding
|
|
393
|
+
// unnecessary `BigInt` conversion for integers that are exactly
|
|
394
|
+
// representable as doubles
|
|
395
|
+
if (String(value) === source) return value;
|
|
396
|
+
const bigint = sourceToBigInt(source);
|
|
397
|
+
return bigint !== null ? bigint : value;
|
|
398
|
+
}
|
|
399
|
+
|
|
369
400
|
class Blaze {
|
|
401
|
+
static reviver = reviver;
|
|
402
|
+
|
|
370
403
|
constructor(template) {
|
|
371
404
|
if (!Array.isArray(template) || template[0] !== JSON_VERSION) {
|
|
372
405
|
throw new Error(
|
|
@@ -623,7 +656,7 @@ function evaluateInstructionTracked(instruction, instance, depth, template, eval
|
|
|
623
656
|
if (!handler) return true;
|
|
624
657
|
|
|
625
658
|
const type = instruction[0];
|
|
626
|
-
if (type <
|
|
659
|
+
if (type < 92 || type > 96) {
|
|
627
660
|
if (evaluator.trackMode) {
|
|
628
661
|
evaluator.pushPath(instruction[1]);
|
|
629
662
|
}
|
|
@@ -691,6 +724,7 @@ function effectiveTypeStrictReal(value) {
|
|
|
691
724
|
switch (typeof value) {
|
|
692
725
|
case 'boolean': return Type.Boolean;
|
|
693
726
|
case 'number': return Number.isInteger(value) ? Type.Integer : Type.Real;
|
|
727
|
+
case 'bigint': return Type.Integer;
|
|
694
728
|
case 'string': return Type.String;
|
|
695
729
|
case 'object': return Array.isArray(value) ? Type.Array : Type.Object;
|
|
696
730
|
default: return Type.Null;
|
|
@@ -730,6 +764,7 @@ function fastHash(value) {
|
|
|
730
764
|
switch (typeof value) {
|
|
731
765
|
case 'boolean': return value ? 1 : 0;
|
|
732
766
|
case 'number': return 4 + ((value | 0) & 255);
|
|
767
|
+
case 'bigint': return 4 + Number(value & 255n);
|
|
733
768
|
case 'string': return 3 + value.length;
|
|
734
769
|
case 'object':
|
|
735
770
|
if (Array.isArray(value)) {
|
|
@@ -782,7 +817,15 @@ function isUnique(array) {
|
|
|
782
817
|
}
|
|
783
818
|
|
|
784
819
|
function isDivisibleBy(value, divisor) {
|
|
785
|
-
if (divisor === 0) return false;
|
|
820
|
+
if (divisor === 0 || divisor === 0n) return false;
|
|
821
|
+
if (typeof value === 'bigint' && typeof divisor === 'bigint') {
|
|
822
|
+
return value % divisor === 0n;
|
|
823
|
+
}
|
|
824
|
+
if (typeof value === 'bigint') {
|
|
825
|
+
value = Number(value);
|
|
826
|
+
} else if (typeof divisor === 'bigint') {
|
|
827
|
+
divisor = Number(divisor);
|
|
828
|
+
}
|
|
786
829
|
const remainder = value % divisor;
|
|
787
830
|
if (remainder === 0) return true;
|
|
788
831
|
return Math.abs(remainder) < 1e-9 || Math.abs(remainder - divisor) < 1e-9 ||
|
|
@@ -1231,7 +1274,8 @@ function AssertionEqualsAnyStringHash(instruction, instance, depth, template, ev
|
|
|
1231
1274
|
|
|
1232
1275
|
function AssertionGreaterEqual(instruction, instance, depth, template, evaluator) {
|
|
1233
1276
|
const target = resolveInstance(instance, instruction[2]);
|
|
1234
|
-
|
|
1277
|
+
const targetType = typeof target;
|
|
1278
|
+
if (targetType !== 'number' && targetType !== 'bigint') return true;
|
|
1235
1279
|
if (evaluator.callbackMode) evaluator.callbackPush(instruction);
|
|
1236
1280
|
const __result = target >= instruction[5];
|
|
1237
1281
|
if (evaluator.callbackMode) evaluator.callbackPop(instruction, __result);
|
|
@@ -1240,7 +1284,8 @@ function AssertionGreaterEqual(instruction, instance, depth, template, evaluator
|
|
|
1240
1284
|
|
|
1241
1285
|
function AssertionLessEqual(instruction, instance, depth, template, evaluator) {
|
|
1242
1286
|
const target = resolveInstance(instance, instruction[2]);
|
|
1243
|
-
|
|
1287
|
+
const targetType = typeof target;
|
|
1288
|
+
if (targetType !== 'number' && targetType !== 'bigint') return true;
|
|
1244
1289
|
if (evaluator.callbackMode) evaluator.callbackPush(instruction);
|
|
1245
1290
|
const __result = target <= instruction[5];
|
|
1246
1291
|
if (evaluator.callbackMode) evaluator.callbackPop(instruction, __result);
|
|
@@ -1249,7 +1294,8 @@ function AssertionLessEqual(instruction, instance, depth, template, evaluator) {
|
|
|
1249
1294
|
|
|
1250
1295
|
function AssertionGreater(instruction, instance, depth, template, evaluator) {
|
|
1251
1296
|
const target = resolveInstance(instance, instruction[2]);
|
|
1252
|
-
|
|
1297
|
+
const targetType = typeof target;
|
|
1298
|
+
if (targetType !== 'number' && targetType !== 'bigint') return true;
|
|
1253
1299
|
if (evaluator.callbackMode) evaluator.callbackPush(instruction);
|
|
1254
1300
|
const __result = target > instruction[5];
|
|
1255
1301
|
if (evaluator.callbackMode) evaluator.callbackPop(instruction, __result);
|
|
@@ -1258,7 +1304,8 @@ function AssertionGreater(instruction, instance, depth, template, evaluator) {
|
|
|
1258
1304
|
|
|
1259
1305
|
function AssertionLess(instruction, instance, depth, template, evaluator) {
|
|
1260
1306
|
const target = resolveInstance(instance, instruction[2]);
|
|
1261
|
-
|
|
1307
|
+
const targetType = typeof target;
|
|
1308
|
+
if (targetType !== 'number' && targetType !== 'bigint') return true;
|
|
1262
1309
|
if (evaluator.callbackMode) evaluator.callbackPush(instruction);
|
|
1263
1310
|
const __result = target < instruction[5];
|
|
1264
1311
|
if (evaluator.callbackMode) evaluator.callbackPop(instruction, __result);
|
|
@@ -1276,13 +1323,50 @@ function AssertionUnique(instruction, instance, depth, template, evaluator) {
|
|
|
1276
1323
|
|
|
1277
1324
|
function AssertionDivisible(instruction, instance, depth, template, evaluator) {
|
|
1278
1325
|
const target = resolveInstance(instance, instruction[2]);
|
|
1279
|
-
|
|
1326
|
+
const targetType = typeof target;
|
|
1327
|
+
if (targetType !== 'number' && targetType !== 'bigint') return true;
|
|
1280
1328
|
if (evaluator.callbackMode) evaluator.callbackPush(instruction);
|
|
1281
1329
|
const __result = isDivisibleBy(target, instruction[5]);
|
|
1282
1330
|
if (evaluator.callbackMode) evaluator.callbackPop(instruction, __result);
|
|
1283
1331
|
return __result;
|
|
1284
1332
|
};
|
|
1285
1333
|
|
|
1334
|
+
function AssertionTypeIntegerBounded(instruction, instance, depth, template, evaluator) {
|
|
1335
|
+
const target = resolveInstance(instance, instruction[2]);
|
|
1336
|
+
if (evaluator.callbackMode) evaluator.callbackPush(instruction);
|
|
1337
|
+
const range = instruction[5];
|
|
1338
|
+
const __result = (typeof target === 'bigint' || Number.isInteger(target)) && target >= range[0] && target <= range[1];
|
|
1339
|
+
if (evaluator.callbackMode) evaluator.callbackPop(instruction, __result);
|
|
1340
|
+
return __result;
|
|
1341
|
+
};
|
|
1342
|
+
|
|
1343
|
+
function AssertionTypeIntegerBoundedStrict(instruction, instance, depth, template, evaluator) {
|
|
1344
|
+
const target = resolveInstance(instance, instruction[2]);
|
|
1345
|
+
if (evaluator.callbackMode) evaluator.callbackPush(instruction);
|
|
1346
|
+
const range = instruction[5];
|
|
1347
|
+
const __result = (typeof target === 'bigint' || Number.isInteger(target)) && target >= range[0] && target <= range[1];
|
|
1348
|
+
if (evaluator.callbackMode) evaluator.callbackPop(instruction, __result);
|
|
1349
|
+
return __result;
|
|
1350
|
+
};
|
|
1351
|
+
|
|
1352
|
+
function AssertionTypeIntegerLowerBound(instruction, instance, depth, template, evaluator) {
|
|
1353
|
+
const target = resolveInstance(instance, instruction[2]);
|
|
1354
|
+
if (evaluator.callbackMode) evaluator.callbackPush(instruction);
|
|
1355
|
+
const range = instruction[5];
|
|
1356
|
+
const __result = (typeof target === 'bigint' || Number.isInteger(target)) && target >= range[0];
|
|
1357
|
+
if (evaluator.callbackMode) evaluator.callbackPop(instruction, __result);
|
|
1358
|
+
return __result;
|
|
1359
|
+
};
|
|
1360
|
+
|
|
1361
|
+
function AssertionTypeIntegerLowerBoundStrict(instruction, instance, depth, template, evaluator) {
|
|
1362
|
+
const target = resolveInstance(instance, instruction[2]);
|
|
1363
|
+
if (evaluator.callbackMode) evaluator.callbackPush(instruction);
|
|
1364
|
+
const range = instruction[5];
|
|
1365
|
+
const __result = (typeof target === 'bigint' || Number.isInteger(target)) && target >= range[0];
|
|
1366
|
+
if (evaluator.callbackMode) evaluator.callbackPop(instruction, __result);
|
|
1367
|
+
return __result;
|
|
1368
|
+
};
|
|
1369
|
+
|
|
1286
1370
|
function AssertionStringType(instruction, instance, depth, template, evaluator) {
|
|
1287
1371
|
const target = evaluator.propertyTarget !== undefined
|
|
1288
1372
|
? evaluator.propertyTarget : resolveInstance(instance, instruction[2]);
|
|
@@ -1428,6 +1512,37 @@ function AssertionArrayPrefixEvaluate(instruction, instance, depth, template, ev
|
|
|
1428
1512
|
return true;
|
|
1429
1513
|
};
|
|
1430
1514
|
|
|
1515
|
+
function AssertionObjectPropertiesSimple(instruction, instance, depth, template, evaluator) {
|
|
1516
|
+
const target = resolveInstance(instance, instruction[2]);
|
|
1517
|
+
if (evaluator.callbackMode) evaluator.callbackPush(instruction);
|
|
1518
|
+
if (!isObject(target)) {
|
|
1519
|
+
if (evaluator.callbackMode) evaluator.callbackPop(instruction, false);
|
|
1520
|
+
return false;
|
|
1521
|
+
}
|
|
1522
|
+
const value = instruction[5];
|
|
1523
|
+
const children = instruction[6];
|
|
1524
|
+
for (let index = 0; index < value.length; index++) {
|
|
1525
|
+
const entry = value[index];
|
|
1526
|
+
const name = entry[0];
|
|
1527
|
+
const required = entry[2];
|
|
1528
|
+
if (!Object.hasOwn(target, name)) {
|
|
1529
|
+
if (required) {
|
|
1530
|
+
if (evaluator.callbackMode) evaluator.callbackPop(instruction, false);
|
|
1531
|
+
return false;
|
|
1532
|
+
}
|
|
1533
|
+
continue;
|
|
1534
|
+
}
|
|
1535
|
+
if (index < children.length) {
|
|
1536
|
+
if (!evaluateInstructionFast(children[index], target[name], depth + 1, template, evaluator)) {
|
|
1537
|
+
if (evaluator.callbackMode) evaluator.callbackPop(instruction, false);
|
|
1538
|
+
return false;
|
|
1539
|
+
}
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
if (evaluator.callbackMode) evaluator.callbackPop(instruction, true);
|
|
1543
|
+
return true;
|
|
1544
|
+
};
|
|
1545
|
+
|
|
1431
1546
|
function AnnotationEmit(instruction, instance, depth, template, evaluator) {
|
|
1432
1547
|
if (evaluator.callbackMode) evaluator.callbackAnnotation(instruction);
|
|
1433
1548
|
return true;
|
|
@@ -2288,6 +2403,56 @@ function LoopItemsPropertiesExactlyTypeStrictHash(instruction, instance, depth,
|
|
|
2288
2403
|
if (evaluator.callbackMode) evaluator.callbackPop(instruction, true);
|
|
2289
2404
|
return true;
|
|
2290
2405
|
};
|
|
2406
|
+
|
|
2407
|
+
function LoopItemsIntegerBounded(instruction, instance, depth, template, evaluator) {
|
|
2408
|
+
const target = resolveInstance(instance, instruction[2]);
|
|
2409
|
+
if (!Array.isArray(target) || target.length === 0) return true;
|
|
2410
|
+
if (evaluator.callbackMode) evaluator.callbackPush(instruction);
|
|
2411
|
+
const minimum = instruction[5][0];
|
|
2412
|
+
const maximum = instruction[5][1];
|
|
2413
|
+
for (let index = 0; index < target.length; index++) {
|
|
2414
|
+
const element = target[index];
|
|
2415
|
+
const elementType = typeof element;
|
|
2416
|
+
if (elementType !== 'number' && elementType !== 'bigint') {
|
|
2417
|
+
if (evaluator.callbackMode) evaluator.callbackPop(instruction, false);
|
|
2418
|
+
return false;
|
|
2419
|
+
}
|
|
2420
|
+
if (element < minimum || element > maximum) {
|
|
2421
|
+
if (evaluator.callbackMode) evaluator.callbackPop(instruction, false);
|
|
2422
|
+
return false;
|
|
2423
|
+
}
|
|
2424
|
+
}
|
|
2425
|
+
if (evaluator.callbackMode) evaluator.callbackPop(instruction, true);
|
|
2426
|
+
return true;
|
|
2427
|
+
};
|
|
2428
|
+
|
|
2429
|
+
function LoopItemsIntegerBoundedSized(instruction, instance, depth, template, evaluator) {
|
|
2430
|
+
const value = instruction[5];
|
|
2431
|
+
const minimum = value[0][0];
|
|
2432
|
+
const maximum = value[0][1];
|
|
2433
|
+
const minimumSize = value[1][0];
|
|
2434
|
+
const target = resolveInstance(instance, instruction[2]);
|
|
2435
|
+
if (evaluator.callbackMode) evaluator.callbackPush(instruction);
|
|
2436
|
+
if (!Array.isArray(target) || target.length < minimumSize) {
|
|
2437
|
+
if (evaluator.callbackMode) evaluator.callbackPop(instruction, false);
|
|
2438
|
+
return false;
|
|
2439
|
+
}
|
|
2440
|
+
for (let index = 0; index < target.length; index++) {
|
|
2441
|
+
const element = target[index];
|
|
2442
|
+
const elementType = typeof element;
|
|
2443
|
+
if (elementType !== 'number' && elementType !== 'bigint') {
|
|
2444
|
+
if (evaluator.callbackMode) evaluator.callbackPop(instruction, false);
|
|
2445
|
+
return false;
|
|
2446
|
+
}
|
|
2447
|
+
if (element < minimum || element > maximum) {
|
|
2448
|
+
if (evaluator.callbackMode) evaluator.callbackPop(instruction, false);
|
|
2449
|
+
return false;
|
|
2450
|
+
}
|
|
2451
|
+
}
|
|
2452
|
+
if (evaluator.callbackMode) evaluator.callbackPop(instruction, true);
|
|
2453
|
+
return true;
|
|
2454
|
+
};
|
|
2455
|
+
|
|
2291
2456
|
function LoopContains(instruction, instance, depth, template, evaluator) {
|
|
2292
2457
|
const target = resolveInstance(instance, instruction[2]);
|
|
2293
2458
|
if (!Array.isArray(target)) return true;
|
|
@@ -2467,63 +2632,70 @@ const handlers = [
|
|
|
2467
2632
|
AssertionLess, // 32
|
|
2468
2633
|
AssertionUnique, // 33
|
|
2469
2634
|
AssertionDivisible, // 34
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2635
|
+
AssertionTypeIntegerBounded, // 35
|
|
2636
|
+
AssertionTypeIntegerBoundedStrict, // 36
|
|
2637
|
+
AssertionTypeIntegerLowerBound, // 37
|
|
2638
|
+
AssertionTypeIntegerLowerBoundStrict, // 38
|
|
2639
|
+
AssertionStringType, // 39
|
|
2640
|
+
AssertionPropertyType, // 40
|
|
2641
|
+
AssertionPropertyTypeEvaluate, // 41
|
|
2642
|
+
AssertionPropertyTypeStrict, // 42
|
|
2643
|
+
AssertionPropertyTypeStrictEvaluate, // 43
|
|
2644
|
+
AssertionPropertyTypeStrictAny, // 44
|
|
2645
|
+
AssertionPropertyTypeStrictAnyEvaluate, // 45
|
|
2646
|
+
AssertionArrayPrefix, // 46
|
|
2647
|
+
AssertionArrayPrefixEvaluate, // 47
|
|
2648
|
+
AssertionObjectPropertiesSimple, // 48
|
|
2649
|
+
AnnotationEmit, // 49
|
|
2650
|
+
AnnotationToParent, // 50
|
|
2651
|
+
AnnotationBasenameToParent, // 51
|
|
2652
|
+
Evaluate, // 52
|
|
2653
|
+
LogicalNot, // 53
|
|
2654
|
+
LogicalNotEvaluate, // 54
|
|
2655
|
+
LogicalOr, // 55
|
|
2656
|
+
LogicalAnd, // 56
|
|
2657
|
+
LogicalXor, // 57
|
|
2658
|
+
LogicalCondition, // 58
|
|
2659
|
+
LogicalWhenType, // 59
|
|
2660
|
+
LogicalWhenDefines, // 60
|
|
2661
|
+
LogicalWhenArraySizeGreater, // 61
|
|
2662
|
+
LoopPropertiesUnevaluated, // 62
|
|
2663
|
+
LoopPropertiesUnevaluatedExcept, // 63
|
|
2664
|
+
LoopPropertiesMatch, // 64
|
|
2665
|
+
LoopPropertiesMatchClosed, // 65
|
|
2666
|
+
LoopProperties, // 66
|
|
2667
|
+
LoopPropertiesEvaluate, // 67
|
|
2668
|
+
LoopPropertiesRegex, // 68
|
|
2669
|
+
LoopPropertiesRegexClosed, // 69
|
|
2670
|
+
LoopPropertiesStartsWith, // 70
|
|
2671
|
+
LoopPropertiesExcept, // 71
|
|
2672
|
+
LoopPropertiesType, // 72
|
|
2673
|
+
LoopPropertiesTypeEvaluate, // 73
|
|
2674
|
+
LoopPropertiesExactlyTypeStrict, // 74
|
|
2675
|
+
LoopPropertiesExactlyTypeStrictHash, // 75
|
|
2676
|
+
LoopPropertiesTypeStrict, // 76
|
|
2677
|
+
LoopPropertiesTypeStrictEvaluate, // 77
|
|
2678
|
+
LoopPropertiesTypeStrictAny, // 78
|
|
2679
|
+
LoopPropertiesTypeStrictAnyEvaluate, // 79
|
|
2680
|
+
LoopKeys, // 80
|
|
2681
|
+
LoopItems, // 81
|
|
2682
|
+
LoopItemsFrom, // 82
|
|
2683
|
+
LoopItemsUnevaluated, // 83
|
|
2684
|
+
LoopItemsType, // 84
|
|
2685
|
+
LoopItemsTypeStrict, // 85
|
|
2686
|
+
LoopItemsTypeStrictAny, // 86
|
|
2687
|
+
LoopItemsPropertiesExactlyTypeStrictHash, // 87
|
|
2688
|
+
LoopItemsPropertiesExactlyTypeStrictHash, // 88
|
|
2689
|
+
LoopItemsIntegerBounded, // 89
|
|
2690
|
+
LoopItemsIntegerBoundedSized, // 90
|
|
2691
|
+
LoopContains, // 91
|
|
2692
|
+
ControlGroup, // 92
|
|
2693
|
+
ControlGroupWhenDefines, // 93
|
|
2694
|
+
ControlGroupWhenDefinesDirect, // 94
|
|
2695
|
+
ControlGroupWhenType, // 95
|
|
2696
|
+
ControlEvaluate, // 96
|
|
2697
|
+
ControlDynamicAnchorJump, // 97
|
|
2698
|
+
ControlJump // 98
|
|
2527
2699
|
];
|
|
2528
2700
|
|
|
2529
2701
|
function AssertionTypeArrayBounded_fast(instruction, instance, depth, template, evaluator) {
|
|
@@ -3101,25 +3273,29 @@ function AssertionObjectSizeGreater_fast(instruction, instance, depth, template,
|
|
|
3101
3273
|
|
|
3102
3274
|
function AssertionGreaterEqual_fast(instruction, instance, depth, template, evaluator) {
|
|
3103
3275
|
const target = resolveInstance(instance, instruction[2]);
|
|
3104
|
-
|
|
3276
|
+
const targetType = typeof target;
|
|
3277
|
+
if (targetType !== 'number' && targetType !== 'bigint') return true;
|
|
3105
3278
|
return target >= instruction[5];
|
|
3106
3279
|
}
|
|
3107
3280
|
|
|
3108
3281
|
function AssertionLessEqual_fast(instruction, instance, depth, template, evaluator) {
|
|
3109
3282
|
const target = resolveInstance(instance, instruction[2]);
|
|
3110
|
-
|
|
3283
|
+
const targetType = typeof target;
|
|
3284
|
+
if (targetType !== 'number' && targetType !== 'bigint') return true;
|
|
3111
3285
|
return target <= instruction[5];
|
|
3112
3286
|
}
|
|
3113
3287
|
|
|
3114
3288
|
function AssertionGreater_fast(instruction, instance, depth, template, evaluator) {
|
|
3115
3289
|
const target = resolveInstance(instance, instruction[2]);
|
|
3116
|
-
|
|
3290
|
+
const targetType = typeof target;
|
|
3291
|
+
if (targetType !== 'number' && targetType !== 'bigint') return true;
|
|
3117
3292
|
return target > instruction[5];
|
|
3118
3293
|
}
|
|
3119
3294
|
|
|
3120
3295
|
function AssertionLess_fast(instruction, instance, depth, template, evaluator) {
|
|
3121
3296
|
const target = resolveInstance(instance, instruction[2]);
|
|
3122
|
-
|
|
3297
|
+
const targetType = typeof target;
|
|
3298
|
+
if (targetType !== 'number' && targetType !== 'bigint') return true;
|
|
3123
3299
|
return target < instruction[5];
|
|
3124
3300
|
}
|
|
3125
3301
|
|
|
@@ -3131,7 +3307,8 @@ function AssertionUnique_fast(instruction, instance, depth, template, evaluator)
|
|
|
3131
3307
|
|
|
3132
3308
|
function AssertionDivisible_fast(instruction, instance, depth, template, evaluator) {
|
|
3133
3309
|
const target = resolveInstance(instance, instruction[2]);
|
|
3134
|
-
|
|
3310
|
+
const targetType = typeof target;
|
|
3311
|
+
if (targetType !== 'number' && targetType !== 'bigint') return true;
|
|
3135
3312
|
return isDivisibleBy(target, instruction[5]);
|
|
3136
3313
|
}
|
|
3137
3314
|
|
|
@@ -3239,6 +3416,26 @@ function AssertionArrayPrefixEvaluate_fast(instruction, instance, depth, templat
|
|
|
3239
3416
|
return true;
|
|
3240
3417
|
}
|
|
3241
3418
|
|
|
3419
|
+
function AssertionObjectPropertiesSimple_fast(instruction, instance, depth, template, evaluator) {
|
|
3420
|
+
const target = resolveInstance(instance, instruction[2]);
|
|
3421
|
+
if (!isObject(target)) return false;
|
|
3422
|
+
const value = instruction[5];
|
|
3423
|
+
const children = instruction[6];
|
|
3424
|
+
for (let index = 0; index < value.length; index++) {
|
|
3425
|
+
const entry = value[index];
|
|
3426
|
+
const name = entry[0];
|
|
3427
|
+
const required = entry[2];
|
|
3428
|
+
if (!Object.hasOwn(target, name)) {
|
|
3429
|
+
if (required) return false;
|
|
3430
|
+
continue;
|
|
3431
|
+
}
|
|
3432
|
+
if (index < children.length) {
|
|
3433
|
+
if (!evaluateInstructionFast(children[index], target[name], depth + 1, template, evaluator)) return false;
|
|
3434
|
+
}
|
|
3435
|
+
}
|
|
3436
|
+
return true;
|
|
3437
|
+
}
|
|
3438
|
+
|
|
3242
3439
|
function AnnotationEmit_fast() { return true; }
|
|
3243
3440
|
function AnnotationToParent_fast() { return true; }
|
|
3244
3441
|
function AnnotationBasenameToParent_fast() { return true; }
|
|
@@ -3622,37 +3819,89 @@ function ControlDynamicAnchorJump_fast(instruction, instance, depth, template, e
|
|
|
3622
3819
|
return false;
|
|
3623
3820
|
}
|
|
3624
3821
|
|
|
3822
|
+
function LoopItemsIntegerBounded_fast(instruction, instance, depth, template, evaluator) {
|
|
3823
|
+
const target = resolveInstance(instance, instruction[2]);
|
|
3824
|
+
if (!Array.isArray(target) || target.length === 0) return true;
|
|
3825
|
+
const minimum = instruction[5][0];
|
|
3826
|
+
const maximum = instruction[5][1];
|
|
3827
|
+
for (let index = 0; index < target.length; index++) {
|
|
3828
|
+
const element = target[index];
|
|
3829
|
+
const elementType = typeof element;
|
|
3830
|
+
if ((elementType !== 'number' && elementType !== 'bigint') || element < minimum || element > maximum) return false;
|
|
3831
|
+
}
|
|
3832
|
+
return true;
|
|
3833
|
+
}
|
|
3834
|
+
|
|
3835
|
+
function LoopItemsIntegerBoundedSized_fast(instruction, instance, depth, template, evaluator) {
|
|
3836
|
+
const value = instruction[5];
|
|
3837
|
+
const minimum = value[0][0];
|
|
3838
|
+
const maximum = value[0][1];
|
|
3839
|
+
const minimumSize = value[1][0];
|
|
3840
|
+
const target = resolveInstance(instance, instruction[2]);
|
|
3841
|
+
if (!Array.isArray(target) || target.length < minimumSize) return false;
|
|
3842
|
+
for (let index = 0; index < target.length; index++) {
|
|
3843
|
+
const element = target[index];
|
|
3844
|
+
const elementType = typeof element;
|
|
3845
|
+
if ((elementType !== 'number' && elementType !== 'bigint') || element < minimum || element > maximum) return false;
|
|
3846
|
+
}
|
|
3847
|
+
return true;
|
|
3848
|
+
}
|
|
3849
|
+
|
|
3850
|
+
function AssertionTypeIntegerBounded_fast(instruction, instance, depth, template, evaluator) {
|
|
3851
|
+
const target = resolveInstance(instance, instruction[2]);
|
|
3852
|
+
const range = instruction[5];
|
|
3853
|
+
return (typeof target === 'bigint' || Number.isInteger(target)) && target >= range[0] && target <= range[1];
|
|
3854
|
+
}
|
|
3855
|
+
|
|
3856
|
+
function AssertionTypeIntegerBoundedStrict_fast(instruction, instance, depth, template, evaluator) {
|
|
3857
|
+
const target = resolveInstance(instance, instruction[2]);
|
|
3858
|
+
const range = instruction[5];
|
|
3859
|
+
return (typeof target === 'bigint' || Number.isInteger(target)) && target >= range[0] && target <= range[1];
|
|
3860
|
+
}
|
|
3861
|
+
|
|
3862
|
+
function AssertionTypeIntegerLowerBound_fast(instruction, instance, depth, template, evaluator) {
|
|
3863
|
+
const target = resolveInstance(instance, instruction[2]);
|
|
3864
|
+
const range = instruction[5];
|
|
3865
|
+
return (typeof target === 'bigint' || Number.isInteger(target)) && target >= range[0];
|
|
3866
|
+
}
|
|
3867
|
+
|
|
3868
|
+
function AssertionTypeIntegerLowerBoundStrict_fast(instruction, instance, depth, template, evaluator) {
|
|
3869
|
+
const target = resolveInstance(instance, instruction[2]);
|
|
3870
|
+
const range = instruction[5];
|
|
3871
|
+
return (typeof target === 'bigint' || Number.isInteger(target)) && target >= range[0];
|
|
3872
|
+
}
|
|
3873
|
+
|
|
3625
3874
|
const fastHandlers = handlers.slice();
|
|
3626
3875
|
fastHandlers[15] = AssertionTypeArrayBounded_fast;
|
|
3627
|
-
fastHandlers[
|
|
3628
|
-
fastHandlers[
|
|
3876
|
+
fastHandlers[86] = LoopItemsTypeStrictAny_fast;
|
|
3877
|
+
fastHandlers[42] = AssertionPropertyTypeStrict_fast;
|
|
3629
3878
|
fastHandlers[11] = AssertionTypeStrict_fast;
|
|
3630
3879
|
fastHandlers[4] = AssertionDefinesAllStrict_fast;
|
|
3631
3880
|
fastHandlers[26] = AssertionEqual_fast;
|
|
3632
|
-
fastHandlers[
|
|
3633
|
-
fastHandlers[
|
|
3634
|
-
fastHandlers[
|
|
3881
|
+
fastHandlers[64] = LoopPropertiesMatch_fast;
|
|
3882
|
+
fastHandlers[55] = LogicalOr_fast;
|
|
3883
|
+
fastHandlers[98] = ControlJump_fast;
|
|
3635
3884
|
fastHandlers[28] = AssertionEqualsAnyStringHash_fast;
|
|
3636
|
-
fastHandlers[
|
|
3885
|
+
fastHandlers[57] = LogicalXor_fast;
|
|
3637
3886
|
fastHandlers[2] = AssertionDefinesStrict_fast;
|
|
3638
|
-
fastHandlers[
|
|
3639
|
-
fastHandlers[
|
|
3887
|
+
fastHandlers[81] = LoopItems_fast;
|
|
3888
|
+
fastHandlers[65] = LoopPropertiesMatchClosed_fast;
|
|
3640
3889
|
fastHandlers[13] = AssertionTypeStringBounded_fast;
|
|
3641
|
-
fastHandlers[
|
|
3890
|
+
fastHandlers[56] = LogicalAnd_fast;
|
|
3642
3891
|
fastHandlers[8] = AssertionPropertyDependencies_fast;
|
|
3643
3892
|
fastHandlers[10] = AssertionTypeAny_fast;
|
|
3644
|
-
fastHandlers[
|
|
3645
|
-
fastHandlers[
|
|
3893
|
+
fastHandlers[58] = LogicalCondition_fast;
|
|
3894
|
+
fastHandlers[71] = LoopPropertiesExcept_fast;
|
|
3646
3895
|
fastHandlers[19] = AssertionRegex_fast;
|
|
3647
|
-
fastHandlers[
|
|
3896
|
+
fastHandlers[66] = LoopProperties_fast;
|
|
3648
3897
|
fastHandlers[1] = AssertionDefines_fast;
|
|
3649
|
-
fastHandlers[
|
|
3650
|
-
fastHandlers[
|
|
3898
|
+
fastHandlers[59] = LogicalWhenType_fast;
|
|
3899
|
+
fastHandlers[60] = LogicalWhenDefines_fast;
|
|
3651
3900
|
fastHandlers[0] = AssertionFail_fast;
|
|
3652
|
-
fastHandlers[
|
|
3653
|
-
fastHandlers[
|
|
3654
|
-
fastHandlers[
|
|
3655
|
-
fastHandlers[
|
|
3901
|
+
fastHandlers[91] = LoopContains_fast;
|
|
3902
|
+
fastHandlers[53] = LogicalNot_fast;
|
|
3903
|
+
fastHandlers[84] = LoopItemsType_fast;
|
|
3904
|
+
fastHandlers[85] = LoopItemsTypeStrict_fast;
|
|
3656
3905
|
fastHandlers[27] = AssertionEqualsAny_fast;
|
|
3657
3906
|
fastHandlers[3] = AssertionDefinesAll_fast;
|
|
3658
3907
|
fastHandlers[5] = AssertionDefinesExactly_fast;
|
|
@@ -3676,39 +3925,46 @@ fastHandlers[31] = AssertionGreater_fast;
|
|
|
3676
3925
|
fastHandlers[32] = AssertionLess_fast;
|
|
3677
3926
|
fastHandlers[33] = AssertionUnique_fast;
|
|
3678
3927
|
fastHandlers[34] = AssertionDivisible_fast;
|
|
3679
|
-
fastHandlers[35] =
|
|
3680
|
-
fastHandlers[36] =
|
|
3681
|
-
fastHandlers[37] =
|
|
3682
|
-
fastHandlers[
|
|
3683
|
-
fastHandlers[
|
|
3684
|
-
fastHandlers[
|
|
3685
|
-
fastHandlers[
|
|
3686
|
-
fastHandlers[43] =
|
|
3687
|
-
fastHandlers[44] =
|
|
3688
|
-
fastHandlers[45] =
|
|
3689
|
-
fastHandlers[46] =
|
|
3690
|
-
fastHandlers[47] =
|
|
3691
|
-
fastHandlers[
|
|
3692
|
-
fastHandlers[
|
|
3693
|
-
fastHandlers[
|
|
3694
|
-
fastHandlers[
|
|
3695
|
-
fastHandlers[
|
|
3696
|
-
fastHandlers[
|
|
3697
|
-
fastHandlers[
|
|
3698
|
-
fastHandlers[
|
|
3699
|
-
fastHandlers[
|
|
3700
|
-
fastHandlers[
|
|
3701
|
-
fastHandlers[
|
|
3702
|
-
fastHandlers[
|
|
3703
|
-
fastHandlers[
|
|
3704
|
-
fastHandlers[72] =
|
|
3705
|
-
fastHandlers[73] =
|
|
3706
|
-
fastHandlers[74] =
|
|
3707
|
-
fastHandlers[75] =
|
|
3708
|
-
fastHandlers[
|
|
3709
|
-
fastHandlers[
|
|
3710
|
-
fastHandlers[
|
|
3711
|
-
fastHandlers[
|
|
3712
|
-
fastHandlers[
|
|
3928
|
+
fastHandlers[35] = AssertionTypeIntegerBounded_fast;
|
|
3929
|
+
fastHandlers[36] = AssertionTypeIntegerBoundedStrict_fast;
|
|
3930
|
+
fastHandlers[37] = AssertionTypeIntegerLowerBound_fast;
|
|
3931
|
+
fastHandlers[38] = AssertionTypeIntegerLowerBoundStrict_fast;
|
|
3932
|
+
fastHandlers[39] = AssertionStringType_fast;
|
|
3933
|
+
fastHandlers[40] = AssertionPropertyType_fast;
|
|
3934
|
+
fastHandlers[41] = AssertionPropertyTypeEvaluate_fast;
|
|
3935
|
+
fastHandlers[43] = AssertionPropertyTypeStrictEvaluate_fast;
|
|
3936
|
+
fastHandlers[44] = AssertionPropertyTypeStrictAny_fast;
|
|
3937
|
+
fastHandlers[45] = AssertionPropertyTypeStrictAnyEvaluate_fast;
|
|
3938
|
+
fastHandlers[46] = AssertionArrayPrefix_fast;
|
|
3939
|
+
fastHandlers[47] = AssertionArrayPrefixEvaluate_fast;
|
|
3940
|
+
fastHandlers[48] = AssertionObjectPropertiesSimple_fast;
|
|
3941
|
+
fastHandlers[49] = AnnotationEmit_fast;
|
|
3942
|
+
fastHandlers[50] = AnnotationToParent_fast;
|
|
3943
|
+
fastHandlers[51] = AnnotationBasenameToParent_fast;
|
|
3944
|
+
fastHandlers[52] = Evaluate_fast;
|
|
3945
|
+
fastHandlers[54] = LogicalNotEvaluate_fast;
|
|
3946
|
+
fastHandlers[61] = LogicalWhenArraySizeGreater_fast;
|
|
3947
|
+
fastHandlers[62] = LoopPropertiesUnevaluated_fast;
|
|
3948
|
+
fastHandlers[63] = LoopPropertiesUnevaluatedExcept_fast;
|
|
3949
|
+
fastHandlers[67] = LoopPropertiesEvaluate_fast;
|
|
3950
|
+
fastHandlers[68] = LoopPropertiesRegex_fast;
|
|
3951
|
+
fastHandlers[69] = LoopPropertiesRegexClosed_fast;
|
|
3952
|
+
fastHandlers[70] = LoopPropertiesStartsWith_fast;
|
|
3953
|
+
fastHandlers[72] = LoopPropertiesType_fast;
|
|
3954
|
+
fastHandlers[73] = LoopPropertiesTypeEvaluate_fast;
|
|
3955
|
+
fastHandlers[74] = LoopPropertiesExactlyTypeStrict_fast;
|
|
3956
|
+
fastHandlers[75] = LoopPropertiesExactlyTypeStrictHash_fast;
|
|
3957
|
+
fastHandlers[76] = LoopPropertiesTypeStrict_fast;
|
|
3958
|
+
fastHandlers[77] = LoopPropertiesTypeStrictEvaluate_fast;
|
|
3959
|
+
fastHandlers[78] = LoopPropertiesTypeStrictAny_fast;
|
|
3960
|
+
fastHandlers[79] = LoopPropertiesTypeStrictAnyEvaluate_fast;
|
|
3961
|
+
fastHandlers[80] = LoopKeys_fast;
|
|
3962
|
+
fastHandlers[82] = LoopItemsFrom_fast;
|
|
3963
|
+
fastHandlers[83] = LoopItemsUnevaluated_fast;
|
|
3964
|
+
fastHandlers[87] = LoopItemsPropertiesExactlyTypeStrictHash_fast;
|
|
3965
|
+
fastHandlers[88] = LoopItemsPropertiesExactlyTypeStrictHash_fast;
|
|
3966
|
+
fastHandlers[89] = LoopItemsIntegerBounded_fast;
|
|
3967
|
+
fastHandlers[90] = LoopItemsIntegerBoundedSized_fast;
|
|
3968
|
+
fastHandlers[97] = ControlDynamicAnchorJump_fast;
|
|
3713
3969
|
|
|
3714
3970
|
export { Blaze };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sourcemeta/blaze",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "15.0.0",
|
|
4
4
|
"description": "A pure JavaScript port of the evaluator from Blaze, a high-performance C++ JSON Schema validator. Zero dependencies. Supports Draft 4, Draft 6, Draft 7, 2019-09, and 2020-12 with schema-specific code generation for near-native speed",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.mjs",
|