Skip to content

Commit 0b32810

Browse files
short-circuit evaluation of boolean schemas in "not", "then"/"else"
..which also removes a redundant error for then/else
1 parent cf3854d commit 0b32810

File tree

4 files changed

+16
-10
lines changed

4 files changed

+16
-10
lines changed

lib/JSON/Schema/Modern/Vocabulary/Applicator.pm

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ sub _eval_keyword_oneOf ($class, $data, $schema, $state) {
134134
sub _traverse_keyword_not { shift->traverse_subschema(@_) }
135135

136136
sub _eval_keyword_not ($class, $data, $schema, $state) {
137+
return !$schema->{not} || E($state, 'subschema is true') if is_type('boolean', $schema->{not});
138+
137139
return 1 if not $class->eval($data, $schema->{not},
138140
+{ %$state, schema_path => $state->{schema_path}.'/not',
139141
short_circuit_suggested => 1, # errors do not propagate upward from this subschema
@@ -158,6 +160,10 @@ sub _eval_keyword_if ($class, $data, $schema, $state) {
158160
? 'then' : 'else';
159161

160162
return 1 if not exists $schema->{$keyword};
163+
164+
return $schema->{$keyword} || E({ %$state, keyword => $keyword }, 'subschema is false')
165+
if is_type('boolean', $schema->{$keyword});
166+
161167
return 1 if $class->eval($data, $schema->{$keyword},
162168
+{ %$state, schema_path => $state->{schema_path}.'/'.$keyword });
163169
return E({ %$state, keyword => $keyword }, 'subschema is not valid');

t/errors.t

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ subtest 'anyOf keeps all errors for false paths when invalid, discards errors fo
180180
{
181181
instanceLocation => '',
182182
keywordLocation => '/not',
183-
error => 'subschema is valid',
183+
error => 'subschema is true',
184184
},
185185
],
186186
},
@@ -376,7 +376,7 @@ subtest 'applicators with non-boolean subschemas, discarding intermediary errors
376376
{
377377
instanceLocation => '',
378378
keywordLocation => '/not',
379-
error => 'subschema is valid',
379+
error => 'subschema is true',
380380
},
381381
# these errors are discarded because /contains passes on instance /1
382382
#{
@@ -402,7 +402,7 @@ subtest 'applicators with non-boolean subschemas, discarding intermediary errors
402402
{
403403
instanceLocation => '',
404404
keywordLocation => '/not',
405-
error => 'subschema is valid',
405+
error => 'subschema is true',
406406
},
407407
],
408408
},
@@ -695,7 +695,7 @@ subtest 'errors after crossing multiple $refs using $id and $anchor' => sub {
695695
instanceLocation => '',
696696
keywordLocation => '/$ref/$ref/$ref/not',
697697
absoluteKeywordLocation => 'base.json#/$defs/mynot/not',
698-
error => 'subschema is valid',
698+
error => 'subschema is true',
699699
},
700700
{
701701
instanceLocation => '',
@@ -757,7 +757,7 @@ subtest 'errors after crossing multiple $refs using $id and $anchor' => sub {
757757
instanceLocation => '',
758758
keywordLocation => '/$ref/not',
759759
absoluteKeywordLocation => 'http://localhost:1234/a/b.json#/$defs/bar/$defs/baz/not',
760-
error => 'subschema is valid',
760+
error => 'subschema is true',
761761
},
762762
],
763763
},
@@ -1385,7 +1385,7 @@ subtest 'effective_base_uri and overriding starting locations' => sub {
13851385
instanceLocation => '',
13861386
keywordLocation => '/not',
13871387
absoluteKeywordLocation => 'https://example.com/foo#/not',
1388-
error => 'subschema is valid',
1388+
error => 'subschema is true',
13891389
},
13901390
],
13911391
},
@@ -1423,7 +1423,7 @@ subtest 'effective_base_uri and overriding starting locations' => sub {
14231423
instanceLocation => '/html/body/div/div/h1/div/p/0',
14241424
keywordLocation => '/some/other/document/$ref/items/$ref/not',
14251425
absoluteKeywordLocation => 'https://example.com/api#/$defs/beta/not',
1426-
error => 'subschema is valid',
1426+
error => 'subschema is true',
14271427
},
14281428
{
14291429
instanceLocation => '/html/body/div/div/h1/div/p',

t/find-identifiers.t

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ subtest 'anchors' => sub {
128128
instanceLocation => '',
129129
keywordLocation => '/allOf/1/$ref/not',
130130
absoluteKeywordLocation => 'http://localhost:4242#/$defs/bar/not',
131-
error => 'subschema is valid',
131+
error => 'subschema is true',
132132
},
133133
{
134134
instanceLocation => '',

t/output_format.t

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ cmp_result(
108108
{
109109
instanceLocation => '',
110110
keywordLocation => '/not',
111-
error => 'subschema is valid',
111+
error => 'subschema is true',
112112
},
113113
{
114114
instanceLocation => '',
@@ -252,7 +252,7 @@ cmp_result(
252252
{
253253
instanceLocation => '',
254254
keywordLocation => '/not',
255-
error => 'subschema is valid',
255+
error => 'subschema is true',
256256
},
257257
{
258258
instanceLocation => '',

0 commit comments

Comments
 (0)