Filename | /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern/Vocabulary/Unevaluated.pm |
Statements | Executed 129100 statements in 146ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
3742 | 1 | 1 | 103ms | 353ms | _eval_keyword_unevaluatedProperties | JSON::Schema::Modern::Vocabulary::Unevaluated::
3742 | 1 | 1 | 2.54ms | 2.54ms | CORE:sort (opcode) | JSON::Schema::Modern::Vocabulary::Unevaluated::
154 | 1 | 1 | 978µs | 5.36ms | _traverse_keyword_unevaluatedProperties | JSON::Schema::Modern::Vocabulary::Unevaluated::
1 | 1 | 1 | 30µs | 33µs | BEGIN@1.309 | JSON::Schema::Modern::Vocabulary::Applicator::
1 | 1 | 1 | 19µs | 19µs | BEGIN@9 | JSON::Schema::Modern::Vocabulary::Unevaluated::
1 | 1 | 1 | 18µs | 63µs | BEGIN@17 | JSON::Schema::Modern::Vocabulary::Unevaluated::
1 | 1 | 1 | 16µs | 43µs | BEGIN@16 | JSON::Schema::Modern::Vocabulary::Unevaluated::
1 | 1 | 1 | 12µs | 662µs | BEGIN@11 | JSON::Schema::Modern::Vocabulary::Unevaluated::
1 | 1 | 1 | 12µs | 37µs | BEGIN@13 | JSON::Schema::Modern::Vocabulary::Unevaluated::
2 | 2 | 1 | 11µs | 15µs | keywords | JSON::Schema::Modern::Vocabulary::Unevaluated::
1 | 1 | 1 | 10µs | 24µs | BEGIN@14 | JSON::Schema::Modern::Vocabulary::Unevaluated::
1 | 1 | 1 | 10µs | 25µs | BEGIN@15 | JSON::Schema::Modern::Vocabulary::Unevaluated::
1 | 1 | 1 | 9µs | 344µs | BEGIN@10 | JSON::Schema::Modern::Vocabulary::Unevaluated::
1 | 1 | 1 | 7µs | 40µs | BEGIN@2.310 | JSON::Schema::Modern::Vocabulary::Applicator::
1 | 1 | 1 | 7µs | 103µs | BEGIN@12 | JSON::Schema::Modern::Vocabulary::Unevaluated::
1 | 1 | 1 | 6µs | 32µs | BEGIN@18 | JSON::Schema::Modern::Vocabulary::Unevaluated::
1 | 1 | 1 | 6µs | 196µs | BEGIN@19 | JSON::Schema::Modern::Vocabulary::Unevaluated::
2 | 1 | 1 | 4µs | 4µs | CORE:match (opcode) | JSON::Schema::Modern::Vocabulary::Unevaluated::
1 | 1 | 1 | 2µs | 2µs | vocabulary | JSON::Schema::Modern::Vocabulary::Unevaluated::
2 | 1 | 1 | 1µs | 1µs | evaluation_order | JSON::Schema::Modern::Vocabulary::Unevaluated::
0 | 0 | 0 | 0s | 0s | __ANON__[:118] | JSON::Schema::Modern::Vocabulary::Unevaluated::
0 | 0 | 0 | 0s | 0s | __ANON__[:56] | JSON::Schema::Modern::Vocabulary::Unevaluated::
0 | 0 | 0 | 0s | 0s | __ANON__[:72] | JSON::Schema::Modern::Vocabulary::Unevaluated::
0 | 0 | 0 | 0s | 0s | _eval_keyword_unevaluatedItems | JSON::Schema::Modern::Vocabulary::Unevaluated::
0 | 0 | 0 | 0s | 0s | _traverse_keyword_unevaluatedItems | JSON::Schema::Modern::Vocabulary::Unevaluated::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | 2 | 33µs | 2 | 36µs | # spent 33µs (30+3) within JSON::Schema::Modern::Vocabulary::Applicator::BEGIN@1.309 which was called:
# once (30µs+3µs) by JSON::Schema::Modern::Vocabulary::Applicator::BEGIN@21 at line 1 # spent 33µs making 1 call to JSON::Schema::Modern::Vocabulary::Applicator::BEGIN@1.309
# spent 3µs making 1 call to strict::import |
2 | 2 | 339µs | 2 | 73µs | # spent 40µs (7+33) within JSON::Schema::Modern::Vocabulary::Applicator::BEGIN@2.310 which was called:
# once (7µs+33µs) by JSON::Schema::Modern::Vocabulary::Applicator::BEGIN@21 at line 2 # spent 40µs making 1 call to JSON::Schema::Modern::Vocabulary::Applicator::BEGIN@2.310
# spent 33µs making 1 call to warnings::import |
3 | package JSON::Schema::Modern::Vocabulary::Unevaluated; | ||||
4 | # vim: set ts=8 sts=2 sw=2 tw=100 et : | ||||
5 | # ABSTRACT: Implementation of the JSON Schema Unevaluated vocabulary | ||||
6 | |||||
7 | 1 | 0s | our $VERSION = '0.559'; | ||
8 | |||||
9 | 2 | 62µs | 1 | 19µs | # spent 19µs within JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@9 which was called:
# once (19µs+0s) by JSON::Schema::Modern::Vocabulary::Applicator::BEGIN@21 at line 9 # spent 19µs making 1 call to JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@9 |
10 | 2 | 35µs | 2 | 679µs | # spent 344µs (9+335) within JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@10 which was called:
# once (9µs+335µs) by JSON::Schema::Modern::Vocabulary::Applicator::BEGIN@21 at line 10 # spent 344µs making 1 call to JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@10
# spent 335µs making 1 call to Moo::import |
11 | 3 | 40µs | 3 | 1.31ms | # spent 662µs (12+650) within JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@11 which was called:
# once (12µs+650µs) by JSON::Schema::Modern::Vocabulary::Applicator::BEGIN@21 at line 11 # spent 662µs making 1 call to JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@11
# spent 630µs making 1 call to strictures::import
# spent 19µs making 1 call to strictures::VERSION |
12 | 2 | 38µs | 2 | 199µs | # spent 103µs (7+96) within JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@12 which was called:
# once (7µs+96µs) by JSON::Schema::Modern::Vocabulary::Applicator::BEGIN@21 at line 12 # spent 103µs making 1 call to JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@12
# spent 96µs making 1 call to experimental::import |
13 | 2 | 24µs | 2 | 40µs | # spent 37µs (12+25) within JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@13 which was called:
# once (12µs+25µs) by JSON::Schema::Modern::Vocabulary::Applicator::BEGIN@21 at line 13 # spent 37µs making 1 call to JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@13
# spent 3µs making 1 call to if::import |
14 | 2 | 19µs | 2 | 25µs | # spent 24µs (10+14) within JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@14 which was called:
# once (10µs+14µs) by JSON::Schema::Modern::Vocabulary::Applicator::BEGIN@21 at line 14 # spent 24µs making 1 call to JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@14
# spent 1µs making 1 call to if::unimport |
15 | 2 | 52µs | 2 | 25µs | # spent 25µs (10+15) within JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@15 which was called:
# once (10µs+15µs) by JSON::Schema::Modern::Vocabulary::Applicator::BEGIN@21 at line 15 # spent 25µs making 1 call to JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@15
# spent 0s making 1 call to if::unimport |
16 | 2 | 26µs | 2 | 46µs | # spent 43µs (16+27) within JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@16 which was called:
# once (16µs+27µs) by JSON::Schema::Modern::Vocabulary::Applicator::BEGIN@21 at line 16 # spent 43µs making 1 call to JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@16
# spent 3µs making 1 call to if::unimport |
17 | 3 | 39µs | 3 | 81µs | # spent 63µs (18+45) within JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@17 which was called:
# once (18µs+45µs) by JSON::Schema::Modern::Vocabulary::Applicator::BEGIN@21 at line 17 # spent 63µs making 1 call to JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@17
# spent 10µs making 1 call to List::Util::import
# spent 8µs making 1 call to UNIVERSAL::VERSION |
18 | 2 | 13µs | 2 | 58µs | # spent 32µs (6+26) within JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@18 which was called:
# once (6µs+26µs) by JSON::Schema::Modern::Vocabulary::Applicator::BEGIN@21 at line 18 # spent 32µs making 1 call to JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@18
# spent 26µs making 1 call to Exporter::import |
19 | 2 | 710µs | 2 | 386µs | # spent 196µs (6+190) within JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@19 which was called:
# once (6µs+190µs) by JSON::Schema::Modern::Vocabulary::Applicator::BEGIN@21 at line 19 # spent 196µs making 1 call to JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@19
# spent 190µs making 1 call to namespace::clean::import |
20 | |||||
21 | 1 | 3µs | 1 | 350µs | with 'JSON::Schema::Modern::Vocabulary'; # spent 350µs making 1 call to Moo::with |
22 | |||||
23 | # spent 2µs within JSON::Schema::Modern::Vocabulary::Unevaluated::vocabulary which was called:
# once (2µs+0s) by JSON::Schema::Modern::__ANON__[/Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern.pm:709] at line 705 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern.pm | ||||
24 | 1 | 2µs | 'https://json-schema.org/draft/2020-12/vocab/unevaluated' => 'draft2020-12'; | ||
25 | } | ||||
26 | |||||
27 | 2 | 7µs | # spent 1µs within JSON::Schema::Modern::Vocabulary::Unevaluated::evaluation_order which was called 2 times, avg 500ns/call:
# 2 times (1µs+0s) by JSON::Schema::Modern::Vocabulary::Core::CORE:sort at line 337 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern/Vocabulary/Core.pm, avg 500ns/call | ||
28 | |||||
29 | # This vocabulary should be evaluated after the Applicator vocabulary. | ||||
30 | 6 | 2µs | # spent 15µs (11+4) within JSON::Schema::Modern::Vocabulary::Unevaluated::keywords which was called 2 times, avg 7µs/call:
# once (7µs+1000ns) by JSON::Schema::Modern::_traverse_subschema at line 480 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern.pm
# once (4µs+3µs) by JSON::Schema::Modern::_eval_subschema at line 572 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern.pm | ||
31 | 2 | 9µs | 2 | 4µs | die 'Unevaluated not implemented in '.$spec_version if $spec_version =~ /^draft[467]$/; # spent 4µs making 2 calls to JSON::Schema::Modern::Vocabulary::Unevaluated::CORE:match, avg 2µs/call |
32 | 2 | 4µs | qw(unevaluatedItems unevaluatedProperties); | ||
33 | } | ||||
34 | |||||
35 | sub _traverse_keyword_unevaluatedItems ($self, $schema, $state) { | ||||
36 | $self->traverse_subschema($schema, $state); | ||||
37 | } | ||||
38 | |||||
39 | sub _eval_keyword_unevaluatedItems ($self, $data, $schema, $state) { | ||||
40 | abort($state, 'EXCEPTION: "unevaluatedItems" keyword present, but annotation collection is disabled') | ||||
41 | if not $state->{collect_annotations}; | ||||
42 | |||||
43 | abort($state, 'EXCEPTION: "unevaluatedItems" keyword present, but short_circuit is enabled: results unreliable') | ||||
44 | if $state->{short_circuit}; | ||||
45 | |||||
46 | return 1 if not is_type('array', $data); | ||||
47 | |||||
48 | my @annotations = local_annotations($state); | ||||
49 | |||||
50 | # a relevant keyword already produced a 'true' annotation at this location | ||||
51 | my @boolean_annotation_keywords = | ||||
52 | $state->{spec_version} eq 'draft2019-09' ? qw(items additionalItems unevaluatedItems) | ||||
53 | : qw(prefixItems items contains unevaluatedItems); | ||||
54 | my %bools; @bools{@boolean_annotation_keywords} = (1)x@boolean_annotation_keywords; | ||||
55 | return 1 | ||||
56 | if any { $bools{$_->{keyword}} && is_type('boolean', $_->{annotation}) && $_->{annotation} } | ||||
57 | @annotations; | ||||
58 | |||||
59 | # otherwise, evaluate at every instance item greater than the max of all 'prefixItems'/numeric | ||||
60 | # 'items' annotations that isn't in a 'contains' annotation | ||||
61 | my $max_index_annotation_keyword = $state->{spec_version} eq 'draft2019-09' ? 'items' : 'prefixItems'; | ||||
62 | my $last_index = max(-1, grep is_type('integer', $_), | ||||
63 | map +($_->{keyword} eq $max_index_annotation_keyword ? $_->{annotation} : ()), @annotations); | ||||
64 | |||||
65 | return 1 if $last_index == $data->$#*; | ||||
66 | |||||
67 | my @contains_annotation_indexes = $state->{spec_version} eq 'draft2019-09' ? () | ||||
68 | : map +($_->{keyword} eq 'contains' ? $_->{annotation}->@* : ()), @annotations; | ||||
69 | |||||
70 | my $valid = 1; | ||||
71 | foreach my $idx ($last_index+1 .. $data->$#*) { | ||||
72 | next if any { $idx == $_ } @contains_annotation_indexes; | ||||
73 | if (is_type('boolean', $schema->{unevaluatedItems})) { | ||||
74 | next if $schema->{unevaluatedItems}; | ||||
75 | $valid = E({ %$state, data_path => $state->{data_path}.'/'.$idx }, | ||||
76 | 'additional item not permitted') | ||||
77 | } | ||||
78 | else { | ||||
79 | if ($self->eval($data->[$idx], $schema->{unevaluatedItems}, | ||||
80 | +{ %$state, data_path => $state->{data_path}.'/'.$idx, | ||||
81 | schema_path => $state->{schema_path}.'/unevaluatedItems', | ||||
82 | collect_annotations => $state->{collect_annotations} & ~1 })) { | ||||
83 | next; | ||||
84 | } | ||||
85 | |||||
86 | $valid = 0; | ||||
87 | } | ||||
88 | last if $state->{short_circuit}; | ||||
89 | } | ||||
90 | |||||
91 | A($state, true); | ||||
92 | return E($state, 'subschema is not valid against all additional items') if not $valid; | ||||
93 | return 1; | ||||
94 | } | ||||
95 | |||||
96 | 616 | 105µs | # spent 5.36ms (978µs+4.38) within JSON::Schema::Modern::Vocabulary::Unevaluated::_traverse_keyword_unevaluatedProperties which was called 154 times, avg 35µs/call:
# 154 times (978µs+4.38ms) by JSON::Schema::Modern::_traverse_subschema at line 492 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern.pm, avg 35µs/call | ||
97 | 154 | 743µs | 154 | 3.15ms | $self->traverse_subschema($schema, $state); # spent 4.38ms making 154 calls to JSON::Schema::Modern::Vocabulary::traverse_subschema, avg 28µs/call, recursion: max depth 2, sum of overlapping time 1.23ms |
98 | } | ||||
99 | |||||
100 | 18710 | 3.37ms | # spent 353ms (103+250) within JSON::Schema::Modern::Vocabulary::Unevaluated::_eval_keyword_unevaluatedProperties which was called 3742 times, avg 94µs/call:
# 3742 times (103ms+250ms) by JSON::Schema::Modern::_eval_subschema at line 587 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern.pm, avg 94µs/call | ||
101 | abort($state, 'EXCEPTION: "unevaluatedProperties" keyword present, but annotation collection is disabled') | ||||
102 | 3742 | 1.69ms | if not $state->{collect_annotations}; | ||
103 | |||||
104 | abort($state, 'EXCEPTION: "unevaluatedProperties" keyword present, but short_circuit is enabled: results unreliable') | ||||
105 | 3742 | 1.46ms | if $state->{short_circuit}; | ||
106 | |||||
107 | 3742 | 4.19ms | 3742 | 6.18ms | return 1 if not is_type('object', $data); # spent 6.18ms making 3742 calls to JSON::Schema::Modern::Utilities::is_type, avg 2µs/call |
108 | |||||
109 | my @evaluated_properties = map { | ||||
110 | 12729 | 10.8ms | 3742 | 28.2ms | my $keyword = $_->{keyword}; # spent 28.2ms making 3742 calls to JSON::Schema::Modern::Utilities::local_annotations, avg 8µs/call |
111 | (grep $keyword eq $_, qw(properties additionalProperties patternProperties unevaluatedProperties)) | ||||
112 | 8987 | 9.07ms | ? $_->{annotation}->@* : (); | ||
113 | } local_annotations($state); | ||||
114 | |||||
115 | 3742 | 691µs | my $valid = 1; | ||
116 | 3742 | 671µs | my @properties; | ||
117 | 3742 | 26.8ms | 3742 | 2.54ms | foreach my $property (sort keys %$data) { # spent 2.54ms making 3742 calls to JSON::Schema::Modern::Vocabulary::Unevaluated::CORE:sort, avg 680ns/call |
118 | 54182 | 37.5ms | 7978 | 15.2ms | next if any { $_ eq $property } @evaluated_properties; # spent 15.2ms making 7978 calls to List::Util::any, avg 2µs/call |
119 | push @properties, $property; | ||||
120 | |||||
121 | if (is_type('boolean', $schema->{unevaluatedProperties})) { | ||||
122 | next if $schema->{unevaluatedProperties}; | ||||
123 | $valid = E({ %$state, data_path => jsonp($state->{data_path}, $property) }, | ||||
124 | 'additional property not permitted'); | ||||
125 | } | ||||
126 | else { | ||||
127 | if ($self->eval($data->{$property}, $schema->{unevaluatedProperties}, | ||||
128 | +{ %$state, data_path => jsonp($state->{data_path}, $property), | ||||
129 | schema_path => $state->{schema_path}.'/unevaluatedProperties', | ||||
130 | collect_annotations => $state->{collect_annotations} & ~1 })) { | ||||
131 | next; | ||||
132 | } | ||||
133 | |||||
134 | $valid = 0; | ||||
135 | } | ||||
136 | last if $state->{short_circuit}; | ||||
137 | } | ||||
138 | |||||
139 | 3742 | 3.38ms | 3742 | 198ms | A($state, \@properties); # spent 198ms making 3742 calls to JSON::Schema::Modern::Utilities::A, avg 53µs/call |
140 | 3742 | 834µs | return E($state, 'not all additional properties are valid') if not $valid; | ||
141 | 3742 | 43.5ms | return 1; | ||
142 | } | ||||
143 | |||||
144 | 1 | 10µs | 1; | ||
145 | 1 | 30µs | 1 | 455µs | __END__ # spent 455µs making 1 call to B::Hooks::EndOfScope::XS::__ANON__[B/Hooks/EndOfScope/XS.pm:26] |
# spent 4µs within JSON::Schema::Modern::Vocabulary::Unevaluated::CORE:match which was called 2 times, avg 2µs/call:
# 2 times (4µs+0s) by JSON::Schema::Modern::Vocabulary::Unevaluated::keywords at line 31, avg 2µs/call | |||||
# spent 2.54ms within JSON::Schema::Modern::Vocabulary::Unevaluated::CORE:sort which was called 3742 times, avg 680ns/call:
# 3742 times (2.54ms+0s) by JSON::Schema::Modern::Vocabulary::Unevaluated::_eval_keyword_unevaluatedProperties at line 117, avg 680ns/call |