Skip to content

Commit cb26a0b

Browse files
authored
Implement a new AssertionNotTypeStrictAny instruction (#780)
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
1 parent 61341bd commit cb26a0b

9 files changed

Lines changed: 547 additions & 338 deletions

File tree

ports/javascript/describe.mjs

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import {
44
ASSERTION_DEFINES_EXACTLY, ASSERTION_DEFINES_EXACTLY_STRICT,
55
ASSERTION_DEFINES_EXACTLY_STRICT_HASH3, ASSERTION_PROPERTY_DEPENDENCIES,
66
ASSERTION_TYPE, ASSERTION_TYPE_ANY, ASSERTION_TYPE_STRICT,
7-
ASSERTION_TYPE_STRICT_ANY, ASSERTION_TYPE_STRING_BOUNDED,
7+
ASSERTION_TYPE_STRICT_ANY, ASSERTION_NOT_TYPE_STRICT_ANY,
8+
ASSERTION_TYPE_STRING_BOUNDED,
89
ASSERTION_TYPE_STRING_UPPER, ASSERTION_TYPE_ARRAY_BOUNDED,
910
ASSERTION_TYPE_ARRAY_UPPER, ASSERTION_TYPE_OBJECT_BOUNDED,
1011
ASSERTION_TYPE_OBJECT_UPPER, ASSERTION_REGEX,
@@ -214,6 +215,14 @@ function describeTypeCheck(valid, currentType, expectedType) {
214215
return message;
215216
}
216217

218+
function describeNotTypeCheck(valid, currentType, expectedType) {
219+
let message = 'The value was expected to NOT be of type ' + typeName(expectedType);
220+
if (!valid) {
221+
message += ' but it was of type ' + typeName(currentType);
222+
}
223+
return message;
224+
}
225+
217226
function describeTypesCheck(valid, currentType, bitmask) {
218227
let types = normalizeTypes(bitmask);
219228
const hasReal = (bitmask & (1 << TYPE_REAL)) !== 0;
@@ -265,6 +274,57 @@ function describeTypesCheck(valid, currentType, bitmask) {
265274
return message;
266275
}
267276

277+
function describeNotTypesCheck(valid, currentType, bitmask) {
278+
let types = normalizeTypes(bitmask);
279+
const hasReal = (bitmask & (1 << TYPE_REAL)) !== 0;
280+
const hasInteger = (bitmask & (1 << TYPE_INTEGER)) !== 0;
281+
282+
let popcount = 0;
283+
for (let bit = 0; bit < 8; bit++) {
284+
if ((types & (1 << bit)) !== 0) popcount++;
285+
}
286+
287+
if (popcount === 1) {
288+
let typeIndex = 0;
289+
for (let bit = 0; bit < 8; bit++) {
290+
if ((types & (1 << bit)) !== 0) { typeIndex = bit; break; }
291+
}
292+
return describeNotTypeCheck(valid, currentType, typeIndex);
293+
}
294+
295+
let message = 'The value was expected to NOT be of type ';
296+
let first = true;
297+
let lastBit = 0;
298+
for (let bit = 0; bit < 8; bit++) {
299+
if ((types & (1 << bit)) !== 0) lastBit = bit;
300+
}
301+
for (let bit = 0; bit < 8; bit++) {
302+
if ((types & (1 << bit)) !== 0) {
303+
if (!first) message += ', ';
304+
if (bit === lastBit) message += 'or ';
305+
message += typeName(bit);
306+
first = false;
307+
}
308+
}
309+
310+
if (valid) {
311+
message += ' and it was of type ';
312+
} else {
313+
message += ' but it was of type ';
314+
}
315+
316+
if (!valid && currentType === TYPE_INTEGER && hasReal) {
317+
message += 'number';
318+
} else if ((!valid && currentType === TYPE_INTEGER && hasReal) ||
319+
currentType === TYPE_REAL) {
320+
message += 'number';
321+
} else {
322+
message += typeName(currentType);
323+
}
324+
325+
return message;
326+
}
327+
268328
function describeReference(target) {
269329
return 'The ' + typeName(jsonTypeOf(target)) +
270330
' value was expected to validate against the referenced schema';
@@ -916,6 +976,10 @@ export function describe(valid, instruction, evaluatePath,
916976
return describeTypesCheck(valid, targetType, value);
917977
}
918978

979+
if (opcode === ASSERTION_NOT_TYPE_STRICT_ANY) {
980+
return describeNotTypesCheck(valid, targetType, value);
981+
}
982+
919983
if (opcode === ASSERTION_TYPE_STRING_BOUNDED) {
920984
const minimum = value[0];
921985
const maximum = value[1];

ports/javascript/index.mjs

Lines changed: 250 additions & 231 deletions
Large diffs are not rendered by default.

ports/javascript/official.test.mjs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,15 +133,15 @@ describe('reviver', () => {
133133

134134
describe('version', () => {
135135
it('rejects a template with an unsupported version', () => {
136-
const template = [5, false, false, [[]], []];
136+
const template = [6, false, false, [[]], []];
137137
assert.throws(() => new Blaze(template), {
138-
message: 'Only version 4 of the compiled template is supported by this version of the evaluator'
138+
message: 'Only version 5 of the compiled template is supported by this version of the evaluator'
139139
});
140140
});
141141

142142
it('rejects a template that is not an array', () => {
143143
assert.throws(() => new Blaze({}), {
144-
message: 'Only version 4 of the compiled template is supported by this version of the evaluator'
144+
message: 'Only version 5 of the compiled template is supported by this version of the evaluator'
145145
});
146146
});
147147
});

ports/javascript/opcodes.mjs

Lines changed: 88 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -11,92 +11,93 @@ export const ASSERTION_TYPE = 9;
1111
export const ASSERTION_TYPE_ANY = 10;
1212
export const ASSERTION_TYPE_STRICT = 11;
1313
export const ASSERTION_TYPE_STRICT_ANY = 12;
14-
export const ASSERTION_TYPE_STRING_BOUNDED = 13;
15-
export const ASSERTION_TYPE_STRING_UPPER = 14;
16-
export const ASSERTION_TYPE_ARRAY_BOUNDED = 15;
17-
export const ASSERTION_TYPE_ARRAY_UPPER = 16;
18-
export const ASSERTION_TYPE_OBJECT_BOUNDED = 17;
19-
export const ASSERTION_TYPE_OBJECT_UPPER = 18;
20-
export const ASSERTION_REGEX = 19;
21-
export const ASSERTION_STRING_SIZE_LESS = 20;
22-
export const ASSERTION_STRING_SIZE_GREATER = 21;
23-
export const ASSERTION_ARRAY_SIZE_LESS = 22;
24-
export const ASSERTION_ARRAY_SIZE_GREATER = 23;
25-
export const ASSERTION_OBJECT_SIZE_LESS = 24;
26-
export const ASSERTION_OBJECT_SIZE_GREATER = 25;
27-
export const ASSERTION_EQUAL = 26;
28-
export const ASSERTION_EQUALS_ANY = 27;
29-
export const ASSERTION_EQUALS_ANY_STRING_HASH = 28;
30-
export const ASSERTION_GREATER_EQUAL = 29;
31-
export const ASSERTION_LESS_EQUAL = 30;
32-
export const ASSERTION_GREATER = 31;
33-
export const ASSERTION_LESS = 32;
34-
export const ASSERTION_UNIQUE = 33;
35-
export const ASSERTION_DIVISIBLE = 34;
36-
export const ASSERTION_TYPE_INTEGER_BOUNDED = 35;
37-
export const ASSERTION_TYPE_INTEGER_BOUNDED_STRICT = 36;
38-
export const ASSERTION_TYPE_INTEGER_LOWER_BOUND = 37;
39-
export const ASSERTION_TYPE_INTEGER_LOWER_BOUND_STRICT = 38;
40-
export const ASSERTION_STRING_TYPE = 39;
41-
export const ASSERTION_PROPERTY_TYPE = 40;
42-
export const ASSERTION_PROPERTY_TYPE_EVALUATE = 41;
43-
export const ASSERTION_PROPERTY_TYPE_STRICT = 42;
44-
export const ASSERTION_PROPERTY_TYPE_STRICT_EVALUATE = 43;
45-
export const ASSERTION_PROPERTY_TYPE_STRICT_ANY = 44;
46-
export const ASSERTION_PROPERTY_TYPE_STRICT_ANY_EVALUATE = 45;
47-
export const ASSERTION_ARRAY_PREFIX = 46;
48-
export const ASSERTION_ARRAY_PREFIX_EVALUATE = 47;
49-
export const ASSERTION_OBJECT_PROPERTIES_SIMPLE = 48;
50-
export const ANNOTATION_EMIT = 49;
51-
export const ANNOTATION_TO_PARENT = 50;
52-
export const ANNOTATION_BASENAME_TO_PARENT = 51;
53-
export const EVALUATE = 52;
54-
export const LOGICAL_NOT = 53;
55-
export const LOGICAL_NOT_EVALUATE = 54;
56-
export const LOGICAL_OR = 55;
57-
export const LOGICAL_AND = 56;
58-
export const LOGICAL_XOR = 57;
59-
export const LOGICAL_CONDITION = 58;
60-
export const LOGICAL_WHEN_TYPE = 59;
61-
export const LOGICAL_WHEN_DEFINES = 60;
62-
export const LOGICAL_WHEN_ARRAY_SIZE_GREATER = 61;
63-
export const LOOP_PROPERTIES_UNEVALUATED = 62;
64-
export const LOOP_PROPERTIES_UNEVALUATED_EXCEPT = 63;
65-
export const LOOP_PROPERTIES_MATCH = 64;
66-
export const LOOP_PROPERTIES_MATCH_CLOSED = 65;
67-
export const LOOP_PROPERTIES = 66;
68-
export const LOOP_PROPERTIES_EVALUATE = 67;
69-
export const LOOP_PROPERTIES_REGEX = 68;
70-
export const LOOP_PROPERTIES_REGEX_CLOSED = 69;
71-
export const LOOP_PROPERTIES_STARTS_WITH = 70;
72-
export const LOOP_PROPERTIES_EXCEPT = 71;
73-
export const LOOP_PROPERTIES_TYPE = 72;
74-
export const LOOP_PROPERTIES_TYPE_EVALUATE = 73;
75-
export const LOOP_PROPERTIES_EXACTLY_TYPE_STRICT = 74;
76-
export const LOOP_PROPERTIES_EXACTLY_TYPE_STRICT_HASH = 75;
77-
export const LOOP_PROPERTIES_TYPE_STRICT = 76;
78-
export const LOOP_PROPERTIES_TYPE_STRICT_EVALUATE = 77;
79-
export const LOOP_PROPERTIES_TYPE_STRICT_ANY = 78;
80-
export const LOOP_PROPERTIES_TYPE_STRICT_ANY_EVALUATE = 79;
81-
export const LOOP_KEYS = 80;
82-
export const LOOP_ITEMS = 81;
83-
export const LOOP_ITEMS_FROM = 82;
84-
export const LOOP_ITEMS_UNEVALUATED = 83;
85-
export const LOOP_ITEMS_TYPE = 84;
86-
export const LOOP_ITEMS_TYPE_STRICT = 85;
87-
export const LOOP_ITEMS_TYPE_STRICT_ANY = 86;
88-
export const LOOP_ITEMS_PROPERTIES_EXACTLY_TYPE_STRICT_HASH = 87;
89-
export const LOOP_ITEMS_PROPERTIES_EXACTLY_TYPE_STRICT_HASH3 = 88;
90-
export const LOOP_ITEMS_INTEGER_BOUNDED = 89;
91-
export const LOOP_ITEMS_INTEGER_BOUNDED_SIZED = 90;
92-
export const LOOP_CONTAINS = 91;
93-
export const CONTROL_GROUP = 92;
94-
export const CONTROL_GROUP_WHEN_DEFINES = 93;
95-
export const CONTROL_GROUP_WHEN_DEFINES_DIRECT = 94;
96-
export const CONTROL_GROUP_WHEN_TYPE = 95;
97-
export const CONTROL_EVALUATE = 96;
98-
export const CONTROL_DYNAMIC_ANCHOR_JUMP = 97;
99-
export const CONTROL_JUMP = 98;
14+
export const ASSERTION_NOT_TYPE_STRICT_ANY = 13;
15+
export const ASSERTION_TYPE_STRING_BOUNDED = 14;
16+
export const ASSERTION_TYPE_STRING_UPPER = 15;
17+
export const ASSERTION_TYPE_ARRAY_BOUNDED = 16;
18+
export const ASSERTION_TYPE_ARRAY_UPPER = 17;
19+
export const ASSERTION_TYPE_OBJECT_BOUNDED = 18;
20+
export const ASSERTION_TYPE_OBJECT_UPPER = 19;
21+
export const ASSERTION_REGEX = 20;
22+
export const ASSERTION_STRING_SIZE_LESS = 21;
23+
export const ASSERTION_STRING_SIZE_GREATER = 22;
24+
export const ASSERTION_ARRAY_SIZE_LESS = 23;
25+
export const ASSERTION_ARRAY_SIZE_GREATER = 24;
26+
export const ASSERTION_OBJECT_SIZE_LESS = 25;
27+
export const ASSERTION_OBJECT_SIZE_GREATER = 26;
28+
export const ASSERTION_EQUAL = 27;
29+
export const ASSERTION_EQUALS_ANY = 28;
30+
export const ASSERTION_EQUALS_ANY_STRING_HASH = 29;
31+
export const ASSERTION_GREATER_EQUAL = 30;
32+
export const ASSERTION_LESS_EQUAL = 31;
33+
export const ASSERTION_GREATER = 32;
34+
export const ASSERTION_LESS = 33;
35+
export const ASSERTION_UNIQUE = 34;
36+
export const ASSERTION_DIVISIBLE = 35;
37+
export const ASSERTION_TYPE_INTEGER_BOUNDED = 36;
38+
export const ASSERTION_TYPE_INTEGER_BOUNDED_STRICT = 37;
39+
export const ASSERTION_TYPE_INTEGER_LOWER_BOUND = 38;
40+
export const ASSERTION_TYPE_INTEGER_LOWER_BOUND_STRICT = 39;
41+
export const ASSERTION_STRING_TYPE = 40;
42+
export const ASSERTION_PROPERTY_TYPE = 41;
43+
export const ASSERTION_PROPERTY_TYPE_EVALUATE = 42;
44+
export const ASSERTION_PROPERTY_TYPE_STRICT = 43;
45+
export const ASSERTION_PROPERTY_TYPE_STRICT_EVALUATE = 44;
46+
export const ASSERTION_PROPERTY_TYPE_STRICT_ANY = 45;
47+
export const ASSERTION_PROPERTY_TYPE_STRICT_ANY_EVALUATE = 46;
48+
export const ASSERTION_ARRAY_PREFIX = 47;
49+
export const ASSERTION_ARRAY_PREFIX_EVALUATE = 48;
50+
export const ASSERTION_OBJECT_PROPERTIES_SIMPLE = 49;
51+
export const ANNOTATION_EMIT = 50;
52+
export const ANNOTATION_TO_PARENT = 51;
53+
export const ANNOTATION_BASENAME_TO_PARENT = 52;
54+
export const EVALUATE = 53;
55+
export const LOGICAL_NOT = 54;
56+
export const LOGICAL_NOT_EVALUATE = 55;
57+
export const LOGICAL_OR = 56;
58+
export const LOGICAL_AND = 57;
59+
export const LOGICAL_XOR = 58;
60+
export const LOGICAL_CONDITION = 59;
61+
export const LOGICAL_WHEN_TYPE = 60;
62+
export const LOGICAL_WHEN_DEFINES = 61;
63+
export const LOGICAL_WHEN_ARRAY_SIZE_GREATER = 62;
64+
export const LOOP_PROPERTIES_UNEVALUATED = 63;
65+
export const LOOP_PROPERTIES_UNEVALUATED_EXCEPT = 64;
66+
export const LOOP_PROPERTIES_MATCH = 65;
67+
export const LOOP_PROPERTIES_MATCH_CLOSED = 66;
68+
export const LOOP_PROPERTIES = 67;
69+
export const LOOP_PROPERTIES_EVALUATE = 68;
70+
export const LOOP_PROPERTIES_REGEX = 69;
71+
export const LOOP_PROPERTIES_REGEX_CLOSED = 70;
72+
export const LOOP_PROPERTIES_STARTS_WITH = 71;
73+
export const LOOP_PROPERTIES_EXCEPT = 72;
74+
export const LOOP_PROPERTIES_TYPE = 73;
75+
export const LOOP_PROPERTIES_TYPE_EVALUATE = 74;
76+
export const LOOP_PROPERTIES_EXACTLY_TYPE_STRICT = 75;
77+
export const LOOP_PROPERTIES_EXACTLY_TYPE_STRICT_HASH = 76;
78+
export const LOOP_PROPERTIES_TYPE_STRICT = 77;
79+
export const LOOP_PROPERTIES_TYPE_STRICT_EVALUATE = 78;
80+
export const LOOP_PROPERTIES_TYPE_STRICT_ANY = 79;
81+
export const LOOP_PROPERTIES_TYPE_STRICT_ANY_EVALUATE = 80;
82+
export const LOOP_KEYS = 81;
83+
export const LOOP_ITEMS = 82;
84+
export const LOOP_ITEMS_FROM = 83;
85+
export const LOOP_ITEMS_UNEVALUATED = 84;
86+
export const LOOP_ITEMS_TYPE = 85;
87+
export const LOOP_ITEMS_TYPE_STRICT = 86;
88+
export const LOOP_ITEMS_TYPE_STRICT_ANY = 87;
89+
export const LOOP_ITEMS_PROPERTIES_EXACTLY_TYPE_STRICT_HASH = 88;
90+
export const LOOP_ITEMS_PROPERTIES_EXACTLY_TYPE_STRICT_HASH3 = 89;
91+
export const LOOP_ITEMS_INTEGER_BOUNDED = 90;
92+
export const LOOP_ITEMS_INTEGER_BOUNDED_SIZED = 91;
93+
export const LOOP_CONTAINS = 92;
94+
export const CONTROL_GROUP = 93;
95+
export const CONTROL_GROUP_WHEN_DEFINES = 94;
96+
export const CONTROL_GROUP_WHEN_DEFINES_DIRECT = 95;
97+
export const CONTROL_GROUP_WHEN_TYPE = 96;
98+
export const CONTROL_EVALUATE = 97;
99+
export const CONTROL_DYNAMIC_ANCHOR_JUMP = 98;
100+
export const CONTROL_JUMP = 99;
100101

101102
export const INSTRUCTION_NAMES = {
102103
"AssertionFail": ASSERTION_FAIL,
@@ -112,6 +113,7 @@ export const INSTRUCTION_NAMES = {
112113
"AssertionTypeAny": ASSERTION_TYPE_ANY,
113114
"AssertionTypeStrict": ASSERTION_TYPE_STRICT,
114115
"AssertionTypeStrictAny": ASSERTION_TYPE_STRICT_ANY,
116+
"AssertionNotTypeStrictAny": ASSERTION_NOT_TYPE_STRICT_ANY,
115117
"AssertionTypeStringBounded": ASSERTION_TYPE_STRING_BOUNDED,
116118
"AssertionTypeStringUpper": ASSERTION_TYPE_STRING_UPPER,
117119
"AssertionTypeArrayBounded": ASSERTION_TYPE_ARRAY_BOUNDED,

0 commit comments

Comments
 (0)