| Filename | /Users/ether/.perlbrew/libs/36.0@std/lib/perl5/JSON/Schema/Modern/Vocabulary/Unevaluated.pm |
| Statements | Executed 607923 statements in 596ms |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 94075 | 2 | 1 | 264ms | 342ms | JSON::Schema::Modern::Vocabulary::Unevaluated::keywords |
| 3747 | 1 | 1 | 177ms | 1.99s | JSON::Schema::Modern::Vocabulary::Unevaluated::_eval_keyword_unevaluatedProperties |
| 94075 | 1 | 1 | 77.3ms | 77.3ms | JSON::Schema::Modern::Vocabulary::Unevaluated::CORE:match (opcode) |
| 3747 | 1 | 1 | 4.20ms | 4.20ms | JSON::Schema::Modern::Vocabulary::Unevaluated::CORE:sort (opcode) |
| 156 | 1 | 1 | 1.09ms | 5.62ms | JSON::Schema::Modern::Vocabulary::Unevaluated::_traverse_keyword_unevaluatedProperties |
| 1 | 1 | 1 | 25µs | 28µs | JSON::Schema::Modern::Vocabulary::Applicator::BEGIN@1.308 |
| 1 | 1 | 1 | 16µs | 48µs | JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@17 |
| 1 | 1 | 1 | 14µs | 570µs | JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@11 |
| 1 | 1 | 1 | 13µs | 34µs | JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@13 |
| 1 | 1 | 1 | 10µs | 18µs | JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@16 |
| 1 | 1 | 1 | 10µs | 10µs | JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@9 |
| 1 | 1 | 1 | 9µs | 23µs | JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@14 |
| 1 | 1 | 1 | 7µs | 35µs | JSON::Schema::Modern::Vocabulary::Applicator::BEGIN@2.309 |
| 1 | 1 | 1 | 7µs | 366µs | JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@19 |
| 1 | 1 | 1 | 6µs | 202µs | JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@10 |
| 1 | 1 | 1 | 6µs | 12µs | JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@15 |
| 1 | 1 | 1 | 5µs | 80µs | JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@12 |
| 1 | 1 | 1 | 3µs | 26µs | JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@18 |
| 2 | 1 | 1 | 2µs | 2µs | JSON::Schema::Modern::Vocabulary::Unevaluated::evaluation_order |
| 1 | 1 | 1 | 2µs | 2µs | JSON::Schema::Modern::Vocabulary::Unevaluated::vocabulary |
| 0 | 0 | 0 | 0s | 0s | JSON::Schema::Modern::Vocabulary::Unevaluated::__ANON__[:134] |
| 0 | 0 | 0 | 0s | 0s | JSON::Schema::Modern::Vocabulary::Unevaluated::__ANON__[:61] |
| 0 | 0 | 0 | 0s | 0s | JSON::Schema::Modern::Vocabulary::Unevaluated::__ANON__[:79] |
| 0 | 0 | 0 | 0s | 0s | JSON::Schema::Modern::Vocabulary::Unevaluated::_eval_keyword_unevaluatedItems |
| 0 | 0 | 0 | 0s | 0s | JSON::Schema::Modern::Vocabulary::Unevaluated::_traverse_keyword_unevaluatedItems |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | 2 | 27µs | 2 | 31µs | # spent 28µs (25+3) within JSON::Schema::Modern::Vocabulary::Applicator::BEGIN@1.308 which was called:
# once (25µs+3µs) by JSON::Schema::Modern::Vocabulary::Applicator::BEGIN@21 at line 1 # spent 28µs making 1 call to JSON::Schema::Modern::Vocabulary::Applicator::BEGIN@1.308
# spent 3µs making 1 call to strict::import |
| 2 | 2 | 36µs | 2 | 63µs | # spent 35µs (7+28) within JSON::Schema::Modern::Vocabulary::Applicator::BEGIN@2.309 which was called:
# once (7µs+28µs) by JSON::Schema::Modern::Vocabulary::Applicator::BEGIN@21 at line 2 # spent 35µs making 1 call to JSON::Schema::Modern::Vocabulary::Applicator::BEGIN@2.309
# spent 28µ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.552'; | ||
| 8 | |||||
| 9 | 2 | 38µs | 1 | 10µs | # spent 10µs within JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@9 which was called:
# once (10µs+0s) by JSON::Schema::Modern::Vocabulary::Applicator::BEGIN@21 at line 9 # spent 10µs making 1 call to JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@9 |
| 10 | 2 | 21µs | 2 | 398µs | # spent 202µs (6+196) within JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@10 which was called:
# once (6µs+196µs) by JSON::Schema::Modern::Vocabulary::Applicator::BEGIN@21 at line 10 # spent 202µs making 1 call to JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@10
# spent 196µs making 1 call to Moo::import |
| 11 | 3 | 31µs | 3 | 1.13ms | # spent 570µs (14+556) within JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@11 which was called:
# once (14µs+556µs) by JSON::Schema::Modern::Vocabulary::Applicator::BEGIN@21 at line 11 # spent 570µs making 1 call to JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@11
# spent 541µs making 1 call to strictures::import
# spent 15µs making 1 call to strictures::VERSION |
| 12 | 2 | 27µs | 2 | 155µs | # spent 80µs (5+75) within JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@12 which was called:
# once (5µs+75µs) by JSON::Schema::Modern::Vocabulary::Applicator::BEGIN@21 at line 12 # spent 80µs making 1 call to JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@12
# spent 75µs making 1 call to experimental::import |
| 13 | 2 | 26µs | 2 | 37µs | # spent 34µs (13+21) within JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@13 which was called:
# once (13µs+21µs) by JSON::Schema::Modern::Vocabulary::Applicator::BEGIN@21 at line 13 # spent 34µs making 1 call to JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@13
# spent 3µs making 1 call to if::import |
| 14 | 2 | 16µs | 2 | 23µs | # spent 23µs (9+14) within JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@14 which was called:
# once (9µs+14µs) by JSON::Schema::Modern::Vocabulary::Applicator::BEGIN@21 at line 14 # spent 23µs making 1 call to JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@14
# spent 0s making 1 call to if::unimport |
| 15 | 2 | 15µs | 2 | 12µs | # spent 12µs (6+6) within JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@15 which was called:
# once (6µs+6µs) by JSON::Schema::Modern::Vocabulary::Applicator::BEGIN@21 at line 15 # spent 12µs making 1 call to JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@15
# spent 0s making 1 call to if::unimport |
| 16 | 2 | 19µs | 2 | 19µs | # spent 18µs (10+8) within JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@16 which was called:
# once (10µs+8µs) by JSON::Schema::Modern::Vocabulary::Applicator::BEGIN@21 at line 16 # spent 18µs making 1 call to JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@16
# spent 1µs making 1 call to if::unimport |
| 17 | 3 | 31µs | 3 | 61µs | # spent 48µs (16+32) within JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@17 which was called:
# once (16µs+32µs) by JSON::Schema::Modern::Vocabulary::Applicator::BEGIN@21 at line 17 # spent 48µs making 1 call to JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@17
# spent 9µs making 1 call to List::Util::import
# spent 4µs making 1 call to UNIVERSAL::VERSION |
| 18 | 2 | 14µs | 2 | 49µs | # spent 26µs (3+23) within JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@18 which was called:
# once (3µs+23µs) by JSON::Schema::Modern::Vocabulary::Applicator::BEGIN@21 at line 18 # spent 26µs making 1 call to JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@18
# spent 23µs making 1 call to Exporter::import |
| 19 | 2 | 1.42ms | 2 | 725µs | # spent 366µs (7+359) within JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@19 which was called:
# once (7µs+359µs) by JSON::Schema::Modern::Vocabulary::Applicator::BEGIN@21 at line 19 # spent 366µs making 1 call to JSON::Schema::Modern::Vocabulary::Unevaluated::BEGIN@19
# spent 359µs making 1 call to namespace::clean::import |
| 20 | |||||
| 21 | 1 | 1µs | 1 | 511µs | with 'JSON::Schema::Modern::Vocabulary'; # spent 511µ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/.perlbrew/libs/36.0@std/lib/perl5/JSON/Schema/Modern.pm:670] at line 666 of JSON/Schema/Modern.pm | ||||
| 24 | 1 | 3µs | 'https://json-schema.org/draft/2020-12/vocab/unevaluated' => 'draft2020-12'; | ||
| 25 | } | ||||
| 26 | |||||
| 27 | 2 | 4µs | # spent 2µs within JSON::Schema::Modern::Vocabulary::Unevaluated::evaluation_order which was called 2 times, avg 1µs/call:
# 2 times (2µs+0s) by JSON::Schema::Modern::Vocabulary::Core::CORE:sort at line 322 of JSON/Schema/Modern/Vocabulary/Core.pm, avg 1µs/call | ||
| 28 | |||||
| 29 | # This vocabulary should be evaluated after the Applicator vocabulary. | ||||
| 30 | 282225 | 41.0ms | # spent 342ms (264+77.3) within JSON::Schema::Modern::Vocabulary::Unevaluated::keywords which was called 94075 times, avg 4µs/call:
# 91595 times (258ms+75.4ms) by JSON::Schema::Modern::_eval_subschema at line 535 of JSON/Schema/Modern.pm, avg 4µs/call
# 2480 times (6.68ms+1.91ms) by JSON::Schema::Modern::_traverse_subschema at line 447 of JSON/Schema/Modern.pm, avg 3µs/call | ||
| 31 | 94075 | 205ms | 94075 | 77.3ms | die 'Unevaluated not implemented in '.$spec_version if $spec_version =~ /^draft[467]$/; # spent 77.3ms making 94075 calls to JSON::Schema::Modern::Vocabulary::Unevaluated::CORE:match, avg 822ns/call |
| 32 | 94075 | 167ms | qw(unevaluatedItems unevaluatedProperties); | ||
| 33 | } | ||||
| 34 | |||||
| 35 | sub _traverse_keyword_unevaluatedItems ($self, $schema, $state) { | ||||
| 36 | my $valid = $self->traverse_subschema($schema, $state); | ||||
| 37 | |||||
| 38 | # remember that annotations need to be collected in order to evaluate this keyword | ||||
| 39 | $state->{configs}{collect_annotations} = 1; | ||||
| 40 | |||||
| 41 | return $valid; | ||||
| 42 | } | ||||
| 43 | |||||
| 44 | sub _eval_keyword_unevaluatedItems ($self, $data, $schema, $state) { | ||||
| 45 | abort($state, 'EXCEPTION: "unevaluatedItems" keyword present, but annotation collection is disabled') | ||||
| 46 | if not $state->{collect_annotations}; | ||||
| 47 | |||||
| 48 | abort($state, 'EXCEPTION: "unevaluatedItems" keyword present, but short_circuit is enabled: results unreliable') | ||||
| 49 | if $state->{short_circuit}; | ||||
| 50 | |||||
| 51 | return 1 if not is_type('array', $data); | ||||
| 52 | |||||
| 53 | my @annotations = local_annotations($state); | ||||
| 54 | |||||
| 55 | # a relevant keyword already produced a 'true' annotation at this location | ||||
| 56 | my @boolean_annotation_keywords = | ||||
| 57 | $state->{spec_version} eq 'draft2019-09' ? qw(items additionalItems unevaluatedItems) | ||||
| 58 | : qw(prefixItems items contains unevaluatedItems); | ||||
| 59 | my %bools; @bools{@boolean_annotation_keywords} = (1)x@boolean_annotation_keywords; | ||||
| 60 | return 1 | ||||
| 61 | if any { $bools{$_->keyword} && is_type('boolean', $_->annotation) && $_->annotation } | ||||
| 62 | @annotations; | ||||
| 63 | |||||
| 64 | # otherwise, evaluate at every instance item greater than the max of all 'prefixItems'/numeric | ||||
| 65 | # 'items' annotations that isn't in a 'contains' annotation | ||||
| 66 | my $max_index_annotation_keyword = $state->{spec_version} eq 'draft2019-09' ? 'items' : 'prefixItems'; | ||||
| 67 | my $last_index = max(-1, grep is_type('integer', $_), | ||||
| 68 | map +($_->keyword eq $max_index_annotation_keyword ? $_->annotation : ()), @annotations); | ||||
| 69 | |||||
| 70 | return 1 if $last_index == $data->$#*; | ||||
| 71 | |||||
| 72 | my @contains_annotation_indexes = $state->{spec_version} eq 'draft2019-09' ? () | ||||
| 73 | : map +($_->keyword eq 'contains' ? $_->annotation->@* : ()), @annotations; | ||||
| 74 | |||||
| 75 | my $valid = 1; | ||||
| 76 | my @orig_annotations = $state->{annotations}->@*; | ||||
| 77 | my @new_annotations; | ||||
| 78 | foreach my $idx ($last_index+1 .. $data->$#*) { | ||||
| 79 | next if any { $idx == $_ } @contains_annotation_indexes; | ||||
| 80 | if (is_type('boolean', $schema->{unevaluatedItems})) { | ||||
| 81 | next if $schema->{unevaluatedItems}; | ||||
| 82 | $valid = E({ %$state, data_path => $state->{data_path}.'/'.$idx }, | ||||
| 83 | 'additional item not permitted') | ||||
| 84 | } | ||||
| 85 | else { | ||||
| 86 | my @annotations = @orig_annotations; | ||||
| 87 | if ($self->eval($data->[$idx], $schema->{unevaluatedItems}, | ||||
| 88 | +{ %$state, annotations => \@annotations, | ||||
| 89 | data_path => $state->{data_path}.'/'.$idx, | ||||
| 90 | schema_path => $state->{schema_path}.'/unevaluatedItems' })) { | ||||
| 91 | push @new_annotations, @annotations[$#orig_annotations+1 .. $#annotations]; | ||||
| 92 | next; | ||||
| 93 | } | ||||
| 94 | |||||
| 95 | $valid = 0; | ||||
| 96 | } | ||||
| 97 | last if $state->{short_circuit}; | ||||
| 98 | } | ||||
| 99 | |||||
| 100 | push $state->{annotations}->@*, @new_annotations; | ||||
| 101 | A($state, true); | ||||
| 102 | return E($state, 'subschema is not valid against all additional items') if not $valid; | ||||
| 103 | return 1; | ||||
| 104 | } | ||||
| 105 | |||||
| 106 | 624 | 154µs | # spent 5.62ms (1.09+4.52) within JSON::Schema::Modern::Vocabulary::Unevaluated::_traverse_keyword_unevaluatedProperties which was called 156 times, avg 36µs/call:
# 156 times (1.09ms+4.52ms) by JSON::Schema::Modern::_traverse_subschema at line 457 of JSON/Schema/Modern.pm, avg 36µs/call | ||
| 107 | 156 | 486µs | 156 | 3.30ms | my $valid = $self->traverse_subschema($schema, $state); # spent 4.52ms making 156 calls to JSON::Schema::Modern::Vocabulary::traverse_subschema, avg 29µs/call, recursion: max depth 2, sum of overlapping time 1.22ms |
| 108 | |||||
| 109 | # remember that annotations need to be collected in order to evaluate this keyword | ||||
| 110 | 156 | 132µs | $state->{configs}{collect_annotations} = 1; | ||
| 111 | |||||
| 112 | 156 | 352µs | return $valid; | ||
| 113 | } | ||||
| 114 | |||||
| 115 | 18735 | 3.80ms | # spent 1.99s (177ms+1.81) within JSON::Schema::Modern::Vocabulary::Unevaluated::_eval_keyword_unevaluatedProperties which was called 3747 times, avg 531µs/call:
# 3747 times (177ms+1.81s) by JSON::Schema::Modern::_eval_subschema at line 548 of JSON/Schema/Modern.pm, avg 531µs/call | ||
| 116 | abort($state, 'EXCEPTION: "unevaluatedProperties" keyword present, but annotation collection is disabled') | ||||
| 117 | 3747 | 2.46ms | if not $state->{collect_annotations}; | ||
| 118 | |||||
| 119 | abort($state, 'EXCEPTION: "unevaluatedProperties" keyword present, but short_circuit is enabled: results unreliable') | ||||
| 120 | 3747 | 1.87ms | if $state->{short_circuit}; | ||
| 121 | |||||
| 122 | 3747 | 5.09ms | 3747 | 7.72ms | return 1 if not is_type('object', $data); # spent 7.72ms making 3747 calls to JSON::Schema::Modern::Utilities::is_type, avg 2µs/call |
| 123 | |||||
| 124 | my @evaluated_properties = map { | ||||
| 125 | 12992 | 23.0ms | 12992 | 817ms | my $keyword = $_->keyword; # spent 805ms making 3747 calls to JSON::Schema::Modern::Utilities::local_annotations, avg 215µs/call
# spent 11.9ms making 9245 calls to JSON::Schema::Modern::Annotation::keyword, avg 1µs/call |
| 126 | 9245 | 21.3ms | 9244 | 10.8ms | (grep $keyword eq $_, qw(properties additionalProperties patternProperties unevaluatedProperties)) # spent 10.8ms making 9244 calls to JSON::Schema::Modern::Annotation::annotation, avg 1µs/call |
| 127 | ? $_->annotation->@* : (); | ||||
| 128 | } local_annotations($state); | ||||
| 129 | |||||
| 130 | 3747 | 1.13ms | my $valid = 1; | ||
| 131 | 3747 | 17.9ms | my @orig_annotations = $state->{annotations}->@*; | ||
| 132 | 3747 | 1.23ms | my (@properties, @new_annotations); | ||
| 133 | 3747 | 22.1ms | 3747 | 4.20ms | foreach my $property (sort keys %$data) { # spent 4.20ms making 3747 calls to JSON::Schema::Modern::Vocabulary::Unevaluated::CORE:sort, avg 1µs/call |
| 134 | 54233 | 46.4ms | 7991 | 18.3ms | next if any { $_ eq $property } @evaluated_properties; # spent 18.3ms making 7991 calls to List::Util::any, avg 2µs/call |
| 135 | push @properties, $property; | ||||
| 136 | |||||
| 137 | if (is_type('boolean', $schema->{unevaluatedProperties})) { | ||||
| 138 | next if $schema->{unevaluatedProperties}; | ||||
| 139 | $valid = E({ %$state, data_path => jsonp($state->{data_path}, $property) }, | ||||
| 140 | 'additional property not permitted'); | ||||
| 141 | } | ||||
| 142 | else { | ||||
| 143 | my @annotations = @orig_annotations; | ||||
| 144 | if ($self->eval($data->{$property}, $schema->{unevaluatedProperties}, | ||||
| 145 | +{ %$state, annotations => \@annotations, | ||||
| 146 | data_path => jsonp($state->{data_path}, $property), | ||||
| 147 | schema_path => $state->{schema_path}.'/unevaluatedProperties' })) { | ||||
| 148 | push @new_annotations, @annotations[$#orig_annotations+1 .. $#annotations]; | ||||
| 149 | next; | ||||
| 150 | } | ||||
| 151 | |||||
| 152 | $valid = 0; | ||||
| 153 | } | ||||
| 154 | last if $state->{short_circuit}; | ||||
| 155 | } | ||||
| 156 | |||||
| 157 | 3747 | 2.25ms | push $state->{annotations}->@*, @new_annotations; | ||
| 158 | 3747 | 5.50ms | 3747 | 954ms | A($state, \@properties); # spent 954ms making 3747 calls to JSON::Schema::Modern::Utilities::A, avg 255µs/call |
| 159 | 3747 | 1.91ms | return E($state, 'not all additional properties are valid') if not $valid; | ||
| 160 | 3747 | 24.0ms | return 1; | ||
| 161 | } | ||||
| 162 | |||||
| 163 | 1 | 5µs | 1; | ||
| 164 | |||||
| 165 | 1 | 24µs | 1 | 456µs | __END__ # spent 456µs making 1 call to B::Hooks::EndOfScope::XS::__ANON__[B/Hooks/EndOfScope/XS.pm:26] |
# spent 77.3ms within JSON::Schema::Modern::Vocabulary::Unevaluated::CORE:match which was called 94075 times, avg 822ns/call:
# 94075 times (77.3ms+0s) by JSON::Schema::Modern::Vocabulary::Unevaluated::keywords at line 31, avg 822ns/call | |||||
# spent 4.20ms within JSON::Schema::Modern::Vocabulary::Unevaluated::CORE:sort which was called 3747 times, avg 1µs/call:
# 3747 times (4.20ms+0s) by JSON::Schema::Modern::Vocabulary::Unevaluated::_eval_keyword_unevaluatedProperties at line 133, avg 1µs/call |