← Index
NYTProf Performance Profile   « line view »
For ../prof.pl
  Run on Wed Dec 14 15:33:55 2022
Reported on Wed Dec 14 15:40:04 2022

Filename/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/JSON/Schema/Modern/Vocabulary/Core.pm
StatementsExecuted 1111246 statements in 1.47s
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
3912111705ms97.2sJSON::Schema::Modern::Vocabulary::Core::::_eval_keyword_refJSON::Schema::Modern::Vocabulary::Core::_eval_keyword_ref (recurses: max depth 31, inclusive time 939s)
9407521331ms331msJSON::Schema::Modern::Vocabulary::Core::::keywordsJSON::Schema::Modern::Vocabulary::Core::keywords
2586211328ms1.87sJSON::Schema::Modern::Vocabulary::Core::::_eval_keyword_idJSON::Schema::Modern::Vocabulary::Core::_eval_keyword_id
258611143ms68.0sJSON::Schema::Modern::Vocabulary::Core::::_eval_keyword_dynamicRefJSON::Schema::Modern::Vocabulary::Core::_eval_keyword_dynamicRef (recurses: max depth 6, inclusive time 72.9s)
725224.20ms171msJSON::Schema::Modern::Vocabulary::Core::::_traverse_keyword_refJSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_ref
1111543µs5.94msJSON::Schema::Modern::Vocabulary::Core::::_traverse_keyword_vocabularyJSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_vocabulary
11811522µs2.33msJSON::Schema::Modern::Vocabulary::Core::::_traverse_keyword_commentJSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_comment
1411455µs5.94msJSON::Schema::Modern::Vocabulary::Core::::_traverse_keyword_idJSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_id
1522336µs4.42msJSON::Schema::Modern::Vocabulary::Core::::_traverse_keyword_anchorJSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_anchor
1511285µs4.58msJSON::Schema::Modern::Vocabulary::Core::::_traverse_keyword_schemaJSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_schema
3011111µs111µsJSON::Schema::Modern::Vocabulary::Core::::CORE:matchJSON::Schema::Modern::Vocabulary::Core::CORE:match (opcode)
111102µs664µsJSON::Schema::Modern::Vocabulary::Core::::__fetch_vocabulary_dataJSON::Schema::Modern::Vocabulary::Core::__fetch_vocabulary_data
133194µs115µsJSON::Schema::Modern::Vocabulary::Core::::CORE:sortJSON::Schema::Modern::Vocabulary::Core::CORE:sort (opcode)
221168µs5.63msJSON::Schema::Modern::Vocabulary::Core::::_traverse_keyword_dynamicRefJSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_dynamicRef
121146µs80.9msJSON::Schema::Modern::Vocabulary::Core::::_traverse_keyword_defsJSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_defs (recurses: max depth 1, inclusive time 13.6ms)
141145µs4.10msJSON::Schema::Modern::Vocabulary::Core::::_traverse_keyword_dynamicAnchorJSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_dynamicAnchor
11132µs35µsModule::Runtime::::BEGIN@1 Module::Runtime::BEGIN@1
11125µs991µsJSON::Schema::Modern::Vocabulary::Core::::BEGIN@11JSON::Schema::Modern::Vocabulary::Core::BEGIN@11
11118µs38µsJSON::Schema::Modern::Vocabulary::Core::::BEGIN@14JSON::Schema::Modern::Vocabulary::Core::BEGIN@14
11117µs50µsJSON::Schema::Modern::Vocabulary::Core::::BEGIN@13JSON::Schema::Modern::Vocabulary::Core::BEGIN@13
11116µs16µsJSON::Schema::Modern::Vocabulary::Core::::BEGIN@9JSON::Schema::Modern::Vocabulary::Core::BEGIN@9
11115µs28µsJSON::Schema::Modern::Vocabulary::Core::::BEGIN@16JSON::Schema::Modern::Vocabulary::Core::BEGIN@16
11112µs27µsJSON::Schema::Modern::Vocabulary::Core::::BEGIN@15JSON::Schema::Modern::Vocabulary::Core::BEGIN@15
11111µs281µsJSON::Schema::Modern::Vocabulary::Core::::BEGIN@10JSON::Schema::Modern::Vocabulary::Core::BEGIN@10
11110µs264µsJSON::Schema::Modern::Vocabulary::Core::::BEGIN@18JSON::Schema::Modern::Vocabulary::Core::BEGIN@18
1119µs138µsJSON::Schema::Modern::Vocabulary::Core::::BEGIN@12JSON::Schema::Modern::Vocabulary::Core::BEGIN@12
1119µs73µsJSON::Schema::Modern::Vocabulary::Core::::BEGIN@17JSON::Schema::Modern::Vocabulary::Core::BEGIN@17
1117µs36µsModule::Runtime::::BEGIN@2 Module::Runtime::BEGIN@2
3112µs2µsJSON::Schema::Modern::Vocabulary::Core::::evaluation_orderJSON::Schema::Modern::Vocabulary::Core::evaluation_order
1111µs1µsJSON::Schema::Modern::Vocabulary::Core::::vocabularyJSON::Schema::Modern::Vocabulary::Core::vocabulary
0000s0sJSON::Schema::Modern::Vocabulary::Core::::_eval_keyword_recursiveAnchorJSON::Schema::Modern::Vocabulary::Core::_eval_keyword_recursiveAnchor
0000s0sJSON::Schema::Modern::Vocabulary::Core::::_eval_keyword_recursiveRefJSON::Schema::Modern::Vocabulary::Core::_eval_keyword_recursiveRef
0000s0sJSON::Schema::Modern::Vocabulary::Core::::_traverse_keyword_definitionsJSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_definitions
0000s0sJSON::Schema::Modern::Vocabulary::Core::::_traverse_keyword_recursiveAnchorJSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_recursiveAnchor
0000s0sJSON::Schema::Modern::Vocabulary::Core::::_traverse_keyword_recursiveRefJSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_recursiveRef
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1233µs238µs
# spent 35µs (32+3) within Module::Runtime::BEGIN@1 which was called: # once (32µs+3µs) by Module::Runtime::require_module at line 1
use strict;
# spent 35µs making 1 call to Module::Runtime::BEGIN@1 # spent 3µs making 1 call to strict::import
2248µs265µs
# spent 36µs (7+29) within Module::Runtime::BEGIN@2 which was called: # once (7µs+29µs) by Module::Runtime::require_module at line 2
use warnings;
# spent 36µs making 1 call to Module::Runtime::BEGIN@2 # spent 29µs making 1 call to warnings::import
3package JSON::Schema::Modern::Vocabulary::Core;
4# vim: set ts=8 sts=2 sw=2 tw=100 et :
5# ABSTRACT: Implementation of the JSON Schema Core vocabulary
6
710sour $VERSION = '0.552';
8
9238µs116µs
# spent 16µs within JSON::Schema::Modern::Vocabulary::Core::BEGIN@9 which was called: # once (16µs+0s) by Module::Runtime::require_module at line 9
use 5.020;
10233µs2551µs
# spent 281µs (11+270) within JSON::Schema::Modern::Vocabulary::Core::BEGIN@10 which was called: # once (11µs+270µs) by Module::Runtime::require_module at line 10
use Moo;
# spent 281µs making 1 call to JSON::Schema::Modern::Vocabulary::Core::BEGIN@10 # spent 270µs making 1 call to Moo::import
11346µs31.96ms
# spent 991µs (25+966) within JSON::Schema::Modern::Vocabulary::Core::BEGIN@11 which was called: # once (25µs+966µs) by Module::Runtime::require_module at line 11
use strictures 2;
# spent 991µs making 1 call to JSON::Schema::Modern::Vocabulary::Core::BEGIN@11 # spent 945µs making 1 call to strictures::import # spent 20µs making 1 call to strictures::VERSION
12260µs2267µs
# spent 138µs (9+129) within JSON::Schema::Modern::Vocabulary::Core::BEGIN@12 which was called: # once (9µs+129µs) by Module::Runtime::require_module at line 12
use experimental qw(signatures postderef);
# spent 138µs making 1 call to JSON::Schema::Modern::Vocabulary::Core::BEGIN@12 # spent 129µs making 1 call to experimental::import
13241µs253µs
# spent 50µs (17+33) within JSON::Schema::Modern::Vocabulary::Core::BEGIN@13 which was called: # once (17µs+33µs) by Module::Runtime::require_module at line 13
use if "$]" >= 5.022, experimental => 're_strict';
# spent 50µs making 1 call to JSON::Schema::Modern::Vocabulary::Core::BEGIN@13 # spent 3µs making 1 call to if::import
14230µs240µs
# spent 38µs (18+20) within JSON::Schema::Modern::Vocabulary::Core::BEGIN@14 which was called: # once (18µs+20µs) by Module::Runtime::require_module at line 14
no if "$]" >= 5.031009, feature => 'indirect';
# spent 38µs making 1 call to JSON::Schema::Modern::Vocabulary::Core::BEGIN@14 # spent 2µs making 1 call to if::unimport
15232µs229µs
# spent 27µs (12+15) within JSON::Schema::Modern::Vocabulary::Core::BEGIN@15 which was called: # once (12µs+15µs) by Module::Runtime::require_module at line 15
no if "$]" >= 5.033001, feature => 'multidimensional';
# spent 27µs making 1 call to JSON::Schema::Modern::Vocabulary::Core::BEGIN@15 # spent 2µs making 1 call to if::unimport
16227µs229µs
# spent 28µs (15+13) within JSON::Schema::Modern::Vocabulary::Core::BEGIN@16 which was called: # once (15µs+13µs) by Module::Runtime::require_module at line 16
no if "$]" >= 5.033006, feature => 'bareword_filehandles';
# spent 28µs making 1 call to JSON::Schema::Modern::Vocabulary::Core::BEGIN@16 # spent 1µs making 1 call to if::unimport
172170µs2137µs
# spent 73µs (9+64) within JSON::Schema::Modern::Vocabulary::Core::BEGIN@17 which was called: # once (9µs+64µs) by Module::Runtime::require_module at line 17
use JSON::Schema::Modern::Utilities qw(is_type abort assert_keyword_type canonical_uri E assert_uri_reference assert_uri jsonp);
# spent 73µs making 1 call to JSON::Schema::Modern::Vocabulary::Core::BEGIN@17 # spent 64µs making 1 call to Exporter::import
1822.76ms2518µs
# spent 264µs (10+254) within JSON::Schema::Modern::Vocabulary::Core::BEGIN@18 which was called: # once (10µs+254µs) by Module::Runtime::require_module at line 18
use namespace::clean;
# spent 264µs making 1 call to JSON::Schema::Modern::Vocabulary::Core::BEGIN@18 # spent 254µs making 1 call to namespace::clean::import
19
2013µs14.18mswith 'JSON::Schema::Modern::Vocabulary';
# spent 4.18ms making 1 call to Moo::with
21
22
# spent 1µs within JSON::Schema::Modern::Vocabulary::Core::vocabulary which was called: # once (1µ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
sub vocabulary {
2313µs 'https://json-schema.org/draft/2019-09/vocab/core' => 'draft2019-09',
24 'https://json-schema.org/draft/2020-12/vocab/core' => 'draft2020-12';
25}
26
2736µs
# spent 2µs within JSON::Schema::Modern::Vocabulary::Core::evaluation_order which was called 3 times, avg 667ns/call: # 3 times (2µs+0s) by JSON::Schema::Modern::Vocabulary::Core::CORE:sort at line 322, avg 667ns/call
sub evaluation_order { 0 }
28
2928222553.9ms
# spent 331ms within JSON::Schema::Modern::Vocabulary::Core::keywords which was called 94075 times, avg 4µs/call: # 91595 times (324ms+0s) by JSON::Schema::Modern::_eval_subschema at line 535 of JSON/Schema/Modern.pm, avg 4µs/call # 2480 times (7.26ms+0s) by JSON::Schema::Modern::_traverse_subschema at line 447 of JSON/Schema/Modern.pm, avg 3µs/call
sub keywords ($self, $spec_version) {
30 return (
3194075357ms qw($id $schema),
32 $spec_version ne 'draft7' ? '$anchor' : (),
33 $spec_version eq 'draft2019-09' ? '$recursiveAnchor' : (),
34 $spec_version eq 'draft2020-12' ? '$dynamicAnchor' : (),
35 '$ref',
36 $spec_version eq 'draft2019-09' ? '$recursiveRef' : (),
37 $spec_version eq 'draft2020-12' ? '$dynamicRef' : (),
38 $spec_version eq 'draft7' ? 'definitions' : qw($vocabulary $comment $defs),
39 );
40}
41
42# adds the following keys to $state during traversal:
43# - identifiers: an arrayref of tuples:
44# $uri => { path => $path_to_identifier, canonical_uri => Mojo::URL (absolute when possible) }
45# this is used by the Document constructor to build its resource_index.
46
47568µs
# spent 5.94ms (455µs+5.48) within JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_id which was called 14 times, avg 424µs/call: # 14 times (455µs+5.48ms) by JSON::Schema::Modern::_traverse_subschema at line 457 of JSON/Schema/Modern.pm, avg 424µs/call
sub _traverse_keyword_id ($self, $schema, $state) {
481457µs283.08ms return if not assert_keyword_type($state, $schema, 'string')
# spent 2.27ms making 14 calls to JSON::Schema::Modern::Utilities::assert_uri_reference, avg 162µs/call # spent 809µs making 14 calls to JSON::Schema::Modern::Utilities::assert_keyword_type, avg 58µs/call
49 or not assert_uri_reference($state, $schema);
50
511430µs14566µs my $uri = Mojo::URL->new($schema->{'$id'});
# spent 566µs making 14 calls to Mojo::URL::new, avg 40µs/call
52
531418µs if ($state->{spec_version} eq 'draft7') {
54 if (length($uri->fragment)) {
55 return E($state, '$id cannot change the base uri at the same time as declaring an anchor')
56 if length($uri->clone->fragment(undef));
57
58 return $self->_traverse_keyword_anchor({ %$schema, $state->{keyword} => $uri->fragment }, $state);
59 }
60 }
61 else {
621413µs148µs return E($state, '$id value "%s" cannot have a non-empty fragment', $schema->{'$id'})
# spent 8µs making 14 calls to Mojo::URL::fragment, avg 571ns/call
63 if length $uri->fragment;
64 }
65
661413µs1416µs $uri->fragment(undef);
# spent 16µs making 14 calls to Mojo::URL::fragment, avg 1µs/call
671430µs141.18ms return E($state, '$id cannot be empty') if not length $uri;
# spent 1.18ms making 14 calls to Mojo::URL::__ANON__[Mojo/URL.pm:3], avg 84µs/call
68
691424µs1445µs $state->{initial_schema_uri} = $uri->is_abs ? $uri : $uri->to_abs($state->{initial_schema_uri});
# spent 45µs making 14 calls to Mojo::URL::is_abs, avg 3µs/call
701417µs $state->{traversed_schema_path} = $state->{traversed_schema_path}.$state->{schema_path};
71 # we don't set or update document_path because it is identical to traversed_schema_path
721410µs $state->{schema_path} = '';
73
74 push $state->{identifiers}->@*,
75 $state->{initial_schema_uri} => {
76 path => $state->{traversed_schema_path},
77 canonical_uri => $state->{initial_schema_uri}->clone,
78 specification_version => $state->{spec_version}, # note! $schema keyword can change this
79 vocabularies => $state->{vocabularies}, # reference, not copy
80 configs => $state->{configs},
8114127µs14589µs };
# spent 589µs making 14 calls to Mojo::URL::clone, avg 42µs/call
821433µs return 1;
83}
84
8512931029.4ms
# spent 1.87s (328ms+1.54) within JSON::Schema::Modern::Vocabulary::Core::_eval_keyword_id which was called 25862 times, avg 72µs/call: # 25862 times (328ms+1.54s) by JSON::Schema::Modern::_eval_subschema at line 548 of JSON/Schema/Modern.pm, avg 72µs/call
sub _eval_keyword_id ($self, $data, $schema, $state) {
862586280.2ms25862687ms my $schema_info = $state->{document}->path_to_resource($state->{document_path}.$state->{schema_path});
# spent 687ms making 25862 calls to JSON::Schema::Modern::Document::path_to_resource, avg 27µs/call
87 # this should never happen, if the pre-evaluation traversal was performed correctly
88258626.61ms abort($state, 'failed to resolve %s to canonical uri', $state->{keyword}) if not $schema_info;
89
902586242.2ms25862851ms $state->{initial_schema_uri} = $schema_info->{canonical_uri}->clone;
# spent 851ms making 25862 calls to Mojo::URL::clone, avg 33µs/call
912586226.7ms $state->{traversed_schema_path} = $state->{traversed_schema_path}.$state->{schema_path};
922586210.7ms $state->{document_path} = $state->{document_path}.$state->{schema_path};
93258627.35ms $state->{schema_path} = '';
94258629.24ms $state->{spec_version} = $schema_info->{specification_version};
95258628.06ms $state->{vocabularies} = $schema_info->{vocabularies};
962586224.6ms $state->@{keys $state->{configs}->%*} = values $state->{configs}->%*;
972586227.1ms push $state->{dynamic_scope}->@*, $state->{initial_schema_uri};
98
992586247.0ms return 1;
100}
101
1026019µs
# spent 4.58ms (285µs+4.29) within JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_schema which was called 15 times, avg 305µs/call: # 15 times (285µs+4.29ms) by JSON::Schema::Modern::_traverse_subschema at line 457 of JSON/Schema/Modern.pm, avg 305µs/call
sub _traverse_keyword_schema ($self, $schema, $state) {
1031545µs302.58ms return if not assert_keyword_type($state, $schema, 'string') or not assert_uri($state, $schema);
# spent 2.31ms making 15 calls to JSON::Schema::Modern::Utilities::assert_uri, avg 154µs/call # spent 275µs making 15 calls to JSON::Schema::Modern::Utilities::assert_keyword_type, avg 18µs/call
104
105 # "A JSON Schema resource is a schema which is canonically identified by an absolute URI."
106 # "A resource's root schema is its top-level schema object."
107 # note: we need not be at the document root, but simply adjacent to an $id (or be the at the
108 # document root)
109 return E($state, '$schema can only appear at the schema resource root')
110159µs if length($state->{schema_path});
111
112154µs my ($spec_version, $vocabularies);
113
1141547µs15443µs if (my $metaschema_info = $state->{evaluator}->_get_metaschema_vocabulary_classes($schema->{'$schema'})) {
# spent 443µs making 15 calls to JSON::Schema::Modern::_get_metaschema_vocabulary_classes, avg 30µs/call
115 ($spec_version, $vocabularies) = @$metaschema_info;
116 }
117 else {
11813µs1551µs my $schema_info = $state->{evaluator}->_fetch_from_uri($schema->{'$schema'});
# spent 551µs making 1 call to JSON::Schema::Modern::_fetch_from_uri
11910s return E($state, 'EXCEPTION: unable to find resource %s', $schema->{'$schema'}) if not $schema_info;
120
121 ($spec_version, $vocabularies) = $self->__fetch_vocabulary_data({ %$state,
122 keyword => '$vocabulary', initial_schema_uri => Mojo::URL->new($schema->{'$schema'}),
123115µs3715µs traversed_schema_path => jsonp($state->{schema_path}, '$schema'),
# spent 664µs making 1 call to JSON::Schema::Modern::Vocabulary::Core::__fetch_vocabulary_data # spent 40µs making 1 call to Mojo::URL::new # spent 11µs making 1 call to JSON::Schema::Modern::Utilities::jsonp
124 }, $schema_info);
125 }
126
127156µs return E($state, '"%s" is not a valid metaschema', $schema->{'$schema'}) if not @$vocabularies;
128
129 # we special-case this because the check in _eval_subschema for older drafts + $ref has already happened
130 return E($state, '$schema and $ref cannot be used together in older drafts')
1311541µs if exists $schema->{'$ref'} and $spec_version eq 'draft7';
132
1331520µs $state->@{qw(spec_version vocabularies)} = ($spec_version, $vocabularies);
134
135 # remember, if we don't have a sibling $id, we must be at the document root with no identifiers
1361521µs if ($state->{identifiers}->@*) {
137 $state->{identifiers}[-1]->@{qw(specification_version vocabularies)} = $state->@{qw(spec_version vocabularies)};
138 }
139
1401532µs return 1;
141}
142
1436030µs
# spent 4.42ms (336µs+4.08) within JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_anchor which was called 15 times, avg 294µs/call: # 14 times (276µs+3.78ms) by JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_dynamicAnchor at line 188, avg 290µs/call # once (60µs+302µs) by JSON::Schema::Modern::_traverse_subschema at line 457 of JSON/Schema/Modern.pm
sub _traverse_keyword_anchor ($self, $schema, $state) {
1441517µs15200µs return if not assert_keyword_type($state, $schema, 'string');
# spent 200µs making 15 calls to JSON::Schema::Modern::Utilities::assert_keyword_type, avg 13µs/call
145
146 return E($state, '%s value "%s" does not match required syntax',
147 $state->{keyword}, ($state->{keyword} eq '$id' ? '#' : '').$schema->{$state->{keyword}})
148 if $state->{spec_version} =~ /^draft(?:7|2019-09)$/
149 and $schema->{$state->{keyword}} !~ /^[A-Za-z][A-Za-z0-9_:.-]*$/
150 or $state->{spec_version} eq 'draft2020-12'
15115175µs30111µs and $schema->{$state->{keyword}} !~ /^[A-Za-z_][A-Za-z0-9._-]*$/;
# spent 111µs making 30 calls to JSON::Schema::Modern::Vocabulary::Core::CORE:match, avg 4µs/call
152
1531528µs15820µs my $canonical_uri = canonical_uri($state);
# spent 820µs making 15 calls to JSON::Schema::Modern::Utilities::canonical_uri, avg 55µs/call
154
155 push $state->{identifiers}->@*,
156 Mojo::URL->new->to_abs($canonical_uri)->fragment($schema->{$state->{keyword}}) => {
157 path => $state->{traversed_schema_path}.$state->{schema_path},
158 canonical_uri => $canonical_uri,
159 specification_version => $state->{spec_version},
160 vocabularies => $state->{vocabularies}, # reference, not copy
161 configs => $state->{configs},
16215115µs452.95ms };
# spent 2.90ms making 15 calls to Mojo::URL::to_abs, avg 193µs/call # spent 35µs making 15 calls to Mojo::URL::new, avg 2µs/call # spent 20µs making 15 calls to Mojo::URL::fragment, avg 1µs/call
1631532µs return 1;
164}
165
166# we already indexed the $anchor uri, so there is nothing more to do at evaluation time.
167# we explicitly do NOT set $state->{initial_schema_uri}.
168
169sub _traverse_keyword_recursiveAnchor ($self, $schema, $state) {
170 return if not assert_keyword_type($state, $schema, 'boolean');
171
172 # this is required because the location is used as the base URI for future resolution
173 # of $recursiveRef, and the fragment would be disregarded in the base
174 return E($state, '"$recursiveAnchor" keyword used without "$id"')
175 if length($state->{schema_path});
176 return 1;
177}
178
179sub _eval_keyword_recursiveAnchor ($self, $data, $schema, $state) {
180 return 1 if not $schema->{'$recursiveAnchor'} or exists $state->{recursive_anchor_uri};
181
182 # record the canonical location of the current position, to be used against future resolution
183 # of a $recursiveRef uri -- as if it was the current location when we encounter a $ref.
184 $state->{recursive_anchor_uri} = canonical_uri($state);
185 return 1;
186}
187
1881441µs144.05ms
# spent 4.10ms (45µs+4.06) within JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_dynamicAnchor which was called 14 times, avg 293µs/call: # 14 times (45µs+4.06ms) by JSON::Schema::Modern::_traverse_subschema at line 457 of JSON/Schema/Modern.pm, avg 293µs/call
sub _traverse_keyword_dynamicAnchor { shift->_traverse_keyword_anchor(@_) }
# spent 4.05ms making 14 calls to JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_anchor, avg 290µs/call
189
190# we already indexed the $dynamicAnchor uri, so there is nothing more to do at evaluation time.
191# we explicitly do NOT set $state->{initial_schema_uri}.
192
1932900520µs
# spent 171ms (4.20+167) within JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_ref which was called 725 times, avg 236µs/call: # 703 times (4.05ms+161ms) by JSON::Schema::Modern::_traverse_subschema at line 457 of JSON/Schema/Modern.pm, avg 235µs/call # 22 times (153µs+5.41ms) by JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_dynamicRef at line 219, avg 253µs/call
sub _traverse_keyword_ref ($self, $schema, $state) {
1947251.47ms1450167ms return if not assert_keyword_type($state, $schema, 'string')
# spent 156ms making 725 calls to JSON::Schema::Modern::Utilities::assert_uri_reference, avg 215µs/call # spent 10.8ms making 725 calls to JSON::Schema::Modern::Utilities::assert_keyword_type, avg 15µs/call
195 or not assert_uri_reference($state, $schema);
1967251.53ms return 1;
197}
198
19919560538.0ms
# spent 97.2s (705ms+96.5) within JSON::Schema::Modern::Vocabulary::Core::_eval_keyword_ref which was called 39121 times, avg 2.49ms/call: # 39121 times (705ms+96.5s) by JSON::Schema::Modern::_eval_subschema at line 548 of JSON/Schema/Modern.pm, avg 2.49ms/call
sub _eval_keyword_ref ($self, $data, $schema, $state) {
20039121154ms7824212.0s my $uri = Mojo::URL->new($schema->{'$ref'})->to_abs($state->{initial_schema_uri});
# spent 7.92s making 39121 calls to Mojo::URL::to_abs, avg 202µs/call # spent 4.04s making 39121 calls to Mojo::URL::new, avg 103µs/call
20139121437ms3912197.2s $self->eval_subschema_at_uri($data, $schema, $state, $uri);
# spent 1023s making 39121 calls to JSON::Schema::Modern::Vocabulary::eval_subschema_at_uri, avg 26.2ms/call, recursion: max depth 38, sum of overlapping time 926s
202}
203
204sub _traverse_keyword_recursiveRef { shift->_traverse_keyword_ref(@_) }
205
206sub _eval_keyword_recursiveRef ($self, $data, $schema, $state) {
207 my $uri = Mojo::URL->new($schema->{'$recursiveRef'})->to_abs($state->{initial_schema_uri});
208 my $schema_info = $state->{evaluator}->_fetch_from_uri($uri);
209 abort($state, 'EXCEPTION: unable to find resource %s', $uri) if not $schema_info;
210
211 if (is_type('boolean', $schema_info->{schema}{'$recursiveAnchor'}) and $schema_info->{schema}{'$recursiveAnchor'}) {
212 $uri = Mojo::URL->new($schema->{'$recursiveRef'})
213 ->to_abs($state->{recursive_anchor_uri} // $state->{initial_schema_uri});
214 }
215
216 return $self->eval_subschema_at_uri($data, $schema, $state, $uri);
217}
218
2192269µs225.57ms
# spent 5.63ms (68µs+5.57) within JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_dynamicRef which was called 22 times, avg 256µs/call: # 22 times (68µs+5.57ms) by JSON::Schema::Modern::_traverse_subschema at line 457 of JSON/Schema/Modern.pm, avg 256µs/call
sub _traverse_keyword_dynamicRef { shift->_traverse_keyword_ref(@_) }
# spent 5.57ms making 22 calls to JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_ref, avg 253µs/call
220
221129303.08ms
# spent 68.0s (143ms+67.8) within JSON::Schema::Modern::Vocabulary::Core::_eval_keyword_dynamicRef which was called 2586 times, avg 26.3ms/call: # 2586 times (143ms+67.8s) by JSON::Schema::Modern::_eval_subschema at line 548 of JSON/Schema/Modern.pm, avg 26.3ms/call
sub _eval_keyword_dynamicRef ($self, $data, $schema, $state) {
222258610.2ms5172746ms my $uri = Mojo::URL->new($schema->{'$dynamicRef'})->to_abs($state->{initial_schema_uri});
# spent 411ms making 2586 calls to Mojo::URL::to_abs, avg 159µs/call # spent 334ms making 2586 calls to Mojo::URL::new, avg 129µs/call
22325867.02ms2586662ms my $schema_info = $state->{evaluator}->_fetch_from_uri($uri);
# spent 662ms making 2586 calls to JSON::Schema::Modern::_fetch_from_uri, avg 256µs/call
22425861.06ms abort($state, 'EXCEPTION: unable to find resource %s', $uri) if not $schema_info;
225
226 # If the initially resolved starting point URI includes a fragment that was created by the
227 # "$dynamicAnchor" keyword, ...
228258611.0ms51723.57ms if (length $uri->fragment and exists $schema_info->{schema}{'$dynamicAnchor'}
# spent 3.57ms making 5172 calls to Mojo::URL::fragment, avg 690ns/call
229 and $uri->fragment eq (my $anchor = $schema_info->{schema}{'$dynamicAnchor'})) {
230 # ...the initial URI MUST be replaced by the URI (including the fragment) for the outermost
231 # schema resource in the dynamic scope that defines an identically named fragment with
232 # "$dynamicAnchor".
23325861.89ms foreach my $base_scope ($state->{dynamic_scope}->@*) {
23425864.48ms5172318ms my $test_uri = Mojo::URL->new($base_scope)->fragment($anchor);
# spent 315ms making 2586 calls to Mojo::URL::new, avg 122µs/call # spent 2.62ms making 2586 calls to Mojo::URL::fragment, avg 1µs/call
23525864.48ms2586483ms my $dynamic_anchor_subschema_info = $state->{evaluator}->_fetch_from_uri($test_uri);
# spent 483ms making 2586 calls to JSON::Schema::Modern::_fetch_from_uri, avg 187µs/call
23625862.05ms if (($dynamic_anchor_subschema_info->{schema}->{'$dynamicAnchor'}//'') eq $anchor) {
23725869.00ms $uri = $test_uri;
23825866.37ms last;
239 }
240 }
241 }
242
243258642.6ms25860s return $self->eval_subschema_at_uri($data, $schema, $state, $uri);
# spent 139s making 2586 calls to JSON::Schema::Modern::Vocabulary::eval_subschema_at_uri, avg 53.6ms/call, recursion: max depth 34, sum of overlapping time 139s
244}
245
2464412µs
# spent 5.94ms (543µs+5.40) within JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_vocabulary which was called 11 times, avg 540µs/call: # 11 times (543µs+5.40ms) by JSON::Schema::Modern::_traverse_subschema at line 457 of JSON/Schema/Modern.pm, avg 540µs/call
sub _traverse_keyword_vocabulary ($self, $schema, $state) {
2471117µs1174µs return if not assert_keyword_type($state, $schema, 'object');
# spent 74µs making 11 calls to JSON::Schema::Modern::Utilities::assert_keyword_type, avg 7µs/call
248
249 return E($state, '$vocabulary can only appear at the schema resource root')
250115µs if length($state->{schema_path});
251
252118µs my $valid = 1;
253
254111µs my @vocabulary_classes;
2551166µs1115µs foreach my $uri (sort keys $schema->{'$vocabulary'}->%*) {
# spent 15µs making 11 calls to JSON::Schema::Modern::Vocabulary::Core::CORE:sort, avg 1µs/call
25631207µs31563µs $valid = 0, next if not assert_keyword_type({ %$state, _schema_path_suffix => $uri }, $schema, 'boolean');
# spent 563µs making 31 calls to JSON::Schema::Modern::Utilities::assert_keyword_type, avg 18µs/call
25731159µs314.75ms $valid = 0, next if not assert_uri({ %$state, _schema_path_suffix => $uri }, undef, $uri);
# spent 4.75ms making 31 calls to JSON::Schema::Modern::Utilities::assert_uri, avg 153µs/call
258 }
259
260 # we cannot return an error here for invalid or incomplete vocabulary lists, because
261 # - the specification vocabulary schemas themselves don't list Core,
262 # - it is possible for a metaschema to $ref to another metaschema that uses an unrecognized
263 # vocabulary uri while still validating those vocabulary keywords (e.g.
264 # https://spec.openapis.org/oas/3.1/schema-base/2021-05-20)
265 # Instead, we will verify these constraints when we actually use the metaschema, in
266 # _traverse_keyword_schema -> __fetch_vocabulary_data
267
2681126µs return $valid;
269}
270
271# we do nothing with $vocabulary yet at evaluation time. When we know we are in a metaschema,
272# we can scan the URIs included here and either abort if a vocabulary is enabled that we do not
273# understand, or turn on and off certain keyword behaviours based on the boolean values seen.
274
27547294µs
# spent 2.33ms (522µs+1.81) within JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_comment which was called 118 times, avg 20µs/call: # 118 times (522µs+1.81ms) by JSON::Schema::Modern::_traverse_subschema at line 457 of JSON/Schema/Modern.pm, avg 20µs/call
sub _traverse_keyword_comment ($self, $schema, $state) {
276118115µs1181.81ms return if not assert_keyword_type($state, $schema, 'string');
# spent 1.81ms making 118 calls to JSON::Schema::Modern::Utilities::assert_keyword_type, avg 15µs/call
277118191µs return 1;
278}
279
280# we do nothing with $comment at evaluation time, including not collecting its value for annotations.
281
282sub _traverse_keyword_definitions { shift->traverse_object_schemas(@_) }
2831250µs1280.9ms
# spent 80.9ms (46µs+80.9) within JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_defs which was called 12 times, avg 6.74ms/call: # 12 times (46µs+80.9ms) by JSON::Schema::Modern::_traverse_subschema at line 457 of JSON/Schema/Modern.pm, avg 6.74ms/call
sub _traverse_keyword_defs { shift->traverse_object_schemas(@_) }
# spent 94.4ms making 12 calls to JSON::Schema::Modern::Vocabulary::traverse_object_schemas, avg 7.87ms/call, recursion: max depth 2, sum of overlapping time 13.6ms
284
285# we do nothing directly with $defs at evaluation time, including not collecting its value for
286# annotations.
287
288
289# translate vocabulary URIs into classes, caching the results (if any)
29040s
# spent 664µs (102+562) within JSON::Schema::Modern::Vocabulary::Core::__fetch_vocabulary_data which was called: # once (102µs+562µs) by JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_schema at line 123
sub __fetch_vocabulary_data ($self, $state, $schema_info) {
29111µs if (not exists $schema_info->{schema}{'$vocabulary'}) {
292 # "If "$vocabulary" is absent, an implementation MAY determine behavior based on the meta-schema
293 # if it is recognized from the URI value of the referring schema's "$schema" keyword."
294 my $metaschema_uri = $state->{evaluator}->METASCHEMA_URIS->{$schema_info->{specification_version}};
295 return $state->{evaluator}->_get_metaschema_vocabulary_classes($metaschema_uri)->@*;
296 }
297
29810s my $valid = 1;
29911µs $valid = E($state, '$vocabulary can only appear at the document root') if length $schema_info->{document_path};
30011µs $valid = E($state, 'metaschemas must have an $id') if not exists $schema_info->{schema}{'$id'};
301
30210s return (undef, []) if not $valid;
303
30410s my @vocabulary_classes;
305
306112µs13µs foreach my $uri (sort keys $schema_info->{schema}{'$vocabulary'}->%*) {
307812µs8164µs my $class_info = $state->{evaluator}->_get_vocabulary_class($uri);
# spent 164µs making 8 calls to JSON::Schema::Modern::_get_vocabulary_class, avg 20µs/call
308 $valid = E({ %$state, _schema_path_suffix => $uri }, '"%s" is not a known vocabulary', $uri), next
309833µs88µs if $schema_info->{schema}{'$vocabulary'}{$uri} and not $class_info;
# spent 8µs making 8 calls to JSON::PP::Boolean::__ANON__[JSON/PP/Boolean.pm:7], avg 1µs/call
310
31180s next if not $class_info; # vocabulary is not known, but marked as false in the metaschema
312
31388µs my ($spec_version, $class) = @$class_info;
314 $valid = E({ %$state, _schema_path_suffix => $uri }, '"%s" uses %s, but the metaschema itself uses %s',
315 $uri, $spec_version, $schema_info->{specification_version}), next
31682µs if $spec_version ne $schema_info->{specification_version};
317
31887µs push @vocabulary_classes, $class;
319 }
320
321 @vocabulary_classes = sort {
3221647µs31118µs $a->evaluation_order <=> $b->evaluation_order
# spent 97µs making 1 call to JSON::Schema::Modern::Vocabulary::Core::CORE:sort # spent 4µs making 5 calls to JSON::Schema::Modern::Vocabulary::MetaData::evaluation_order, avg 800ns/call # spent 3µs making 4 calls to JSON::Schema::Modern::Vocabulary::Applicator::evaluation_order, avg 750ns/call # spent 3µs making 5 calls to JSON::Schema::Modern::Vocabulary::FormatAnnotation::evaluation_order, avg 600ns/call # spent 3µs making 5 calls to JSON::Schema::Modern::Vocabulary::Validation::evaluation_order, avg 600ns/call # spent 2µs making 3 calls to JSON::Schema::Modern::Vocabulary::Content::evaluation_order, avg 667ns/call # spent 2µs making 3 calls to JSON::Schema::Modern::Vocabulary::Core::evaluation_order, avg 667ns/call # spent 2µs making 2 calls to JSON::Schema::Modern::Vocabulary::Unevaluated::evaluation_order, avg 1µs/call # spent 2µs making 3 calls to JSON::Schema::Modern::Vocabulary::evaluation_order, avg 667ns/call
323 || ($a->evaluation_order == 999 ? 0
324 : ($valid = E($state, '%s and %s have a conflicting evaluation_order', sort $a, $b)))
325 } @vocabulary_classes;
326
32711µs $valid = E($state, 'the first vocabulary (by evaluation_order) must be Core')
328 if ($vocabulary_classes[0]//'') ne 'JSON::Schema::Modern::Vocabulary::Core';
329
330 $state->{evaluator}->_set_metaschema_vocabulary_classes($schema_info->{canonical_uri},
33114µs1290µs [ $schema_info->{specification_version}, \@vocabulary_classes ]) if $valid;
332
33315µs return ($schema_info->{specification_version}, $valid ? \@vocabulary_classes : []);
334}
335
33618µs1;
337
338147µs1595µs__END__
 
# spent 111µs within JSON::Schema::Modern::Vocabulary::Core::CORE:match which was called 30 times, avg 4µs/call: # 30 times (111µs+0s) by JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_anchor at line 151, avg 4µs/call
sub JSON::Schema::Modern::Vocabulary::Core::CORE:match; # opcode
# spent 115µs (94+21) within JSON::Schema::Modern::Vocabulary::Core::CORE:sort which was called 13 times, avg 9µs/call: # 11 times (15µs+0s) by JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_vocabulary at line 255, avg 1µs/call # once (76µs+21µs) by JSON::Schema::Modern::Vocabulary::Core::__fetch_vocabulary_data at line 322 # once (3µs+0s) by JSON::Schema::Modern::Vocabulary::Core::__fetch_vocabulary_data at line 306
sub JSON::Schema::Modern::Vocabulary::Core::CORE:sort; # opcode