@sourcemeta/blaze 16.1.0 → 16.2.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.
- package/describe.mjs +24 -7
- package/index.mjs +62 -23
- package/package.json +1 -1
package/describe.mjs
CHANGED
|
@@ -135,6 +135,12 @@ function resolveTarget(instance, instanceLocation) {
|
|
|
135
135
|
return current;
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
+
function instanceParent(instance, instanceLocation) {
|
|
139
|
+
if (instanceLocation === '') return undefined;
|
|
140
|
+
const lastSlash = instanceLocation.lastIndexOf('/');
|
|
141
|
+
return resolveTarget(instance, instanceLocation.slice(0, lastSlash));
|
|
142
|
+
}
|
|
143
|
+
|
|
138
144
|
function extractKeyword(evaluatePath) {
|
|
139
145
|
if (evaluatePath === '') return '';
|
|
140
146
|
const lastSlash = evaluatePath.lastIndexOf('/');
|
|
@@ -430,13 +436,20 @@ export function describe(valid, instruction, evaluatePath,
|
|
|
430
436
|
if (keyword === 'contains') {
|
|
431
437
|
return 'The constraints declared for this keyword were not satisfiable';
|
|
432
438
|
}
|
|
433
|
-
|
|
434
|
-
|
|
439
|
+
// A `false` subschema declares no keyword of its own, so a property named
|
|
440
|
+
// after one of these must not be described as if it were that keyword.
|
|
441
|
+
// The instance location agrees only when it sits under an object for the
|
|
442
|
+
// property cases, or under an array for the item case
|
|
443
|
+
const parent = instanceParent(instance, instanceLocation);
|
|
444
|
+
if ((keyword === 'additionalProperties' ||
|
|
445
|
+
keyword === 'unevaluatedProperties') &&
|
|
446
|
+
parent !== undefined && parent !== null && typeof parent === 'object' &&
|
|
447
|
+
!Array.isArray(parent)) {
|
|
435
448
|
const property = lastInstanceToken(instanceLocation);
|
|
436
449
|
return 'The object value was not expected to define the property ' +
|
|
437
450
|
escapeString(property);
|
|
438
451
|
}
|
|
439
|
-
if (keyword === 'unevaluatedItems') {
|
|
452
|
+
if (keyword === 'unevaluatedItems' && Array.isArray(parent)) {
|
|
440
453
|
const tokenValue = lastInstanceToken(instanceLocation);
|
|
441
454
|
return 'The array value was not expected to define the item at index ' +
|
|
442
455
|
tokenValue;
|
|
@@ -560,7 +573,11 @@ export function describe(valid, instruction, evaluatePath,
|
|
|
560
573
|
'positional subschemas';
|
|
561
574
|
}
|
|
562
575
|
|
|
563
|
-
|
|
576
|
+
// Annotation values come from the schema as written, so they need not have
|
|
577
|
+
// the type their keyword expects. When they do not, the generic fallthrough
|
|
578
|
+
// below describes them instead
|
|
579
|
+
if ((keyword === 'title' || keyword === 'description') &&
|
|
580
|
+
typeof annotation === 'string') {
|
|
564
581
|
let message = 'The ' + keyword + ' of the';
|
|
565
582
|
if (instanceLocation === '') {
|
|
566
583
|
message += ' instance';
|
|
@@ -621,7 +638,7 @@ export function describe(valid, instruction, evaluatePath,
|
|
|
621
638
|
return message;
|
|
622
639
|
}
|
|
623
640
|
|
|
624
|
-
if (keyword === 'examples') {
|
|
641
|
+
if (keyword === 'examples' && Array.isArray(annotation)) {
|
|
625
642
|
let message = '';
|
|
626
643
|
if (instanceLocation === '') {
|
|
627
644
|
message += 'Examples of the instance';
|
|
@@ -640,7 +657,7 @@ export function describe(valid, instruction, evaluatePath,
|
|
|
640
657
|
return message;
|
|
641
658
|
}
|
|
642
659
|
|
|
643
|
-
if (keyword === 'contentEncoding') {
|
|
660
|
+
if (keyword === 'contentEncoding' && typeof annotation === 'string') {
|
|
644
661
|
let message = 'The content encoding of the';
|
|
645
662
|
if (instanceLocation === '') {
|
|
646
663
|
message += ' instance';
|
|
@@ -651,7 +668,7 @@ export function describe(valid, instruction, evaluatePath,
|
|
|
651
668
|
return message;
|
|
652
669
|
}
|
|
653
670
|
|
|
654
|
-
if (keyword === 'contentMediaType') {
|
|
671
|
+
if (keyword === 'contentMediaType' && typeof annotation === 'string') {
|
|
655
672
|
let message = 'The content media type of the';
|
|
656
673
|
if (instanceLocation === '') {
|
|
657
674
|
message += ' instance';
|
package/index.mjs
CHANGED
|
@@ -647,6 +647,14 @@ class Blaze {
|
|
|
647
647
|
if (match) entry.skip = true;
|
|
648
648
|
}
|
|
649
649
|
}
|
|
650
|
+
|
|
651
|
+
checkpoint() {
|
|
652
|
+
return this.evaluated.length;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
rewind(checkpoint) {
|
|
656
|
+
this.evaluated.length = checkpoint;
|
|
657
|
+
}
|
|
650
658
|
}
|
|
651
659
|
|
|
652
660
|
function evaluateInstructionFast(instruction, instance, depth, template, evaluator) {
|
|
@@ -1646,16 +1654,21 @@ function LogicalOr(instruction, instance, depth, template, evaluator) {
|
|
|
1646
1654
|
let result = false;
|
|
1647
1655
|
if (exhaustive) {
|
|
1648
1656
|
for (let index = 0; index < children.length; index++) {
|
|
1657
|
+
const checkpoint = evaluator.trackMode ? evaluator.checkpoint() : 0;
|
|
1649
1658
|
if (evaluateInstruction(children[index], target, depth + 1, template, evaluator)) {
|
|
1650
1659
|
result = true;
|
|
1660
|
+
} else if (evaluator.trackMode) {
|
|
1661
|
+
evaluator.rewind(checkpoint);
|
|
1651
1662
|
}
|
|
1652
1663
|
}
|
|
1653
1664
|
} else {
|
|
1654
1665
|
for (let index = 0; index < children.length; index++) {
|
|
1666
|
+
const checkpoint = evaluator.trackMode ? evaluator.checkpoint() : 0;
|
|
1655
1667
|
if (evaluateInstruction(children[index], target, depth + 1, template, evaluator)) {
|
|
1656
1668
|
result = true;
|
|
1657
1669
|
break;
|
|
1658
1670
|
}
|
|
1671
|
+
if (evaluator.trackMode) evaluator.rewind(checkpoint);
|
|
1659
1672
|
}
|
|
1660
1673
|
}
|
|
1661
1674
|
if (evaluator.callbackMode) evaluator.callbackPop(instruction, result);
|
|
@@ -1687,6 +1700,7 @@ function LogicalXor(instruction, instance, depth, template, evaluator) {
|
|
|
1687
1700
|
let hasMatched = false;
|
|
1688
1701
|
if (children) {
|
|
1689
1702
|
for (let index = 0; index < children.length; index++) {
|
|
1703
|
+
const checkpoint = evaluator.trackMode ? evaluator.checkpoint() : 0;
|
|
1690
1704
|
if (evaluateInstruction(children[index], target, depth + 1, template, evaluator)) {
|
|
1691
1705
|
if (hasMatched) {
|
|
1692
1706
|
result = false;
|
|
@@ -1694,6 +1708,8 @@ function LogicalXor(instruction, instance, depth, template, evaluator) {
|
|
|
1694
1708
|
} else {
|
|
1695
1709
|
hasMatched = true;
|
|
1696
1710
|
}
|
|
1711
|
+
} else if (evaluator.trackMode) {
|
|
1712
|
+
evaluator.rewind(checkpoint);
|
|
1697
1713
|
}
|
|
1698
1714
|
}
|
|
1699
1715
|
}
|
|
@@ -1710,24 +1726,29 @@ function LogicalCondition(instruction, instance, depth, template, evaluator) {
|
|
|
1710
1726
|
const children = instruction[6];
|
|
1711
1727
|
const childrenSize = children ? children.length : 0;
|
|
1712
1728
|
|
|
1713
|
-
let conditionEnd = childrenSize;
|
|
1714
|
-
if (thenStart > 0) conditionEnd = thenStart;
|
|
1715
|
-
else if (elseStart > 0) conditionEnd = elseStart;
|
|
1716
|
-
|
|
1717
1729
|
const target = resolveInstance(instance, instruction[2]);
|
|
1718
1730
|
|
|
1731
|
+
const checkpoint = evaluator.trackMode ? evaluator.checkpoint() : 0;
|
|
1719
1732
|
let conditionResult = true;
|
|
1720
|
-
for (let cursor = 0; cursor <
|
|
1733
|
+
for (let cursor = 0; cursor < thenStart; cursor++) {
|
|
1721
1734
|
if (!evaluateInstruction(children[cursor], target, depth + 1, template, evaluator)) {
|
|
1722
1735
|
conditionResult = false;
|
|
1723
1736
|
break;
|
|
1724
1737
|
}
|
|
1725
1738
|
}
|
|
1739
|
+
if (!conditionResult && evaluator.trackMode) evaluator.rewind(checkpoint);
|
|
1726
1740
|
|
|
1727
|
-
|
|
1728
|
-
|
|
1741
|
+
let consequenceStart;
|
|
1742
|
+
let consequenceEnd;
|
|
1743
|
+
if (conditionResult) {
|
|
1744
|
+
consequenceStart = thenStart;
|
|
1745
|
+
consequenceEnd = elseStart > 0 ? elseStart : childrenSize;
|
|
1746
|
+
} else {
|
|
1747
|
+
consequenceStart = elseStart;
|
|
1748
|
+
consequenceEnd = elseStart > 0 ? childrenSize : elseStart;
|
|
1749
|
+
}
|
|
1729
1750
|
|
|
1730
|
-
if (consequenceStart
|
|
1751
|
+
if (consequenceStart < consequenceEnd) {
|
|
1731
1752
|
if (evaluator.trackMode || evaluator.callbackMode) {
|
|
1732
1753
|
evaluator.popPath(instruction[1].length);
|
|
1733
1754
|
}
|
|
@@ -2147,15 +2168,16 @@ function LoopPropertiesExactlyTypeStrict(instruction, instance, depth, template,
|
|
|
2147
2168
|
return false;
|
|
2148
2169
|
}
|
|
2149
2170
|
const value = instruction[5];
|
|
2171
|
+
const names = new Set(value[1]);
|
|
2150
2172
|
let count = 0;
|
|
2151
2173
|
for (const key in target) {
|
|
2152
2174
|
count++;
|
|
2153
|
-
if (effectiveTypeStrictReal(target[key]) !== value[0]) {
|
|
2175
|
+
if (effectiveTypeStrictReal(target[key]) !== value[0] || !names.has(key)) {
|
|
2154
2176
|
if (evaluator.callbackMode) evaluator.callbackPop(instruction, false);
|
|
2155
2177
|
return false;
|
|
2156
2178
|
}
|
|
2157
2179
|
}
|
|
2158
|
-
const __result = count ===
|
|
2180
|
+
const __result = count === names.size;
|
|
2159
2181
|
if (evaluator.callbackMode) evaluator.callbackPop(instruction, __result);
|
|
2160
2182
|
return __result;
|
|
2161
2183
|
};
|
|
@@ -2465,9 +2487,11 @@ function LoopItemsIntegerBoundedSized(instruction, instance, depth, template, ev
|
|
|
2465
2487
|
const minimum = value[0][0];
|
|
2466
2488
|
const maximum = value[0][1];
|
|
2467
2489
|
const minimumSize = value[1][0];
|
|
2490
|
+
const maximumSize = value[1][1];
|
|
2468
2491
|
const target = resolveInstance(instance, instruction[2]);
|
|
2469
2492
|
if (evaluator.callbackMode) evaluator.callbackPush(instruction);
|
|
2470
|
-
if (!Array.isArray(target) || target.length < minimumSize
|
|
2493
|
+
if (!Array.isArray(target) || target.length < minimumSize ||
|
|
2494
|
+
(maximumSize !== null && maximumSize !== undefined && target.length > maximumSize)) {
|
|
2471
2495
|
if (evaluator.callbackMode) evaluator.callbackPop(instruction, false);
|
|
2472
2496
|
return false;
|
|
2473
2497
|
}
|
|
@@ -2494,11 +2518,10 @@ function LoopContains(instruction, instance, depth, template, evaluator) {
|
|
|
2494
2518
|
const minimum = range[0];
|
|
2495
2519
|
const maximum = range[1];
|
|
2496
2520
|
const isExhaustive = range[2];
|
|
2497
|
-
if (minimum === 0 && target.length === 0) return true;
|
|
2498
2521
|
if (evaluator.callbackMode) evaluator.callbackPush(instruction);
|
|
2499
2522
|
|
|
2500
2523
|
const children = instruction[6];
|
|
2501
|
-
let result =
|
|
2524
|
+
let result = minimum === 0;
|
|
2502
2525
|
let matchCount = 0;
|
|
2503
2526
|
for (let index = 0; index < target.length; index++) {
|
|
2504
2527
|
if (evaluator.callbackMode) evaluator.pushInstanceToken(index);
|
|
@@ -2813,11 +2836,15 @@ function LogicalOr_fast(instruction, instance, depth, template, evaluator) {
|
|
|
2813
2836
|
let result = false;
|
|
2814
2837
|
if (exhaustive) {
|
|
2815
2838
|
for (let index = 0; index < children.length; index++) {
|
|
2839
|
+
const checkpoint = evaluator.trackMode ? evaluator.checkpoint() : 0;
|
|
2816
2840
|
if (evaluateInstruction(children[index], target, depth + 1, template, evaluator)) result = true;
|
|
2841
|
+
else if (evaluator.trackMode) evaluator.rewind(checkpoint);
|
|
2817
2842
|
}
|
|
2818
2843
|
} else {
|
|
2819
2844
|
for (let index = 0; index < children.length; index++) {
|
|
2845
|
+
const checkpoint = evaluator.trackMode ? evaluator.checkpoint() : 0;
|
|
2820
2846
|
if (evaluateInstruction(children[index], target, depth + 1, template, evaluator)) return true;
|
|
2847
|
+
if (evaluator.trackMode) evaluator.rewind(checkpoint);
|
|
2821
2848
|
}
|
|
2822
2849
|
}
|
|
2823
2850
|
return result;
|
|
@@ -2862,6 +2889,7 @@ function LogicalXor_fast(instruction, instance, depth, template, evaluator) {
|
|
|
2862
2889
|
let hasMatched = false;
|
|
2863
2890
|
if (children) {
|
|
2864
2891
|
for (let index = 0; index < children.length; index++) {
|
|
2892
|
+
const checkpoint = evaluator.trackMode ? evaluator.checkpoint() : 0;
|
|
2865
2893
|
if (evaluateInstruction(children[index], target, depth + 1, template, evaluator)) {
|
|
2866
2894
|
if (hasMatched) {
|
|
2867
2895
|
result = false;
|
|
@@ -2869,6 +2897,8 @@ function LogicalXor_fast(instruction, instance, depth, template, evaluator) {
|
|
|
2869
2897
|
} else {
|
|
2870
2898
|
hasMatched = true;
|
|
2871
2899
|
}
|
|
2900
|
+
} else if (evaluator.trackMode) {
|
|
2901
|
+
evaluator.rewind(checkpoint);
|
|
2872
2902
|
}
|
|
2873
2903
|
}
|
|
2874
2904
|
}
|
|
@@ -2965,21 +2995,27 @@ function LogicalCondition_fast(instruction, instance, depth, template, evaluator
|
|
|
2965
2995
|
const elseStart = value[1];
|
|
2966
2996
|
const children = instruction[6];
|
|
2967
2997
|
const childrenSize = children ? children.length : 0;
|
|
2968
|
-
let conditionEnd = childrenSize;
|
|
2969
|
-
if (thenStart > 0) conditionEnd = thenStart;
|
|
2970
|
-
else if (elseStart > 0) conditionEnd = elseStart;
|
|
2971
2998
|
const relInstance = instruction[2];
|
|
2972
2999
|
const target = relInstance.length === 0 ? instance : resolveInstance(instance, relInstance);
|
|
3000
|
+
const checkpoint = evaluator.trackMode ? evaluator.checkpoint() : 0;
|
|
2973
3001
|
let conditionResult = true;
|
|
2974
|
-
for (let cursor = 0; cursor <
|
|
3002
|
+
for (let cursor = 0; cursor < thenStart; cursor++) {
|
|
2975
3003
|
if (!evaluateInstruction(children[cursor], target, depth + 1, template, evaluator)) {
|
|
2976
3004
|
conditionResult = false;
|
|
2977
3005
|
break;
|
|
2978
3006
|
}
|
|
2979
3007
|
}
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
3008
|
+
if (!conditionResult && evaluator.trackMode) evaluator.rewind(checkpoint);
|
|
3009
|
+
let consequenceStart;
|
|
3010
|
+
let consequenceEnd;
|
|
3011
|
+
if (conditionResult) {
|
|
3012
|
+
consequenceStart = thenStart;
|
|
3013
|
+
consequenceEnd = elseStart > 0 ? elseStart : childrenSize;
|
|
3014
|
+
} else {
|
|
3015
|
+
consequenceStart = elseStart;
|
|
3016
|
+
consequenceEnd = elseStart > 0 ? childrenSize : elseStart;
|
|
3017
|
+
}
|
|
3018
|
+
if (consequenceStart < consequenceEnd) {
|
|
2983
3019
|
if (evaluator.trackMode) {
|
|
2984
3020
|
evaluator.popPath(instruction[1].length);
|
|
2985
3021
|
}
|
|
@@ -3700,12 +3736,13 @@ function LoopPropertiesExactlyTypeStrict_fast(instruction, instance, depth, temp
|
|
|
3700
3736
|
const target = resolveInstance(instance, instruction[2]);
|
|
3701
3737
|
if (!isObject(target)) return false;
|
|
3702
3738
|
const value = instruction[5];
|
|
3739
|
+
const names = new Set(value[1]);
|
|
3703
3740
|
let count = 0;
|
|
3704
3741
|
for (const key in target) {
|
|
3705
3742
|
count++;
|
|
3706
|
-
if (effectiveTypeStrictReal(target[key]) !== value[0]) return false;
|
|
3743
|
+
if (effectiveTypeStrictReal(target[key]) !== value[0] || !names.has(key)) return false;
|
|
3707
3744
|
}
|
|
3708
|
-
return count ===
|
|
3745
|
+
return count === names.size;
|
|
3709
3746
|
}
|
|
3710
3747
|
|
|
3711
3748
|
function LoopPropertiesExactlyTypeStrictHash_fast(instruction, instance, depth, template, evaluator) {
|
|
@@ -3881,8 +3918,10 @@ function LoopItemsIntegerBoundedSized_fast(instruction, instance, depth, templat
|
|
|
3881
3918
|
const minimum = value[0][0];
|
|
3882
3919
|
const maximum = value[0][1];
|
|
3883
3920
|
const minimumSize = value[1][0];
|
|
3921
|
+
const maximumSize = value[1][1];
|
|
3884
3922
|
const target = resolveInstance(instance, instruction[2]);
|
|
3885
|
-
if (!Array.isArray(target) || target.length < minimumSize
|
|
3923
|
+
if (!Array.isArray(target) || target.length < minimumSize ||
|
|
3924
|
+
(maximumSize !== null && maximumSize !== undefined && target.length > maximumSize)) return false;
|
|
3886
3925
|
for (let index = 0; index < target.length; index++) {
|
|
3887
3926
|
const element = target[index];
|
|
3888
3927
|
const elementType = typeof element;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sourcemeta/blaze",
|
|
3
|
-
"version": "16.1
|
|
3
|
+
"version": "16.2.1",
|
|
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",
|