← Index
NYTProf Performance Profile   « line view »
For ../prof.pl
  Run on Wed Dec 14 16:10:05 2022
Reported on Wed Dec 14 16:12:56 2022

Filename/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/JSON/Schema/Modern.pm
StatementsExecuted 18081507 statements in 15.0s
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
915953211.9s87.2sJSON::Schema::Modern::::_eval_subschemaJSON::Schema::Modern::_eval_subschema (recurses: max depth 74, inclusive time 1984s)
46881532.53s22.5sJSON::Schema::Modern::::_fetch_from_uriJSON::Schema::Modern::_fetch_from_uri
111307ms87.5sJSON::Schema::Modern::::evaluateJSON::Schema::Modern::evaluate
3912311197ms7.36sJSON::Schema::Modern::::_get_or_load_resourceJSON::Schema::Modern::_get_or_load_resource
286352174ms573msJSON::Schema::Modern::::_traverse_subschemaJSON::Schema::Modern::_traverse_subschema (recurses: max depth 6, inclusive time 594ms)
7434330.0ms1.23sJSON::Schema::Modern::::traverseJSON::Schema::Modern::traverse (recurses: max depth 1, inclusive time 1.94ms)
1119.09ms12.8msJSON::Schema::Modern::::BEGIN@25JSON::Schema::Modern::BEGIN@25
1118.18ms77.1msJSON::Schema::Modern::::BEGIN@31JSON::Schema::Modern::BEGIN@31
743115.16ms108msJSON::Schema::Modern::::_get_metaschema_infoJSON::Schema::Modern::_get_metaschema_info (recurses: max depth 1, inclusive time 79µs)
1113.64ms5.45msJSON::Schema::Modern::::BEGIN@36JSON::Schema::Modern::BEGIN@36
1112.88ms25.6msJSON::Schema::Modern::::BEGIN@27JSON::Schema::Modern::BEGIN@27
1112.83ms164msJSON::Schema::Modern::::BEGIN@23JSON::Schema::Modern::BEGIN@23
1112.75ms36.6msJSON::Schema::Modern::::BEGIN@34JSON::Schema::Modern::BEGIN@34
1112.38ms2.66msJSON::Schema::Modern::::BEGIN@28JSON::Schema::Modern::BEGIN@28
1112.32ms54.7msJSON::Schema::Modern::::BEGIN@35JSON::Schema::Modern::BEGIN@35
1111.66ms71.5msJSON::Schema::Modern::::BEGIN@33JSON::Schema::Modern::BEGIN@33
1111.26ms1.45msJSON::Schema::Modern::::BEGIN@30JSON::Schema::Modern::BEGIN@30
1111.19ms9.20msJSON::Schema::Modern::::BEGIN@18JSON::Schema::Modern::BEGIN@18
9321.11ms134msJSON::Schema::Modern::::add_schemaJSON::Schema::Modern::add_schema
111810µs7.43msJSON::Schema::Modern::::BEGIN@29JSON::Schema::Modern::BEGIN@29
1511655µs13.3msJSON::Schema::Modern::::__ANON__[:676]JSON::Schema::Modern::__ANON__[:676]
111113µs55.4msJSON::Schema::Modern::::__ANON__[:700]JSON::Schema::Modern::__ANON__[:700]
11169µs61.2msJSON::Schema::Modern::::add_vocabularyJSON::Schema::Modern::add_vocabulary
11147µs1.10msJSON::Schema::Modern::::__ANON__[:124]JSON::Schema::Modern::__ANON__[:124]
11134µs174µsJSON::Schema::Modern::::__ANON__[:742]JSON::Schema::Modern::__ANON__[:742]
11126µs28µsOpenAPI::Modern::::BEGIN@1 OpenAPI::Modern::BEGIN@1
11120µs1.20msJSON::Schema::Modern::::BEGIN@12JSON::Schema::Modern::BEGIN@12
11120µs73µsJSON::Schema::Modern::::BEGIN@20JSON::Schema::Modern::BEGIN@20
11120µs73µsJSON::Schema::Modern::::BEGIN@784JSON::Schema::Modern::BEGIN@784
11119µs72µsJSON::Schema::Modern::::BEGIN@14JSON::Schema::Modern::BEGIN@14
11117µs86µsJSON::Schema::Modern::::BEGIN@778JSON::Schema::Modern::BEGIN@778
11116µs44µsJSON::Schema::Modern::::BEGIN@15JSON::Schema::Modern::BEGIN@15
11113µs43µsJSON::Schema::Modern::::BEGIN@21JSON::Schema::Modern::BEGIN@21
11113µs69µsJSON::Schema::Modern::::BEGIN@26JSON::Schema::Modern::BEGIN@26
11113µs72µsJSON::Schema::Modern::::BEGIN@32JSON::Schema::Modern::BEGIN@32
11112µs12µsJSON::Schema::Modern::::BEGIN@10JSON::Schema::Modern::BEGIN@10
11111µs134µsJSON::Schema::Modern::::BEGIN@13JSON::Schema::Modern::BEGIN@13
11111µs69µsJSON::Schema::Modern::::__ANON__[:900]JSON::Schema::Modern::__ANON__[:900]
11110µs24µsJSON::Schema::Modern::::BEGIN@16JSON::Schema::Modern::BEGIN@16
11110µs26µsJSON::Schema::Modern::::BEGIN@17JSON::Schema::Modern::BEGIN@17
11110µs13µsJSON::Schema::Modern::::__ANON__[:133]JSON::Schema::Modern::__ANON__[:133]
1118µs269µsJSON::Schema::Modern::::BEGIN@11JSON::Schema::Modern::BEGIN@11
1118µs27µsJSON::Schema::Modern::::BEGIN@19JSON::Schema::Modern::BEGIN@19
1118µs83µsJSON::Schema::Modern::::BEGIN@24JSON::Schema::Modern::BEGIN@24
1117µs363µsJSON::Schema::Modern::::BEGIN@37JSON::Schema::Modern::BEGIN@37
1117µs40µsJSON::Schema::Modern::::BEGIN@46JSON::Schema::Modern::BEGIN@46
1116µs18µsJSON::Schema::Modern::::BEGIN@22JSON::Schema::Modern::BEGIN@22
1116µs50µsOpenAPI::Modern::::BEGIN@2 OpenAPI::Modern::BEGIN@2
1114µs19µsJSON::Schema::Modern::::BEGIN@47JSON::Schema::Modern::BEGIN@47
1114µs6µsJSON::Schema::Modern::::__ANON__[:69]JSON::Schema::Modern::__ANON__[:69]
1114µs6µsJSON::Schema::Modern::::__ANON__[:90]JSON::Schema::Modern::__ANON__[:90]
1112µs2µsJSON::Schema::Modern::::__ANON__[:640]JSON::Schema::Modern::__ANON__[:640]
1111µs1µsJSON::Schema::Modern::::__ANON__[:121]JSON::Schema::Modern::__ANON__[:121]
0000s0sJSON::Schema::Modern::::FREEZEJSON::Schema::Modern::FREEZE
0000s0sJSON::Schema::Modern::::THAWJSON::Schema::Modern::THAW
0000s0sJSON::Schema::Modern::::__ANON__[:177]JSON::Schema::Modern::__ANON__[:177]
0000s0sJSON::Schema::Modern::::__ANON__[:53]JSON::Schema::Modern::__ANON__[:53]
0000s0sJSON::Schema::Modern::::__ANON__[:55]JSON::Schema::Modern::__ANON__[:55]
0000s0sJSON::Schema::Modern::::__ANON__[:56]JSON::Schema::Modern::__ANON__[:56]
0000s0sJSON::Schema::Modern::::__ANON__[:696]JSON::Schema::Modern::__ANON__[:696]
0000s0sJSON::Schema::Modern::::__ANON__[:863]JSON::Schema::Modern::__ANON__[:863]
0000s0sJSON::Schema::Modern::::__ANON__[:919]JSON::Schema::Modern::__ANON__[:919]
0000s0sJSON::Schema::Modern::::__ANON__[:923]JSON::Schema::Modern::__ANON__[:923]
0000s0sJSON::Schema::Modern::::__ANON__[:926]JSON::Schema::Modern::__ANON__[:926]
0000s0sJSON::Schema::Modern::::__ANON__[:934]JSON::Schema::Modern::__ANON__[:934]
0000s0sJSON::Schema::Modern::::__ANON__[:936]JSON::Schema::Modern::__ANON__[:936]
0000s0sJSON::Schema::Modern::::__ANON__[:938]JSON::Schema::Modern::__ANON__[:938]
0000s0sJSON::Schema::Modern::::__ANON__[:951]JSON::Schema::Modern::__ANON__[:951]
0000s0sJSON::Schema::Modern::::__ANON__[:956]JSON::Schema::Modern::__ANON__[:956]
0000s0sJSON::Schema::Modern::::__ANON__[:958]JSON::Schema::Modern::__ANON__[:958]
0000s0sJSON::Schema::Modern::::evaluate_json_stringJSON::Schema::Modern::evaluate_json_string
0000s0sJSON::Schema::Modern::::getJSON::Schema::Modern::get
0000s0sJSON::Schema::Modern::::validate_schemaJSON::Schema::Modern::validate_schema
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1225µs230µs
# spent 28µs (26+2) within OpenAPI::Modern::BEGIN@1 which was called: # once (26µs+2µs) by OpenAPI::Modern::BEGIN@26 at line 1
use strict;
# spent 28µs making 1 call to OpenAPI::Modern::BEGIN@1 # spent 2µs making 1 call to strict::import
2262µs294µs
# spent 50µs (6+44) within OpenAPI::Modern::BEGIN@2 which was called: # once (6µs+44µs) by OpenAPI::Modern::BEGIN@26 at line 2
use warnings;
# spent 50µs making 1 call to OpenAPI::Modern::BEGIN@2 # spent 44µs making 1 call to warnings::import
3package JSON::Schema::Modern; # git description: v0.557-9-g7a2a81fa
4# vim: set ts=8 sts=2 sw=2 tw=100 et :
5# ABSTRACT: Validate data against a schema
6# KEYWORDS: JSON Schema validator data validation structure specification
7
811µsour $VERSION = '0.558';
9
10240µs112µs
# spent 12µs within JSON::Schema::Modern::BEGIN@10 which was called: # once (12µs+0s) by OpenAPI::Modern::BEGIN@26 at line 10
use 5.020; # for fc, unicode_strings features
# spent 12µs making 1 call to JSON::Schema::Modern::BEGIN@10
11231µs2530µs
# spent 269µs (8+261) within JSON::Schema::Modern::BEGIN@11 which was called: # once (8µs+261µs) by OpenAPI::Modern::BEGIN@26 at line 11
use Moo;
# spent 269µs making 1 call to JSON::Schema::Modern::BEGIN@11 # spent 261µs making 1 call to Moo::import
12360µs32.38ms
# spent 1.20ms (20µs+1.18) within JSON::Schema::Modern::BEGIN@12 which was called: # once (20µs+1.18ms) by OpenAPI::Modern::BEGIN@26 at line 12
use strictures 2;
# spent 1.20ms making 1 call to JSON::Schema::Modern::BEGIN@12 # spent 1.16ms making 1 call to strictures::import # spent 22µs making 1 call to strictures::VERSION
13254µs2257µs
# spent 134µs (11+123) within JSON::Schema::Modern::BEGIN@13 which was called: # once (11µs+123µs) by OpenAPI::Modern::BEGIN@26 at line 13
use experimental qw(signatures postderef);
# spent 134µs making 1 call to JSON::Schema::Modern::BEGIN@13 # spent 123µs making 1 call to experimental::import
14254µs275µs
# spent 72µs (19+53) within JSON::Schema::Modern::BEGIN@14 which was called: # once (19µs+53µs) by OpenAPI::Modern::BEGIN@26 at line 14
use if "$]" >= 5.022, experimental => 're_strict';
# spent 72µs making 1 call to JSON::Schema::Modern::BEGIN@14 # spent 3µs making 1 call to if::import
15236µs249µs
# spent 44µs (16+28) within JSON::Schema::Modern::BEGIN@15 which was called: # once (16µs+28µs) by OpenAPI::Modern::BEGIN@26 at line 15
no if "$]" >= 5.031009, feature => 'indirect';
# spent 44µs making 1 call to JSON::Schema::Modern::BEGIN@15 # spent 5µs making 1 call to if::unimport
16225µs224µs
# spent 24µs (10+14) within JSON::Schema::Modern::BEGIN@16 which was called: # once (10µs+14µs) by OpenAPI::Modern::BEGIN@26 at line 16
no if "$]" >= 5.033001, feature => 'multidimensional';
# spent 24µs making 1 call to JSON::Schema::Modern::BEGIN@16 # spent 0s making 1 call to if::unimport
17220µs227µs
# spent 26µs (10+16) within JSON::Schema::Modern::BEGIN@17 which was called: # once (10µs+16µs) by OpenAPI::Modern::BEGIN@26 at line 17
no if "$]" >= 5.033006, feature => 'bareword_filehandles';
# spent 26µs making 1 call to JSON::Schema::Modern::BEGIN@17 # spent 1µs making 1 call to if::unimport
182276µs29.24ms
# spent 9.20ms (1.19+8.01) within JSON::Schema::Modern::BEGIN@18 which was called: # once (1.19ms+8.01ms) by OpenAPI::Modern::BEGIN@26 at line 18
use JSON::MaybeXS;
# spent 9.20ms making 1 call to JSON::Schema::Modern::BEGIN@18 # spent 40µs making 1 call to Exporter::import
19237µs246µs
# spent 27µs (8+19) within JSON::Schema::Modern::BEGIN@19 which was called: # once (8µs+19µs) by OpenAPI::Modern::BEGIN@26 at line 19
use Carp qw(croak carp);
# spent 27µs making 1 call to JSON::Schema::Modern::BEGIN@19 # spent 19µs making 1 call to Exporter::import
20346µs393µs
# spent 73µs (20+53) within JSON::Schema::Modern::BEGIN@20 which was called: # once (20µs+53µs) by OpenAPI::Modern::BEGIN@26 at line 20
use List::Util 1.55 qw(pairs first uniqint pairmap uniq any);
# spent 73µs making 1 call to JSON::Schema::Modern::BEGIN@20 # spent 10µs making 1 call to List::Util::import # spent 10µs making 1 call to UNIVERSAL::VERSION
21341µs373µs
# spent 43µs (13+30) within JSON::Schema::Modern::BEGIN@21 which was called: # once (13µs+30µs) by OpenAPI::Modern::BEGIN@26 at line 21
use Ref::Util 0.100 qw(is_ref is_plain_hashref);
# spent 43µs making 1 call to JSON::Schema::Modern::BEGIN@21 # spent 24µs making 1 call to Exporter::import # spent 6µs making 1 call to UNIVERSAL::VERSION
22223µs230µs
# spent 18µs (6+12) within JSON::Schema::Modern::BEGIN@22 which was called: # once (6µs+12µs) by OpenAPI::Modern::BEGIN@26 at line 22
use Scalar::Util 'refaddr';
# spent 18µs making 1 call to JSON::Schema::Modern::BEGIN@22 # spent 12µs making 1 call to Exporter::import
232513µs2164ms
# spent 164ms (2.83+162) within JSON::Schema::Modern::BEGIN@23 which was called: # once (2.83ms+162ms) by OpenAPI::Modern::BEGIN@26 at line 23
use Mojo::URL;
# spent 164ms making 1 call to JSON::Schema::Modern::BEGIN@23 # spent 2µs making 1 call to Mojo::Base::import
24220µs2158µs
# spent 83µs (8+75) within JSON::Schema::Modern::BEGIN@24 which was called: # once (8µs+75µs) by OpenAPI::Modern::BEGIN@26 at line 24
use Safe::Isa;
# spent 83µs making 1 call to JSON::Schema::Modern::BEGIN@24 # spent 75µs making 1 call to Exporter::import
252717µs212.8ms
# spent 12.8ms (9.09+3.71) within JSON::Schema::Modern::BEGIN@25 which was called: # once (9.09ms+3.71ms) by OpenAPI::Modern::BEGIN@26 at line 25
use Path::Tiny;
# spent 12.8ms making 1 call to JSON::Schema::Modern::BEGIN@25 # spent 54µs making 1 call to Exporter::import
26283µs2125µs
# spent 69µs (13+56) within JSON::Schema::Modern::BEGIN@26 which was called: # once (13µs+56µs) by OpenAPI::Modern::BEGIN@26 at line 26
use Storable 'dclone';
# spent 69µs making 1 call to JSON::Schema::Modern::BEGIN@26 # spent 56µs making 1 call to Exporter::import
272753µs225.6ms
# spent 25.6ms (2.88+22.7) within JSON::Schema::Modern::BEGIN@27 which was called: # once (2.88ms+22.7ms) by OpenAPI::Modern::BEGIN@26 at line 27
use File::ShareDir 'dist_dir';
# spent 25.6ms making 1 call to JSON::Schema::Modern::BEGIN@27 # spent 36µs making 1 call to Exporter::import
282610µs22.68ms
# spent 2.66ms (2.38+278µs) within JSON::Schema::Modern::BEGIN@28 which was called: # once (2.38ms+278µs) by OpenAPI::Modern::BEGIN@26 at line 28
use Module::Runtime qw(use_module require_module);
# spent 2.66ms making 1 call to JSON::Schema::Modern::BEGIN@28 # spent 22µs making 1 call to Module::Runtime::import
293586µs313.9ms
# spent 7.43ms (810µs+6.62) within JSON::Schema::Modern::BEGIN@29 which was called: # once (810µs+6.62ms) by OpenAPI::Modern::BEGIN@26 at line 29
use MooX::TypeTiny 0.002002;
# spent 7.43ms making 1 call to JSON::Schema::Modern::BEGIN@29 # spent 6.47ms making 1 call to MooX::TypeTiny::import # spent 11µs making 1 call to UNIVERSAL::VERSION
302619µs21.54ms
# spent 1.45ms (1.26+197µs) within JSON::Schema::Modern::BEGIN@30 which was called: # once (1.26ms+197µs) by OpenAPI::Modern::BEGIN@26 at line 30
use MooX::HandlesVia;
# spent 1.45ms making 1 call to JSON::Schema::Modern::BEGIN@30 # spent 81µs making 1 call to MooX::HandlesVia::import
313620µs379.5ms
# spent 77.1ms (8.18+68.9) within JSON::Schema::Modern::BEGIN@31 which was called: # once (8.18ms+68.9ms) by OpenAPI::Modern::BEGIN@26 at line 31
use Types::Standard 1.016003 qw(Bool Int Str HasMethods Enum InstanceOf HashRef Dict CodeRef Optional Slurpy ArrayRef Undef ClassName Tuple Map);
# spent 77.1ms making 1 call to JSON::Schema::Modern::BEGIN@31 # spent 2.44ms making 1 call to Exporter::Tiny::import # spent 12µs making 1 call to UNIVERSAL::VERSION
32235µs2131µs
# spent 72µs (13+59) within JSON::Schema::Modern::BEGIN@32 which was called: # once (13µs+59µs) by OpenAPI::Modern::BEGIN@26 at line 32
use Feature::Compat::Try;
# spent 72µs making 1 call to JSON::Schema::Modern::BEGIN@32 # spent 59µs making 1 call to Feature::Compat::Try::import
332506µs271.5ms
# spent 71.5ms (1.66+69.9) within JSON::Schema::Modern::BEGIN@33 which was called: # once (1.66ms+69.9ms) by OpenAPI::Modern::BEGIN@26 at line 33
use JSON::Schema::Modern::Error;
# spent 71.5ms making 1 call to JSON::Schema::Modern::BEGIN@33 # spent 0s making 1 call to JSON::Schema::Modern::__ANON__
342579µs236.6ms
# spent 36.6ms (2.75+33.8) within JSON::Schema::Modern::BEGIN@34 which was called: # once (2.75ms+33.8ms) by OpenAPI::Modern::BEGIN@26 at line 34
use JSON::Schema::Modern::Result;
# spent 36.6ms making 1 call to JSON::Schema::Modern::BEGIN@34 # spent 1µs making 1 call to JSON::Schema::Modern::__ANON__
352560µs254.7ms
# spent 54.7ms (2.32+52.3) within JSON::Schema::Modern::BEGIN@35 which was called: # once (2.32ms+52.3ms) by OpenAPI::Modern::BEGIN@26 at line 35
use JSON::Schema::Modern::Document;
# spent 54.7ms making 1 call to JSON::Schema::Modern::BEGIN@35 # spent 4µs making 1 call to Mojo::Base::import
362647µs25.51ms
# spent 5.45ms (3.64+1.81) within JSON::Schema::Modern::BEGIN@36 which was called: # once (3.64ms+1.81ms) by OpenAPI::Modern::BEGIN@26 at line 36
use JSON::Schema::Modern::Utilities qw(get_type canonical_uri E abort annotate_self);
# spent 5.45ms making 1 call to JSON::Schema::Modern::BEGIN@36 # spent 59µs making 1 call to Exporter::import
37235µs2719µs
# spent 363µs (7+356) within JSON::Schema::Modern::BEGIN@37 which was called: # once (7µs+356µs) by OpenAPI::Modern::BEGIN@26 at line 37
use namespace::clean;
# spent 363µs making 1 call to JSON::Schema::Modern::BEGIN@37 # spent 356µs making 1 call to namespace::clean::import
38
3913µsour @CARP_NOT = qw(
40 JSON::Schema::Modern::Document
41 JSON::Schema::Modern::Vocabulary
42 JSON::Schema::Modern::Vocabulary::Applicator
43 OpenAPI::Modern
44);
45
46225µs273µs
# spent 40µs (7+33) within JSON::Schema::Modern::BEGIN@46 which was called: # once (7µs+33µs) by OpenAPI::Modern::BEGIN@26 at line 46
use constant SPECIFICATION_VERSION_DEFAULT => 'draft2020-12';
# spent 40µs making 1 call to JSON::Schema::Modern::BEGIN@46 # spent 33µs making 1 call to constant::import
4725.32ms234µs
# spent 19µs (4+15) within JSON::Schema::Modern::BEGIN@47 which was called: # once (4µs+15µs) by OpenAPI::Modern::BEGIN@26 at line 47
use constant SPECIFICATION_VERSIONS_SUPPORTED => [qw(draft7 draft2019-09 draft2020-12)];
# spent 19µs making 1 call to JSON::Schema::Modern::BEGIN@47 # spent 15µs making 1 call to constant::import
48
49has specification_version => (
50 is => 'ro',
51 isa => Enum(SPECIFICATION_VERSIONS_SUPPORTED),
52 coerce => sub {
53 return $_[0] if any { $_[0] eq $_ } SPECIFICATION_VERSIONS_SUPPORTED->@*;
54 my $real = 'draft'.($_[0]//'');
55 (any { $real eq $_ } SPECIFICATION_VERSIONS_SUPPORTED->@*) ? $real : $_[0];
56 },
57110µs22.26ms);
# spent 1.33ms making 1 call to MooX::HandlesVia::has # spent 925µs making 1 call to Types::Standard::Enum
58
59125µs3768µshas output_format => (
# spent 570µs making 1 call to MooX::HandlesVia::has # spent 197µs making 1 call to Types::Standard::Enum # spent 1µs making 1 call to JSON::Schema::Modern::Result::OUTPUT_FORMATS
60 is => 'ro',
61 isa => Enum(JSON::Schema::Modern::Result->OUTPUT_FORMATS),
62 default => 'basic',
63);
64
65has short_circuit => (
66 is => 'ro',
67 isa => Bool,
68 lazy => 1,
6913µs12µs
# spent 6µs (4+2) within JSON::Schema::Modern::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/JSON/Schema/Modern.pm:69] which was called: # once (4µs+2µs) by JSON::Schema::Modern::short_circuit at line 23 of (eval 316)[Sub/Quote.pm:3]
default => sub { $_[0]->output_format eq 'flag' && !$_[0]->collect_annotations },
# spent 2µs making 1 call to JSON::Schema::Modern::output_format
7017µs2987µs);
# spent 985µs making 1 call to MooX::HandlesVia::has # spent 2µs making 1 call to Types::Standard::Bool
71
7214µs2665µshas max_traversal_depth => (
# spent 662µs making 1 call to MooX::HandlesVia::has # spent 3µs making 1 call to Types::Standard::Int
73 is => 'ro',
74 isa => Int,
75 default => 50,
76);
77
7813µs2629µshas validate_formats => (
# spent 627µs making 1 call to MooX::HandlesVia::has # spent 2µs making 1 call to Types::Standard::Bool
79 is => 'ro',
80 isa => Bool,
81 default => 0, # as specified by https://json-schema.org/draft/<version>/schema#/$vocabulary
82);
83
84has validate_content_schemas => (
85 is => 'ro',
86 isa => Bool,
87 lazy => 1,
88 # defaults to false in latest versions, as specified by
89 # https://json-schema.org/draft/2020-12/json-schema-validation.html#rfc.section.8.2
9014µs12µs
# spent 6µs (4+2) within JSON::Schema::Modern::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/JSON/Schema/Modern.pm:90] which was called: # once (4µs+2µs) by JSON::Schema::Modern::validate_content_schemas at line 23 of (eval 319)[Sub/Quote.pm:3]
default => sub { ($_[0]->specification_version//'') eq 'draft7' },
# spent 2µs making 1 call to JSON::Schema::Modern::specification_version
9118µs21.58ms);
# spent 1.58ms making 1 call to MooX::HandlesVia::has # spent 2µs making 1 call to Types::Standard::Bool
92
9315µs2649µshas collect_annotations => (
# spent 645µs making 1 call to MooX::HandlesVia::has # spent 4µs making 1 call to Types::Standard::Bool
94 is => 'ro',
95 isa => Bool,
96);
97
9814µs2619µshas scalarref_booleans => (
# spent 617µs making 1 call to MooX::HandlesVia::has # spent 2µs making 1 call to Types::Standard::Bool
99 is => 'ro',
100 isa => Bool,
101);
102
10314µs2517µshas strict => (
# spent 515µs making 1 call to MooX::HandlesVia::has # spent 2µs making 1 call to Types::Standard::Bool
104 is => 'ro',
105 isa => Bool,
106);
107
108has _format_validations => (
109 is => 'bare',
110 isa => my $format_type = Dict[
111 (map +($_ => Optional[CodeRef]), qw(date-time date time duration email idn-email hostname idn-hostname ipv4 ipv6 uri uri-reference iri iri-reference uuid uri-template json-pointer relative-json-pointer regex)),
112 Slurpy[HashRef[Dict[type => Enum[qw(null object array boolean string number integer)], sub => CodeRef]]],
113 ],
114 init_arg => 'format_validations',
115 handles_via => 'Hash',
116 handles => {
117 _get_format_validation => 'get',
118 add_format_validation => 'set',
119 },
120 lazy => 1,
12113µs
# spent 1µs within JSON::Schema::Modern::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/JSON/Schema/Modern.pm:121] which was called: # once (1µs+0s) by JSON::Schema::Modern::_assert__format_validations at line 23 of (eval 329)[Sub/Quote.pm:3]
default => sub { {} },
122174µs4524.2ms);
# spent 9.27ms making 2 calls to Types::Standard::Dict, avg 4.64ms/call # spent 8.49ms making 1 call to MooX::HandlesVia::has # spent 2.45ms making 1 call to Types::Standard::Slurpy # spent 1.49ms making 1 call to Types::Standard::HashRef # spent 1.32ms making 19 calls to Types::Standard::Optional, avg 70µs/call # spent 1.20ms making 1 call to Types::Standard::Enum # spent 15µs making 20 calls to Types::Standard::CodeRef, avg 750ns/call
123
124595µs171.18ms
# spent 1.10ms (47µs+1.05) within JSON::Schema::Modern::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/JSON/Schema/Modern.pm:124] which was called: # once (47µs+1.05ms) by JSON::Schema::Modern::add_format_validation at line 4 of (eval 331)[Class/Method/Modifiers.pm:148]
before add_format_validation => sub ($self, @kvs) { $format_type->({ @$_ }) foreach pairs @kvs };
# spent 982µs making 5 calls to Sub::Defer::__ANON__[Sub/Defer.pm:178], avg 196µs/call # spent 151µs making 1 call to Moo::before # spent 40µs making 10 calls to Type::Tiny::__ANON__[Type/Tiny.pm:89], avg 4µs/call # spent 5µs making 1 call to List::Util::pairs
125
12642µs
# spent 13µs (10+3) within JSON::Schema::Modern::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/JSON/Schema/Modern.pm:133] which was called: # once (10µs+3µs) by JSON::Schema::Modern::__ANON__[(eval 333)[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Class/Method/Modifiers.pm:89]:1] at line 1 of (eval 333)[Class/Method/Modifiers.pm:89]
around BUILDARGS => sub ($orig, $class, @args) {
12713µs13µs my $args = $class->$orig(@args);
# spent 3µs making 1 call to Moo::Object::BUILDARGS
128 croak 'output_format: strict_basic can only be used with specification_version: draft2019-09'
129 if ($args->{output_format}//'') eq 'strict_basic'
13012µs and ($args->{specification_version}//'') ne 'draft2019-09';
131
132126µs return $args;
13313µs1140µs};
# spent 140µs making 1 call to Moo::around
134
135
# spent 134ms (1.11+133) within JSON::Schema::Modern::add_schema which was called 9 times, avg 14.9ms/call: # 6 times (775µs+124ms) by JSON::Schema::Modern::Document::OpenAPI::_add_vocab_and_default_schemas at line 204 of JSON/Schema/Modern/Document/OpenAPI.pm, avg 20.7ms/call # 2 times (152µs+1.71ms) by JSON::Schema::Modern::Document::OpenAPI::_add_vocab_and_default_schemas at line 206 of JSON/Schema/Modern/Document/OpenAPI.pm, avg 933µs/call # once (185µs+7.72ms) by OpenAPI::Modern::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/OpenAPI/Modern.pm:79] at line 75 of OpenAPI/Modern.pm
sub add_schema {
13696µs croak 'insufficient arguments' if @_ < 2;
13795µs my $self = shift;
138
139 # TODO: resolve $uri against $self->base_uri
140941µs10661µs my $uri = !is_ref($_[0]) ? Mojo::URL->new(shift)
# spent 643µs making 9 calls to Mojo::URL::new, avg 71µs/call # spent 18µs making 1 call to Safe::Isa::__ANON__[Safe/Isa.pm:23]
141 : $_[0]->$_isa('Mojo::URL') ? shift : Mojo::URL->new;
142
14397µs910µs croak 'cannot add a schema with a uri with a fragment' if defined $uri->fragment;
# spent 10µs making 9 calls to Mojo::URL::fragment, avg 1µs/call
144
14596µs if (not @_) {
146 my $schema_info = $self->_fetch_from_uri($uri);
147 return if not $schema_info or not defined wantarray;
148 return $schema_info->{document};
149 }
150
151 # document BUILD will trigger $self->traverse($schema)
152972µs2135.0ms my $document = $_[0]->$_isa('JSON::Schema::Modern::Document') ? shift
# spent 34.9ms making 6 calls to JSON::Schema::Modern::Document::new, avg 5.82ms/call # spent 92µs making 9 calls to Safe::Isa::__ANON__[Safe/Isa.pm:23], avg 10µs/call # spent 9µs making 6 calls to Mojo::URL::__ANON__[Mojo/URL.pm:3], avg 2µs/call
153 : JSON::Schema::Modern::Document->new(
154 schema => shift,
155 $uri ? (canonical_uri => $uri) : (),
156 evaluator => $self, # used mainly for traversal during document construction
157 );
158
159926µs9226µs if ($document->has_errors) {
# spent 226µs making 9 calls to JSON::Schema::Modern::Document::has_errors, avg 25µs/call
160 my $result = JSON::Schema::Modern::Result->new(
161 output_format => $self->output_format,
162 valid => 0,
163 errors => [ $document->errors ],
164 exception => 1,
165 );
166 die $result;
167 }
168
1699411µs189215µs if (not grep refaddr($_->{document}) == refaddr($document), $self->_canonical_resources) {
# spent 172µs making 9 calls to JSON::Schema::Modern::_canonical_resources, avg 19µs/call # spent 43µs making 180 calls to Scalar::Util::refaddr, avg 239ns/call
17076.88ms356.89ms my $schema_content = $document->_serialized_schema
# spent 6.75ms making 7 calls to Cpanel::JSON::XS::encode, avg 965µs/call # spent 100µs making 14 calls to JSON::Schema::Modern::Document::_serialized_schema, avg 7µs/call # spent 22µs making 7 calls to JSON::Schema::Modern::_json_decoder, avg 3µs/call # spent 13µs making 7 calls to JSON::Schema::Modern::Document::schema, avg 2µs/call
171 // $document->_serialized_schema($self->_json_decoder->encode($document->schema));
172
1737159µs21431µs if (my $existing_doc = first {
# spent 265µs making 7 calls to List::Util::first, avg 38µs/call # spent 116µs making 7 calls to JSON::Schema::Modern::_canonical_resources, avg 17µs/call # spent 50µs making 7 calls to List::Util::uniqint, avg 7µs/call
17429137µs61156µs my $existing_content = $_->_serialized_schema
# spent 92µs making 8 calls to Cpanel::JSON::XS::encode, avg 12µs/call # spent 53µs making 37 calls to JSON::Schema::Modern::Document::_serialized_schema, avg 1µs/call # spent 7µs making 8 calls to JSON::Schema::Modern::Document::schema, avg 875ns/call # spent 4µs making 8 calls to JSON::Schema::Modern::_json_decoder, avg 500ns/call
175 // $_->_serialized_schema($self->_json_decoder->encode($_->schema));
1762924µs $existing_content eq $schema_content
177 } uniqint map $_->{document}, $self->_canonical_resources) {
178 # we already have this schema content in another document object.
179 $document = $existing_doc;
180 }
181 else {
182774µs149.21ms $self->_add_resources(map +($_->[0] => +{ $_->[1]->%*, document => $document }),
# spent 9.08ms making 7 calls to JSON::Schema::Modern::_add_resources, avg 1.30ms/call # spent 133µs making 7 calls to JSON::Schema::Modern::Document::resource_pairs, avg 19µs/call
183 $document->resource_pairs);
184 }
185 }
186
187966µs91.09ms if ("$uri") {
# spent 1.09ms making 9 calls to Mojo::URL::__ANON__[Mojo/URL.pm:3], avg 121µs/call
188822µs16856µs my $resource = $document->_get_resource($document->canonical_uri);
# spent 843µs making 8 calls to JSON::Schema::Modern::Document::_get_resource, avg 105µs/call # spent 13µs making 8 calls to JSON::Schema::Modern::Document::canonical_uri, avg 2µs/call
189 $self->_add_resources($uri => {
190 path => '',
191 canonical_uri => $document->canonical_uri,
192 specification_version => $resource->{specification_version},
193 vocabularies => $resource->{vocabularies}, # reference, not copy
194 document => $document,
195 configs => $resource->{configs},
196850µs164.41ms });
# spent 4.37ms making 8 calls to JSON::Schema::Modern::_add_resources, avg 546µs/call # spent 34µs making 8 calls to JSON::Schema::Modern::Document::canonical_uri, avg 4µs/call
197 }
198
199943µs return $document;
200}
201
202sub evaluate_json_string ($self, $json_data, $schema, $config_override = {}) {
203 croak 'evaluate_json_string called in void context' if not defined wantarray;
204
205 my $data;
206 try {
207 $data = $self->_json_decoder->decode($json_data)
208 }
209 catch ($e) {
210 return JSON::Schema::Modern::Result->new(
211 output_format => $self->output_format,
212 valid => 0,
213 exception => 1,
214 errors => [
215 JSON::Schema::Modern::Error->new(
216 keyword => undef,
217 instance_location => '',
218 keyword_location => '',
219 error => $e,
220 )
221 ],
222 );
223 }
224
225 return $self->evaluate($data, $schema, $config_override);
226}
227
228# this is called whenever we need to walk a document for something.
229# for now it is just called when a ::Document object is created, to verify the integrity of the
230# schema structure, to identify the metaschema (via the $schema keyword), and to extract all
231# embedded resources via $id and $anchor keywords within.
232# Returns the internal $state object accumulated during the traversal.
2332972837µs
# spent 1.23s (30.0ms+1.20) within JSON::Schema::Modern::traverse which was called 743 times, avg 1.65ms/call: # 727 times (29.1ms+1.07s) by JSON::Schema::Modern::Document::OpenAPI::_traverse_schema at line 218 of JSON/Schema/Modern/Document/OpenAPI.pm, avg 1.52ms/call # 14 times (824µs+123ms) by JSON::Schema::Modern::Document::traverse at line 178 of JSON/Schema/Modern/Document.pm, avg 8.85ms/call # once (30µs+2.62ms) by JSON::Schema::Modern::Document::OpenAPI::traverse at line 115 of JSON/Schema/Modern/Document/OpenAPI.pm # once (77µs+-77µs) by JSON::Schema::Modern::_get_metaschema_info at line 754
sub traverse ($self, $schema_reference, $config_override = {}) {
234 # Note: the starting position is not guaranteed to be at the root of the $document.
2357431.53ms743253ms my $initial_uri = Mojo::URL->new($config_override->{initial_schema_uri} // '');
# spent 253ms making 743 calls to Mojo::URL::new, avg 340µs/call
236743732µs my $initial_path = $config_override->{traversed_schema_path} // '';
2377432.68ms7431.90ms my $spec_version = $self->specification_version//SPECIFICATION_VERSION_DEFAULT;
# spent 1.90ms making 743 calls to JSON::Schema::Modern::specification_version, avg 3µs/call
238
239 my $state = {
240 depth => 0,
241 data_path => '', # this never changes since we don't have an instance yet
242 initial_schema_uri => $initial_uri, # the canonical URI as of the start of this method, or last $id
243 traversed_schema_path => $initial_path, # the accumulated traversal path as of the start, or last $id
244 schema_path => '', # the rest of the path, since the start of this method, or last $id
245 effective_base_uri => Mojo::URL->new(''),
246 errors => [],
247 identifiers => [],
248 configs => {},
249 callbacks => $config_override->{callbacks} // {},
2507435.65ms74385.6ms evaluator => $self,
# spent 85.6ms making 743 calls to Mojo::URL::new, avg 115µs/call
251 traverse => 1,
252 };
253
254743497µs try {
255 my $for_canonical_uri = Mojo::URL->new(
256 (is_plain_hashref($schema_reference) && exists $schema_reference->{'$id'}
257 ? Mojo::URL->new($schema_reference->{'$id'}) : undef)
2587431.96ms757180ms // $state->{initial_schema_uri});
# spent 180ms making 757 calls to Mojo::URL::new, avg 237µs/call
2597431.15ms758420µs $for_canonical_uri->fragment(undef) if not length $for_canonical_uri->fragment;
# spent 420µs making 758 calls to Mojo::URL::fragment, avg 554ns/call
260
261 # a subsequent "$schema" keyword can still change these values
262 $state->@{qw(spec_version vocabularies)} = $self->_get_metaschema_info(
2637435.39ms758109ms $config_override->{metaschema_uri} // $self->METASCHEMA_URIS->{$spec_version},
# spent 109ms making 743 calls to JSON::Schema::Modern::_get_metaschema_info, avg 146µs/call, recursion: max depth 1, sum of overlapping time 79µs # spent 22µs making 15 calls to JSON::Schema::Modern::METASCHEMA_URIS, avg 1µs/call
264 $for_canonical_uri,
265 );
266 }
267 catch ($e) {
268 if ($e->$_isa('JSON::Schema::Modern::Result')) {
269 push $state->{errors}->@*, $e->errors;
270 }
271 elsif ($e->$_isa('JSON::Schema::Modern::Error')) {
272 push $state->{errors}->@*, $e;
273 }
274 else {
275 ()= E({ %$state, exception => 1 }, 'EXCEPTION: '.$e);
276 }
277
278 return $state;
279 }
280
281743344µs try {
2827432.43ms743573ms $self->_traverse_subschema($schema_reference, $state);
# spent 573ms making 743 calls to JSON::Schema::Modern::_traverse_subschema, avg 771µs/call
283 }
284 catch ($e) {
285 if ($e->$_isa('JSON::Schema::Modern::Error')) {
286 # note: we should never be here, since traversal subs are no longer be fatal
287 push $state->{errors}->@*, $e;
288 }
289 else {
290 E({ %$state, exception => 1 }, 'EXCEPTION: '.$e);
291 }
292 }
293
294743401µs delete $state->{traverse};
2957432.26ms return $state;
296}
297
298# the actual runtime evaluation of the schema against input data.
29952µs
# spent 87.5s (307ms+87.2) within JSON::Schema::Modern::evaluate which was called: # once (307ms+87.2s) by JSON::Schema::Modern::Document::OpenAPI::traverse at line 147 of JSON/Schema/Modern/Document/OpenAPI.pm
sub evaluate ($self, $data, $schema_reference, $config_override = {}) {
30010s croak 'evaluate called in void context' if not defined wantarray;
301
30211µs my $initial_path = $config_override->{traversed_schema_path} // '';
30311µs170µs my $effective_base_uri = Mojo::URL->new($config_override->{effective_base_uri}//'');
# spent 70µs making 1 call to Mojo::URL::new
304
305 my $state = {
30613µs11µs data_path => $config_override->{data_path} // '',
# spent 1µs making 1 call to Mojo::URL::new
307 traversed_schema_path => $initial_path, # the accumulated path as of the start of evaluation, or last $id or $ref
308 initial_schema_uri => Mojo::URL->new, # the canonical URI as of the start of evaluation, or last $id or $ref
309 schema_path => '', # the rest of the path, since the start of evaluation, or last $id or $ref
310 effective_base_uri => $effective_base_uri, # resolve locations against this for errors and annotations
311 errors => [],
312 };
313
314 exists $config_override->{$_} and die $_.' not supported as a config override'
31511µs foreach qw(output_format specification_version);
316
31711µs my $valid;
31810s try {
31911µs my $schema_info;
320
32111µs18µs if (not is_ref($schema_reference) or $schema_reference->$_isa('Mojo::URL')) {
# spent 8µs making 1 call to Safe::Isa::__ANON__[Safe/Isa.pm:23]
32211µs1254µs $schema_info = $self->_fetch_from_uri($schema_reference);
# spent 254µs making 1 call to JSON::Schema::Modern::_fetch_from_uri
32311µs169µs $state->{initial_schema_uri} = Mojo::URL->new($config_override->{initial_schema_uri} // '');
# spent 69µs making 1 call to Mojo::URL::new
324 }
325 else {
326 # traverse is called via add_schema -> ::Document->new -> ::Document->BUILD
327 my $document = $self->add_schema('', $schema_reference);
328 my $base_resource = $document->_get_resource($document->canonical_uri)
329 || croak "couldn't get resource: document parse error";
330
331 $schema_info = {
332 schema => $document->schema,
333 document => $document,
334 document_path => '',
335 $base_resource->%{qw(canonical_uri specification_version vocabularies configs)},
336 };
337 }
338
33911µs abort($state, 'EXCEPTION: unable to find resource %s', $schema_reference)
340 if not $schema_info;
341
342 $state = +{
343 %$state,
344 depth => 0,
345 initial_schema_uri => $schema_info->{canonical_uri}, # the canonical URI as of the start of evaluation, or last $id or $ref
346 document => $schema_info->{document}, # the ::Document object containing this schema
347 document_path => $schema_info->{document_path}, # the path within the document of this schema, as of the start of evaluation, or last $id or $ref
348 dynamic_scope => [ $schema_info->{canonical_uri} ],
349 annotations => [],
350 seen => {},
351 spec_version => $schema_info->{specification_version},
352 vocabularies => $schema_info->{vocabularies},
353 callbacks => $config_override->{callbacks} // {},
354 evaluator => $self,
355 $schema_info->{configs}->%*,
356 (map {
357721µs631µs my $val = $config_override->{$_} // $self->$_;
# spent 13µs making 1 call to JSON::Schema::Modern::validate_content_schemas # spent 12µs making 1 call to JSON::Schema::Modern::short_circuit # spent 3µs making 1 call to JSON::Schema::Modern::validate_formats # spent 2µs making 1 call to JSON::Schema::Modern::collect_annotations # spent 1µs making 1 call to JSON::Schema::Modern::scalarref_booleans # spent 0s making 1 call to JSON::Schema::Modern::strict
35860s defined $val ? ( $_ => $val ) : ()
359 } qw(validate_formats validate_content_schemas short_circuit collect_annotations scalarref_booleans strict)),
360 };
361
36210s if ($state->{validate_formats}) {
363 $state->{vocabularies} = [
364 map s/^JSON::Schema::Modern::Vocabulary::Format\KAnnotation$/Assertion/r, $state->{vocabularies}->@*
365110µs75µs ];
# spent 5µs making 7 calls to JSON::Schema::Modern::CORE:subst, avg 714ns/call
36611µs require JSON::Schema::Modern::Vocabulary::FormatAssertion;
367 }
368
36913µs187.2s $valid = $self->_eval_subschema($data, $schema_info->{schema}, $state);
# spent 87.2s making 1 call to JSON::Schema::Modern::_eval_subschema
370121µs warn 'result is false but there are no errors' if not $valid and not $state->{errors}->@*;
371 }
372 catch ($e) {
373 if ($e->$_isa('JSON::Schema::Modern::Result')) {
374 return $e;
375 }
376 elsif ($e->$_isa('JSON::Schema::Modern::Error')) {
377 push $state->{errors}->@*, $e;
378 }
379 else {
380 $valid = E({ %$state, exception => 1 }, 'EXCEPTION: '.$e);
381 }
382 }
383
38412µs die 'evaluate validity inconstent with error count' if $valid xor !$state->{errors}->@*;
385
386 return JSON::Schema::Modern::Result->new(
387 output_format => $self->output_format,
388 valid => $valid,
389 $valid
390 # strip annotations from result if user didn't explicitly ask for them
391 ? ($config_override->{collect_annotations} // $self->collect_annotations
392 ? (annotations => $state->{annotations}) : ())
3931307ms33.32ms : (errors => $state->{errors}),
# spent 3.31ms making 1 call to JSON::Schema::Modern::Result::new # spent 7µs making 1 call to JSON::Schema::Modern::output_format # spent 3µs making 1 call to JSON::Schema::Modern::collect_annotations
394 );
395}
396
397sub validate_schema ($self, $schema, $config_override = {}) {
398 croak 'validate_schema called in void context' if not defined wantarray;
399
400 my $metaschema_uri = is_plain_hashref($schema) && $schema->{'$schema'} ? $schema->{'$schema'}
401 : $self->METASCHEMA_URIS->{$self->specification_version // $self->SPECIFICATION_VERSION_DEFAULT};
402
403 return $self->evaluate($schema, $metaschema_uri, $config_override);
404}
405
406sub get ($self, $uri) {
407 my $schema_info = $self->_fetch_from_uri($uri);
408 return if not $schema_info;
409 my $subschema = is_ref($schema_info->{schema}) ? dclone($schema_info->{schema}) : $schema_info->{schema};
410 return wantarray ? ($subschema, $schema_info->{canonical_uri}) : $subschema;
411}
412
413# defined lower down:
414# sub add_vocabulary { ... }
415# sub add_encoding { ... }
416# sub add_media_type { ... }
417
418######## NO PUBLIC INTERFACES FOLLOW THIS POINT ########
419
420# current spec version => { keyword => undef, or arrayref of alternatives }
42118µsmy %removed_keywords = (
422 'draft7' => {
423 id => [ '$id' ],
424 },
425 'draft2019-09' => {
426 id => [ '$id' ],
427 definitions => [ '$defs' ],
428 dependencies => [ qw(dependentSchemas dependentRequired) ],
429 },
430 'draft2020-12' => {
431 id => [ '$id' ],
432 definitions => [ '$defs' ],
433 dependencies => [ qw(dependentSchemas dependentRequired) ],
434 '$recursiveAnchor' => [ '$dynamicAnchor' ],
435 '$recursiveRef' => [ '$dynamicRef' ],
436 additionalItems => [ 'items' ],
437 },
438);
439
440# {
441# $spec_version => {
442# $vocabulary_class => {
443# traverse => [ [ $keyword => $subref ], [ ... ] ],
444# evaluate => [ [ $keyword => $subref ], [ ... ] ],
445# }
446# }
447# }
448# If we could serialize coderefs, this could be an object attribute;
449# otherwise, we might as well persist this for the lifetime of the process.
45011µsour $vocabulary_cache = {};
451
452114522.21ms
# spent 573ms (174+398) within JSON::Schema::Modern::_traverse_subschema which was called 2863 times, avg 200µs/call: # 1349 times (75.2ms+-75.2ms) by JSON::Schema::Modern::Vocabulary::traverse_object_schemas at line 55 of JSON/Schema/Modern/Vocabulary.pm, avg 0s/call # 743 times (67.2ms+506ms) by JSON::Schema::Modern::traverse at line 282, avg 771µs/call # 562 times (21.0ms+-21.0ms) by JSON::Schema::Modern::Vocabulary::traverse_subschema at line 34 of JSON/Schema/Modern/Vocabulary.pm, avg 0s/call # 203 times (10.8ms+-10.8ms) by JSON::Schema::Modern::Vocabulary::traverse_array_schemas at line 44 of JSON/Schema/Modern/Vocabulary.pm, avg 0s/call # 6 times (195µs+-195µs) by JSON::Schema::Modern::Vocabulary::traverse_property_schema at line 64 of JSON/Schema/Modern/Vocabulary.pm, avg 0s/call
sub _traverse_subschema ($self, $schema, $state) {
45328631.12ms delete $state->{keyword};
454
455 return E($state, 'EXCEPTION: maximum traversal depth exceeded')
45628634.13ms28633.33ms if $state->{depth}++ > $self->max_traversal_depth;
# spent 3.33ms making 2863 calls to JSON::Schema::Modern::max_traversal_depth, avg 1µs/call
457
45828633.90ms28638.79ms my $schema_type = get_type($schema);
# spent 8.79ms making 2863 calls to JSON::Schema::Modern::Utilities::get_type, avg 3µs/call
45928631.25ms return 1 if $schema_type eq 'boolean';
460
4612491494µs return E($state, 'invalid schema type: %s', $schema_type) if $schema_type ne 'object';
462
46324911.23ms return 1 if not keys %$schema;
464
4652488415µs my $valid = 1;
46624888.47ms my %unknown_keywords = map +($_ => undef), keys %$schema;
467 # we must check the array length on every iteration because some keywords can change it!
468248810.4ms for (my $idx = 0; $idx <= $state->{vocabularies}->$#*; ++$idx) {
469194346.00ms my $vocabulary = $state->{vocabularies}[$idx];
470
471 # [ [ $keyword => $subref ], [ ... ] ]
472 my $keyword_list = $vocabulary_cache->{$state->{spec_version}}{$vocabulary}{traverse} //= [
473 map [ $_ => $vocabulary->can('_traverse_keyword_'.($_ =~ s/^\$//r)) ],
474 $vocabulary->keywords($state->{spec_version})
4751943411.4ms130161µs ];
# spent 75µs making 61 calls to UNIVERSAL::can, avg 1µs/call # spent 40µs making 1 call to JSON::Schema::Modern::Vocabulary::Applicator::keywords # spent 16µs making 61 calls to JSON::Schema::Modern::CORE:subst, avg 262ns/call # spent 8µs making 1 call to JSON::Schema::Modern::Vocabulary::Validation::keywords # spent 5µs making 1 call to JSON::Schema::Modern::Vocabulary::Core::keywords # spent 5µs making 1 call to JSON::Schema::Modern::Vocabulary::Unevaluated::keywords # spent 4µs making 1 call to JSON::Schema::Modern::Vocabulary::Content::keywords # spent 3µs making 1 call to JSON::Schema::Modern::Vocabulary::MetaData::keywords # spent 3µs making 1 call to JSON::Schema::Modern::Vocabulary::OpenAPI::keywords # spent 2µs making 1 call to JSON::Schema::Modern::Vocabulary::FormatAnnotation::keywords
476
4771943423.4ms foreach my $keyword_tuple ($keyword_list->@*) {
47814988834.2ms my ($keyword, $sub) = $keyword_tuple->@*;
47914988823.7ms next if not exists $schema->{$keyword};
480
481 # keywords adjacent to $ref are not evaluated before draft2019-09
48243881.57ms next if $keyword ne '$ref' and exists $schema->{'$ref'} and $state->{spec_version} eq 'draft7';
483
48443881.22ms delete $unknown_keywords{$keyword};
48543881.45ms $state->{keyword} = $keyword;
486
48743887.86ms4388925ms if (not $sub->($vocabulary, $schema, $state)) {
# spent 319ms making 387 calls to JSON::Schema::Modern::Vocabulary::Applicator::_traverse_keyword_properties, avg 824µs/call, recursion: max depth 3, sum of overlapping time 27.7ms # spent 169ms making 710 calls to JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_ref, avg 237µs/call # spent 94.8ms making 98 calls to JSON::Schema::Modern::Vocabulary::Applicator::_traverse_keyword_items, avg 968µs/call, recursion: max depth 1, sum of overlapping time 4.14ms # spent 81.0ms making 275 calls to JSON::Schema::Modern::Vocabulary::Validation::_traverse_keyword_required, avg 295µs/call # spent 79.4ms making 12 calls to JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_defs, avg 6.61ms/call, recursion: max depth 1, sum of overlapping time 9.78ms # spent 40.8ms making 1382 calls to JSON::Schema::Modern::Vocabulary::Validation::_traverse_keyword_type, avg 30µs/call # spent 34.9ms making 130 calls to JSON::Schema::Modern::Vocabulary::Applicator::_traverse_keyword_additionalProperties, avg 268µs/call, recursion: max depth 1, sum of overlapping time 6.53ms # spent 22.3ms making 23 calls to JSON::Schema::Modern::Vocabulary::Applicator::_traverse_keyword_allOf, avg 970µs/call # spent 19.4ms making 65 calls to JSON::Schema::Modern::Vocabulary::Applicator::_traverse_keyword_then, avg 299µs/call # spent 15.2ms making 32 calls to JSON::Schema::Modern::Vocabulary::Applicator::_traverse_keyword_anyOf, avg 475µs/call, recursion: max depth 1, sum of overlapping time 137µs # spent 12.6ms making 21 calls to JSON::Schema::Modern::Vocabulary::Applicator::_traverse_keyword_oneOf, avg 602µs/call # spent 11.9ms making 65 calls to JSON::Schema::Modern::Vocabulary::Applicator::_traverse_keyword_if, avg 183µs/call # spent 7.44ms making 3 calls to JSON::Schema::Modern::Vocabulary::Applicator::_traverse_keyword_dependentSchemas, avg 2.48ms/call # spent 6.96ms making 3 calls to JSON::Schema::Modern::Vocabulary::Applicator::_traverse_keyword_contains, avg 2.32ms/call # spent 6.46ms making 156 calls to JSON::Schema::Modern::Vocabulary::Unevaluated::_traverse_keyword_unevaluatedProperties, avg 41µs/call # spent 6.15ms making 22 calls to JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_dynamicRef, avg 280µs/call # spent 5.89ms making 14 calls to JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_id, avg 421µs/call # spent 5.26ms making 11 calls to JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_vocabulary, avg 478µs/call # spent 4.39ms making 15 calls to JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_schema, avg 292µs/call # spent 4.37ms making 69 calls to JSON::Schema::Modern::Vocabulary::Validation::_traverse_keyword_pattern, avg 63µs/call # spent 3.91ms making 14 calls to JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_dynamicAnchor, avg 279µs/call # spent 3.71ms making 14 calls to JSON::Schema::Modern::Vocabulary::Applicator::_traverse_keyword_propertyNames, avg 265µs/call # spent 3.05ms making 15 calls to JSON::Schema::Modern::Vocabulary::Applicator::_traverse_keyword_else, avg 204µs/call # spent 2.86ms making 135 calls to JSON::Schema::Modern::Vocabulary::MetaData::_traverse_keyword_readOnly, avg 21µs/call # spent 2.38ms making 118 calls to JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_comment, avg 20µs/call # spent 1.78ms making 15 calls to JSON::Schema::Modern::Vocabulary::Applicator::_traverse_keyword_not, avg 118µs/call # spent 1.75ms making 97 calls to JSON::Schema::Modern::Vocabulary::MetaData::_traverse_keyword_description, avg 18µs/call # spent 1.28ms making 6 calls to JSON::Schema::Modern::Vocabulary::Applicator::_traverse_keyword_patternProperties, avg 213µs/call # spent 1.25ms making 50 calls to JSON::Schema::Modern::Vocabulary::Validation::_traverse_keyword_minProperties, avg 25µs/call # spent 639µs making 50 calls to JSON::Schema::Modern::Vocabulary::FormatAnnotation::_traverse_keyword_format, avg 13µs/call # spent 620µs making 60 calls to JSON::Schema::Modern::Vocabulary::Validation::_traverse_keyword_enum, avg 10µs/call # spent 511µs making 34 calls to JSON::Schema::Modern::Vocabulary::MetaData::_traverse_keyword_title, avg 15µs/call # spent 393µs making 21 calls to JSON::Schema::Modern::Vocabulary::Validation::_traverse_keyword_minimum, avg 19µs/call # spent 317µs making 8 calls to JSON::Schema::Modern::Vocabulary::Validation::_traverse_keyword_maxLength, avg 40µs/call # spent 250µs making 14 calls to JSON::Schema::Modern::Vocabulary::Validation::_traverse_keyword_minItems, avg 18µs/call # spent 249µs making 1 call to JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_anchor # spent 229µs making 8 calls to JSON::Schema::Modern::Vocabulary::Validation::_traverse_keyword_minLength, avg 29µs/call # spent 171µs making 8 calls to JSON::Schema::Modern::Vocabulary::Validation::_traverse_keyword_maximum, avg 21µs/call # spent 168µs making 15 calls to JSON::Schema::Modern::Vocabulary::MetaData::_traverse_keyword_deprecated, avg 11µs/call # spent 168µs making 95 calls to JSON::Schema::Modern::Vocabulary::Validation::_traverse_keyword_const, avg 2µs/call # spent 123µs making 3 calls to JSON::Schema::Modern::Vocabulary::Validation::_traverse_keyword_maxProperties, avg 41µs/call # spent 121µs making 98 calls to JSON::Schema::Modern::Vocabulary::MetaData::_traverse_keyword_default, avg 1µs/call # spent 107µs making 2 calls to JSON::Schema::Modern::Vocabulary::Validation::_traverse_keyword_maxContains, avg 54µs/call # spent 92µs making 1 call to JSON::Schema::Modern::Vocabulary::Content::_traverse_keyword_contentSchema # spent 77µs making 3 calls to JSON::Schema::Modern::Vocabulary::Validation::_traverse_keyword_uniqueItems, avg 26µs/call # spent 63µs making 1 call to JSON::Schema::Modern::Vocabulary::Content::_traverse_keyword_contentMediaType # spent 52µs making 1 call to JSON::Schema::Modern::Vocabulary::Validation::_traverse_keyword_dependentRequired # spent 27µs making 1 call to JSON::Schema::Modern::Vocabulary::Validation::_traverse_keyword_maxItems # spent 18µs making 5 calls to JSON::Schema::Modern::Vocabulary::OpenAPI::_traverse_keyword_externalDocs, avg 4µs/call # spent 17µs making 1 call to JSON::Schema::Modern::Vocabulary::Validation::_traverse_keyword_exclusiveMinimum # spent 15µs making 1 call to JSON::Schema::Modern::Vocabulary::Validation::_traverse_keyword_minContains
488 die 'traverse returned false but we have no errors' if not $state->{errors}->@*;
489 $valid = 0;
490 next;
491 }
492
49343883.20ms if (my $callback = $state->{callbacks}{$keyword}) {
494 $callback->($schema, $state);
495 }
496 }
497 }
498
49924881.04ms delete $state->{keyword};
500
50124884.66ms24883.85ms if ($self->strict and keys %unknown_keywords) {
# spent 3.85ms making 2488 calls to JSON::Schema::Modern::strict, avg 2µs/call
502 ()= E($state, 'unknown keyword%s found: %s', keys %unknown_keywords > 1 ? 's' : '',
503 join(', ', sort keys %unknown_keywords));
504 }
505
506 # check for previously-supported but now removed keywords
507248813.0ms24883.25ms foreach my $keyword (sort keys $removed_keywords{$state->{spec_version}}->%*) {
# spent 3.25ms making 2488 calls to JSON::Schema::Modern::CORE:sort, avg 1µs/call
508149281.58ms next if not exists $schema->{$keyword};
509 my $message ='no-longer-supported "'.$keyword.'" keyword present (at location "'
510 .canonical_uri($state).'")';
511 if (my $alternates = $removed_keywords{$state->{spec_version}}->{$keyword}) {
512 my @list = map '"'.$_.'"', @$alternates;
513 @list = ((map $_.',', @list[0..$#list-1]), $list[-1]) if @list > 2;
514 splice(@list, -1, 0, 'or') if @list > 1;
515 $message .= ': this should be rewritten as '.join(' ', @list);
516 }
517 carp $message;
518 }
519
52024885.64ms return $valid;
521}
522
52345797580.7ms
# spent 87.2s (11.9+75.4) within JSON::Schema::Modern::_eval_subschema which was called 91595 times, avg 952µs/call: # 49887 times (5.80s+-5.80s) by JSON::Schema::Modern::Vocabulary::eval at line 68 of JSON/Schema/Modern/Vocabulary.pm, avg 0s/call # 41707 times (6.04s+-6.04s) by JSON::Schema::Modern::Vocabulary::eval_subschema_at_uri at line 89 of JSON/Schema/Modern/Vocabulary.pm, avg 0s/call # once (19.0ms+87.2s) by JSON::Schema::Modern::evaluate at line 369
sub _eval_subschema ($self, $data, $schema, $state) {
5249159532.9ms croak '_eval_subschema called in void context' if not defined wantarray;
525
526 # callers created a new $state for us, so we do not propagate upwards changes to depth, traversed
527 # paths; but annotations, errors are arrayrefs so their contents will be shared
52891595119ms $state->{dynamic_scope} = [ ($state->{dynamic_scope}//[])->@* ];
529915952.46s2015087263ms delete $state->@{'keyword', grep /^_/, keys %$state};
# spent 263ms making 2015087 calls to JSON::Schema::Modern::CORE:match, avg 130ns/call
530
531 abort($state, 'EXCEPTION: maximum evaluation depth exceeded')
53291595205ms91595163ms if $state->{depth}++ > $self->max_traversal_depth;
# spent 163ms making 91595 calls to JSON::Schema::Modern::max_traversal_depth, avg 2µs/call
533
53491595147ms91595186ms my $schema_type = get_type($schema);
# spent 186ms making 91595 calls to JSON::Schema::Modern::Utilities::get_type, avg 2µs/call
5359159531.6ms return $schema || E($state, 'subschema is false') if $schema_type eq 'boolean';
536
537 # this should never happen, due to checks in traverse
5389159525.3ms abort($state, 'invalid schema type: %s', $schema_type) if $schema_type ne 'object';
539
5409159536.9ms return 1 if not keys %$schema;
541
542 # find all schema locations in effect at this data path + canonical_uri combination
543 # if any of them are absolute prefix of this schema location, we are in a loop.
54491595113ms915952.50s my $canonical_uri = canonical_uri($state);
# spent 2.50s making 91595 calls to JSON::Schema::Modern::Utilities::canonical_uri, avg 27µs/call
5459159558.2ms my $schema_location = $state->{traversed_schema_path}.$state->{schema_path};
546 abort($state, 'EXCEPTION: infinite loop detected (same location evaluated twice)')
547 if grep substr($schema_location, 0, length) eq $_,
54891595473ms9159510.0s keys $state->{seen}{$state->{data_path}}{$canonical_uri}->%*;
# spent 10.0s making 91595 calls to Mojo::URL::__ANON__[Mojo/URL.pm:3], avg 110µs/call
54991595361ms915958.18s $state->{seen}{$state->{data_path}}{$canonical_uri}{$schema_location}++;
# spent 8.18s making 91595 calls to Mojo::URL::__ANON__[Mojo/URL.pm:3], avg 89µs/call
550
5519159529.6ms my $valid = 1;
55291595380ms my %unknown_keywords = map +($_ => undef), keys %$schema;
5539159536.5ms my $orig_annotations = $state->{annotations};
5549159549.9ms $state->{annotations} = [];
5559159522.1ms my @new_annotations;
556
557 ALL_KEYWORDS:
5589159586.9ms foreach my $vocabulary ($state->{vocabularies}->@*) {
559 # [ [ $keyword => $subref|undef ], [ ... ] ]
560 my $keyword_list = $vocabulary_cache->{$state->{spec_version}}{$vocabulary}{evaluate} //= [
561 map [ $_ => $vocabulary->can('_eval_keyword_'.($_ =~ s/^\$//r)) ],
562 $vocabulary->keywords($state->{spec_version})
563641165576ms124158µs ];
# spent 100µs making 58 calls to UNIVERSAL::can, avg 2µs/call # spent 18µs making 1 call to JSON::Schema::Modern::Vocabulary::Applicator::keywords # spent 12µs making 58 calls to JSON::Schema::Modern::CORE:subst, avg 207ns/call # spent 7µs making 1 call to JSON::Schema::Modern::Vocabulary::Validation::keywords # spent 6µs making 1 call to JSON::Schema::Modern::Vocabulary::MetaData::keywords # spent 6µs making 1 call to JSON::Schema::Modern::Vocabulary::Unevaluated::keywords # spent 5µs making 1 call to JSON::Schema::Modern::Vocabulary::Core::keywords # spent 2µs making 1 call to JSON::Schema::Modern::Vocabulary::FormatAssertion::keywords # spent 1µs making 1 call to JSON::Schema::Modern::Vocabulary::Content::keywords # spent 1µs making 1 call to JSON::Schema::Modern::Vocabulary::FormatAnnotation::keywords
564
565641165969ms foreach my $keyword_tuple ($keyword_list->@*) {
56652209151.34s my ($keyword, $sub) = $keyword_tuple->@*;
5675220915953ms next if not exists $schema->{$keyword};
568
569 # keywords adjacent to $ref are not evaluated before draft2019-09
570308026127ms next if $keyword ne '$ref' and exists $schema->{'$ref'} and $state->{spec_version} eq 'draft7';
571
572308026102ms delete $unknown_keywords{$keyword};
573308026104ms $state->{keyword} = $keyword;
574
57530802690.8ms if ($sub) {
57620247170.9ms my $error_count = $state->{errors}->@*;
577
578202471435ms202471539s if (not $sub->($vocabulary, $data, $schema, $state)) {
# spent 942s making 39121 calls to JSON::Schema::Modern::Vocabulary::Core::_eval_keyword_ref, avg 24.1ms/call, recursion: max depth 31, sum of overlapping time 854s # spent 413s making 32492 calls to JSON::Schema::Modern::Vocabulary::Applicator::_eval_keyword_properties, avg 12.7ms/call, recursion: max depth 11, sum of overlapping time 326s # spent 105s making 3369 calls to JSON::Schema::Modern::Vocabulary::Applicator::_eval_keyword_patternProperties, avg 31.1ms/call, recursion: max depth 2, sum of overlapping time 31.9s # spent 70.0s making 3013 calls to JSON::Schema::Modern::Vocabulary::Applicator::_eval_keyword_if, avg 23.2ms/call, recursion: max depth 1, sum of overlapping time 3.74s # spent 240s making 6002 calls to JSON::Schema::Modern::Vocabulary::Applicator::_eval_keyword_allOf, avg 40.0ms/call, recursion: max depth 13, sum of overlapping time 175s # spent 129s making 2586 calls to JSON::Schema::Modern::Vocabulary::Core::_eval_keyword_dynamicRef, avg 49.7ms/call, recursion: max depth 6, sum of overlapping time 67.1s # spent 98.3s making 977 calls to JSON::Schema::Modern::Vocabulary::Applicator::_eval_keyword_additionalProperties, avg 101ms/call, recursion: max depth 4, sum of overlapping time 37.4s # spent 24.3s making 1758 calls to JSON::Schema::Modern::Vocabulary::Applicator::_eval_keyword_items, avg 13.8ms/call, recursion: max depth 4, sum of overlapping time 2.33s # spent 4.04s making 305 calls to JSON::Schema::Modern::Vocabulary::Applicator::_eval_keyword_dependentSchemas, avg 13.3ms/call # spent 3.34s making 1182 calls to JSON::Schema::Modern::Vocabulary::Applicator::_eval_keyword_anyOf, avg 2.82ms/call # spent 2.64s making 25862 calls to JSON::Schema::Modern::Vocabulary::Core::_eval_keyword_id, avg 102µs/call # spent 2.03s making 25860 calls to JSON::Schema::Modern::Vocabulary::MetaData::_eval_keyword_title, avg 79µs/call # spent 1.03s making 35648 calls to JSON::Schema::Modern::Vocabulary::Validation::_eval_keyword_type, avg 29µs/call # spent 532ms making 3747 calls to JSON::Schema::Modern::Vocabulary::Unevaluated::_eval_keyword_unevaluatedProperties, avg 142µs/call # spent 500ms making 4795 calls to JSON::Schema::Modern::Vocabulary::Validation::_eval_keyword_required, avg 104µs/call # spent 372ms making 627 calls to JSON::Schema::Modern::Vocabulary::Applicator::_eval_keyword_propertyNames, avg 593µs/call # spent 343ms making 5174 calls to JSON::Schema::Modern::Vocabulary::MetaData::_eval_keyword_description, avg 66µs/call # spent 316ms making 305 calls to JSON::Schema::Modern::Vocabulary::Applicator::_eval_keyword_oneOf, avg 1.04ms/call # spent 297ms making 1208 calls to JSON::Schema::Modern::Vocabulary::Validation::_eval_keyword_const, avg 246µs/call # spent 241ms making 1538 calls to JSON::Schema::Modern::Vocabulary::Validation::_eval_keyword_enum, avg 156µs/call # spent 186ms making 2167 calls to JSON::Schema::Modern::Vocabulary::FormatAnnotation::_eval_keyword_format, avg 86µs/call # spent 171ms making 1180 calls to JSON::Schema::Modern::Vocabulary::MetaData::_eval_keyword_default, avg 145µs/call # spent 85.9ms making 1403 calls to JSON::Schema::Modern::Vocabulary::Validation::_eval_keyword_uniqueItems, avg 61µs/call # spent 16.7ms making 63 calls to JSON::Schema::Modern::Vocabulary::FormatAssertion::_eval_keyword_format, avg 265µs/call # spent 13.0ms making 1244 calls to JSON::Schema::Modern::Vocabulary::Validation::_eval_keyword_minItems, avg 10µs/call # spent 7.51ms making 262 calls to JSON::Schema::Modern::Vocabulary::Validation::_eval_keyword_pattern, avg 29µs/call # spent 4.55ms making 485 calls to JSON::Schema::Modern::Vocabulary::Validation::_eval_keyword_minProperties, avg 9µs/call # spent 3.22ms making 4 calls to JSON::Schema::Modern::Vocabulary::Applicator::_eval_keyword_not, avg 804µs/call # spent 1.83ms making 79 calls to JSON::Schema::Modern::Vocabulary::Validation::_eval_keyword_minimum, avg 23µs/call # spent 198µs making 15 calls to JSON::Schema::Modern::Vocabulary::Validation::_eval_keyword_maxProperties, avg 13µs/call
579 warn 'result is false but there are no errors (keyword: '.$keyword.')'
58042832.33ms if $error_count == $state->{errors}->@*;
58142831.06ms $valid = 0;
582
58342831.94ms last ALL_KEYWORDS if $state->{short_circuit};
58442833.29ms next;
585 }
586 }
587
588303743226ms41641133ms if (my $callback = $state->{callbacks}{$keyword}) {
589 $callback->($data, $schema, $state);
590 }
591
592303743447ms push @new_annotations, $state->{annotations}->@[$#new_annotations+1 .. $state->{annotations}->$#*];
593 }
594 }
595
5969159554.0ms delete $state->{keyword};
597
5989159527.6ms if ($state->{strict} and keys %unknown_keywords) {
599 abort($state, 'unknown keyword%s found: %s', keys %unknown_keywords > 1 ? 's' : '',
600 join(', ', sort keys %unknown_keywords));
601 }
602
60391595104ms $state->{annotations} = $orig_annotations;
604
6059159581.7ms if ($valid) {
60687312167ms push $state->{annotations}->@*, @new_annotations;
60787312936ms349244370ms if ($state->{collect_annotations} and $state->{spec_version} !~ qr/^draft(7|2019-09)$/) {
# spent 124ms making 87311 calls to JSON::Schema::Modern::CORE:qr, avg 1µs/call # spent 117ms making 87311 calls to JSON::Schema::Modern::CORE:regcomp, avg 1µs/call # spent 107ms making 87311 calls to JSON::Schema::Modern::CORE:match, avg 1µs/call # spent 22.2ms making 87311 calls to JSON::Schema::Modern::CORE:sort, avg 254ns/call
608 annotate_self(+{ %$state, keyword => $_, _unknown => 1 }, $schema)
609 foreach sort keys %unknown_keywords;
610 }
611 }
612
61391595420ms return $valid;
614}
615
616has _resource_index => (
617 is => 'bare',
618 isa => HashRef[my $resource_type = Dict[
619 canonical_uri => InstanceOf['Mojo::URL'],
620 path => Str,
621 specification_version => my $spec_version_type = Enum(SPECIFICATION_VERSIONS_SUPPORTED),
622 document => InstanceOf['JSON::Schema::Modern::Document'],
623 # the vocabularies used when evaluating instance data against schema
624 vocabularies => ArrayRef[my $vocabulary_class_type = ClassName->where(q{$_->DOES('JSON::Schema::Modern::Vocabulary')})],
625 configs => HashRef,
626 Slurpy[HashRef[Undef]], # no other fields allowed
627 ]],
628 handles_via => 'Hash',
629 handles => {
630 _add_resources => 'set',
631 _get_resource => 'get',
632 _remove_resource => 'delete',
633 _resource_index => 'elements',
634 _resource_keys => 'keys',
635 _add_resources_unsafe => 'set',
636 _canonical_resources => 'values',
637 _resource_exists => 'exists',
638 },
639 lazy => 1,
64014µs
# spent 2µs within JSON::Schema::Modern::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/JSON/Schema/Modern.pm:640] which was called: # once (2µs+0s) by JSON::Schema::Modern::_assert__resource_index at line 23 of (eval 348)[Sub/Quote.pm:3]
default => sub { {} },
641145µs1423.2ms);
# spent 12.3ms making 1 call to MooX::HandlesVia::has # spent 5.18ms making 1 call to Types::Standard::Dict # spent 4.19ms making 3 calls to Types::Standard::HashRef, avg 1.40ms/call # spent 637µs making 1 call to Types::Standard::ArrayRef # spent 566µs making 2 calls to Types::Standard::InstanceOf, avg 283µs/call # spent 191µs making 1 call to Type::Tiny::where # spent 71µs making 1 call to Types::Standard::Slurpy # spent 59µs making 1 call to Types::Standard::Enum # spent 3µs making 1 call to Types::Standard::ClassName # spent 3µs making 1 call to Types::Standard::Undef # spent 1µs making 1 call to Types::Standard::Str
642
643
# spent 13.3ms (655µs+12.6) within JSON::Schema::Modern::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/JSON/Schema/Modern.pm:676] which was called 15 times, avg 886µs/call: # 15 times (655µs+12.6ms) by JSON::Schema::Modern::__ANON__[(eval 350)[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Class/Method/Modifiers.pm:89]:1] at line 1 of (eval 333)[Class/Method/Modifiers.pm:89], avg 886µs/call
around _add_resources => sub {
6441537µs my ($orig, $self) = (shift, shift);
645
646155µs my @resources;
64715280µs3080µs foreach my $pair (sort { $a->[0] cmp $b->[0] } pairs @_) {
# spent 48µs making 15 calls to List::Util::pairs, avg 3µs/call # spent 32µs making 15 calls to JSON::Schema::Modern::CORE:sort, avg 2µs/call
648249µs my ($key, $value) = @$pair;
649
65024191µs729.60ms $resource_type->($value); # check type of hash value against Dict
# spent 5.30ms making 24 calls to Sub::Defer::__ANON__[Sub/Defer.pm:178], avg 221µs/call # spent 4.30ms making 48 calls to Type::Tiny::__ANON__[Type/Tiny.pm:89], avg 90µs/call
651
65224100µs441.44ms if (my $existing = $self->_get_resource($key)) {
# spent 1.34ms making 24 calls to JSON::Schema::Modern::_get_resource, avg 56µs/call # spent 96µs making 2 calls to Mojo::URL::__ANON__[Mojo/URL.pm:3], avg 48µs/call # spent 8µs making 18 calls to JSON::Schema::Modern::CACHED_METASCHEMAS, avg 444ns/call
653 # we allow overwriting canonical_uri = '' to allow for ad hoc evaluation of schemas that
654 # lack all identifiers altogether, but preserve other resources from the original document
655611µs6492µs if ($key ne '') {
# spent 492µs making 6 calls to Mojo::URL::__ANON__[Mojo/URL.pm:3], avg 82µs/call
656 next if $existing->{path} eq $value->{path}
657 and $existing->{canonical_uri} eq $value->{canonical_uri}
658 and $existing->{specification_version} eq $value->{specification_version}
659653µs24790µs and refaddr($existing->{document}) == refaddr($value->{document});
# spent 783µs making 12 calls to Mojo::URL::__ANON__[Mojo/URL.pm:3], avg 65µs/call # spent 7µs making 12 calls to Scalar::Util::refaddr, avg 583ns/call
660 croak 'uri "'.$key.'" conflicts with an existing schema resource';
661 }
662 }
663 elsif ($self->CACHED_METASCHEMAS->{$key}) {
664 croak 'uri "'.$key.'" conflicts with an existing meta-schema resource';
665 }
666
6671826µs1819µs my $fragment = $value->{canonical_uri}->fragment;
# spent 19µs making 18 calls to Mojo::URL::fragment, avg 1µs/call
668 croak sprintf('canonical_uri cannot contain an empty fragment (%s)', $value->{canonical_uri})
669184µs if defined $fragment and $fragment eq '';
670
671 croak sprintf('canonical_uri cannot contain a plain-name fragment (%s)', $value->{canonical_uri})
6721836µs187µs if ($fragment // '') =~ m{^[^/]};
# spent 7µs making 18 calls to JSON::Schema::Modern::CORE:match, avg 389ns/call
673
6741831µs18686µs $self->$orig($key, $value);
# spent 686µs making 18 calls to JSON::Schema::Modern::_add_resources, avg 38µs/call
675 }
67614µs1218µs};
# spent 218µs making 1 call to Moo::around
677
678# $vocabulary uri (not its $id!) => [ spec_version, class ]
679has _vocabulary_classes => (
680 is => 'bare',
681 isa => HashRef[
682 Tuple[
683 $spec_version_type,
684 $vocabulary_class_type,
685 ]
686 ],
687 handles_via => 'Hash',
688 handles => {
689 _get_vocabulary_class => 'get',
690 _set_vocabulary_class => 'set',
691 _get_vocabulary_values => 'values',
692 },
693 lazy => 1,
694
# spent 55.4ms (113µs+55.3) within JSON::Schema::Modern::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/JSON/Schema/Modern.pm:700] which was called: # once (113µs+55.3ms) by JSON::Schema::Modern::_assert__vocabulary_classes at line 23 of (eval 359)[Sub/Quote.pm:3]
default => sub {
695 +{
69631134µs2455.3ms map { my $class = $_; pairmap { $a => [ $b, $class ] } $class->vocabulary }
# spent 55.3ms making 8 calls to Module::Runtime::use_module, avg 6.91ms/call # spent 34µs making 8 calls to List::Util::pairmap, avg 4µs/call # spent 3µs making 1 call to JSON::Schema::Modern::Vocabulary::Applicator::vocabulary # spent 2µs making 1 call to JSON::Schema::Modern::Vocabulary::Core::vocabulary # spent 2µs making 1 call to JSON::Schema::Modern::Vocabulary::FormatAnnotation::vocabulary # spent 2µs making 1 call to JSON::Schema::Modern::Vocabulary::FormatAssertion::vocabulary # spent 2µs making 1 call to JSON::Schema::Modern::Vocabulary::Unevaluated::vocabulary # spent 2µs making 1 call to JSON::Schema::Modern::Vocabulary::Validation::vocabulary # spent 1µs making 1 call to JSON::Schema::Modern::Vocabulary::Content::vocabulary # spent 0s making 1 call to JSON::Schema::Modern::Vocabulary::MetaData::vocabulary
697 map use_module('JSON::Schema::Modern::Vocabulary::'.$_),
698 qw(Core Applicator Validation FormatAssertion FormatAnnotation Content MetaData Unevaluated)
699 }
700 },
701118µs39.11ms);
# spent 5.44ms making 1 call to Types::Standard::Tuple # spent 3.06ms making 1 call to MooX::HandlesVia::has # spent 614µs making 1 call to Types::Standard::HashRef
702
70330s
# spent 61.2ms (69µs+61.1) within JSON::Schema::Modern::add_vocabulary which was called: # once (69µs+61.1ms) by JSON::Schema::Modern::Document::OpenAPI::_add_vocab_and_default_schemas at line 182 of JSON/Schema/Modern/Document/OpenAPI.pm
sub add_vocabulary ($self, $classname) {
70415µs155.7ms return if grep $_->[1] eq $classname, $self->_get_vocabulary_values;
# spent 55.7ms making 1 call to JSON::Schema::Modern::_get_vocabulary_values
705
70618µs44.14ms $vocabulary_class_type->(use_module($classname));
# spent 3.34ms making 1 call to Module::Runtime::use_module # spent 535µs making 1 call to Sub::Defer::__ANON__[Sub/Defer.pm:178] # spent 261µs making 2 calls to Type::Tiny::__ANON__[Type/Tiny.pm:89], avg 130µs/call
707
708 # uri => version, uri => version
709124µs215µs foreach my $pair (pairs $classname->vocabulary) {
# spent 15µs making 1 call to List::Util::pairs # spent 0s making 1 call to JSON::Schema::Modern::Vocabulary::OpenAPI::vocabulary
71013µs my ($uri_string, $spec_version) = @$pair;
711110µs51.09ms Str->where(q{my $uri = Mojo::URL->new($_); $uri->is_abs && !defined $uri->fragment})->($uri_string);
# spent 584µs making 1 call to Sub::Defer::__ANON__[Sub/Defer.pm:178] # spent 313µs making 2 calls to Type::Tiny::__ANON__[Type/Tiny.pm:89], avg 156µs/call # spent 195µs making 1 call to Type::Tiny::where # spent 2µs making 1 call to Types::Standard::Str
712140µs4489µs $spec_version_type->($spec_version);
# spent 424µs making 1 call to Sub::Defer::__ANON__[Sub/Defer.pm:178] # spent 60µs making 1 call to Type::Tiny::DESTROY # spent 5µs making 2 calls to Type::Tiny::__ANON__[Type/Tiny.pm:89], avg 2µs/call
71315µs191µs $self->_set_vocabulary_class($uri_string => [ $spec_version, $classname ])
# spent 91µs making 1 call to JSON::Schema::Modern::_set_vocabulary_class
714 }
715}
716
717# $schema uri => [ spec_version, [ vocab classes ] ].
718has _metaschema_vocabulary_classes => (
719 is => 'bare',
720 isa => HashRef[
721 Tuple[
722 $spec_version_type,
723 ArrayRef[$vocabulary_class_type],
724 ]
725 ],
726 handles_via => 'Hash',
727 handles => {
728 _get_metaschema_vocabulary_classes => 'get',
729 _set_metaschema_vocabulary_classes => 'set',
730 __all_metaschema_vocabulary_classes => 'values',
731 },
732 lazy => 1,
733
# spent 174µs (34+140) within JSON::Schema::Modern::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/JSON/Schema/Modern.pm:742] which was called: # once (34µs+140µs) by JSON::Schema::Modern::_assert__metaschema_vocabulary_classes at line 23 of (eval 364)[Sub/Quote.pm:3]
default => sub {
734110µs7140µs my @modules = map use_module('JSON::Schema::Modern::Vocabulary::'.$_),
# spent 140µs making 7 calls to Module::Runtime::use_module, avg 20µs/call
735 qw(Core Applicator Validation FormatAnnotation Content MetaData Unevaluated);
736 +{
737 'https://json-schema.org/draft/2020-12/schema' => [ 'draft2020-12', [ @modules ] ],
738316µs do { pop @modules; () },
739 'https://json-schema.org/draft/2019-09/schema' => [ 'draft2019-09', \@modules ],
740 'http://json-schema.org/draft-07/schema#' => [ 'draft7', \@modules ],
741 },
742 },
743125µs45.86ms);
# spent 2.72ms making 1 call to MooX::HandlesVia::has # spent 2.10ms making 1 call to Types::Standard::Tuple # spent 924µs making 1 call to Types::Standard::HashRef # spent 121µs making 1 call to Types::Standard::ArrayRef
744
745# retrieves metaschema info either from cache or by parsing the schema for vocabularies
746# throws a JSON::Schema::Modern::Result on error
7472972879µs
# spent 108ms (5.16+103) within JSON::Schema::Modern::_get_metaschema_info which was called 743 times, avg 146µs/call: # 743 times (5.16ms+103ms) by JSON::Schema::Modern::traverse at line 263, avg 146µs/call
sub _get_metaschema_info ($self, $metaschema_uri, $for_canonical_uri) {
748 # check the cache
7497431.95ms743101ms my $metaschema_info = $self->_get_metaschema_vocabulary_classes($metaschema_uri);
# spent 101ms making 743 calls to JSON::Schema::Modern::_get_metaschema_vocabulary_classes, avg 137µs/call
7507431.88ms return @$metaschema_info if $metaschema_info;
751
752 # otherwise, fetch the metaschema and parse its $vocabulary keyword.
753 # we do this by traversing a baby schema with just the $schema keyword.
75417µs10s my $state = $self->traverse({ '$schema' => $metaschema_uri.'' });
# spent 1.94ms making 1 call to JSON::Schema::Modern::traverse, recursion: max depth 1, sum of overlapping time 1.94ms
755 die JSON::Schema::Modern::Result->new(
756 output_format => $self->output_format,
757 valid => JSON::PP::false,
758 errors => [
759 map {
760 my $e = $_;
761 # absolute location is undef iff the location = '/$schema'
762 my $absolute_location = $e->absolute_keyword_location // $for_canonical_uri;
763 JSON::Schema::Modern::Error->new(
764 keyword => $e->keyword eq '$schema' ? '' : $e->keyword,
765 instance_location => $e->instance_location,
766 keyword_location => ($for_canonical_uri->fragment//'').($e->keyword_location =~ s{^/\$schema\b}{}r),
767 length $absolute_location ? ( absolute_keyword_location => $absolute_location ) : (),
768 error => $e->error,
769 )
770 }
771 $state->{errors}->@* ],
772 exception => 1,
77310s ) if $state->{errors}->@*;
77415µs return ($state->{spec_version}, $state->{vocabularies});
775}
776
777# used for determining a default '$schema' keyword where there is none
77812µs
# spent 86µs (17+69) within JSON::Schema::Modern::BEGIN@778 which was called: # once (17µs+69µs) by OpenAPI::Modern::BEGIN@26 at line 782
use constant METASCHEMA_URIS => {
779 'draft2020-12' => 'https://json-schema.org/draft/2020-12/schema',
780 'draft2019-09' => 'https://json-schema.org/draft/2019-09/schema',
781 'draft7' => 'http://json-schema.org/draft-07/schema#',
7821137µs2155µs};
# spent 86µs making 1 call to JSON::Schema::Modern::BEGIN@778 # spent 69µs making 1 call to constant::import
783
78411µs
# spent 73µs (20+53) within JSON::Schema::Modern::BEGIN@784 which was called: # once (20µs+53µs) by OpenAPI::Modern::BEGIN@26 at line 807
use constant CACHED_METASCHEMAS => {
785 'https://json-schema.org/draft/2020-12/meta/applicator' => 'draft2020-12/meta/applicator.json',
786 'https://json-schema.org/draft/2020-12/meta/content' => 'draft2020-12/meta/content.json',
787 'https://json-schema.org/draft/2020-12/meta/core' => 'draft2020-12/meta/core.json',
788 'https://json-schema.org/draft/2020-12/meta/format-annotation' => 'draft2020-12/meta/format-annotation.json',
789 'https://json-schema.org/draft/2020-12/meta/format-assertion' => 'draft2020-12/meta/format-assertion.json',
790 'https://json-schema.org/draft/2020-12/meta/meta-data' => 'draft2020-12/meta/meta-data.json',
791 'https://json-schema.org/draft/2020-12/meta/unevaluated' => 'draft2020-12/meta/unevaluated.json',
792 'https://json-schema.org/draft/2020-12/meta/validation' => 'draft2020-12/meta/validation.json',
793 'https://json-schema.org/draft/2020-12/output/schema' => 'draft2020-12/output/schema.json',
794 'https://json-schema.org/draft/2020-12/schema' => 'draft2020-12/schema.json',
795
796 'https://json-schema.org/draft/2019-09/meta/applicator' => 'draft2019-09/meta/applicator.json',
797 'https://json-schema.org/draft/2019-09/meta/content' => 'draft2019-09/meta/content.json',
798 'https://json-schema.org/draft/2019-09/meta/core' => 'draft2019-09/meta/core.json',
799 'https://json-schema.org/draft/2019-09/meta/format' => 'draft2019-09/meta/format.json',
800 'https://json-schema.org/draft/2019-09/meta/meta-data' => 'draft2019-09/meta/meta-data.json',
801 'https://json-schema.org/draft/2019-09/meta/validation' => 'draft2019-09/meta/validation.json',
802 'https://json-schema.org/draft/2019-09/output/schema' => 'draft2019-09/output/schema.json',
803 'https://json-schema.org/draft/2019-09/schema' => 'draft2019-09/schema.json',
804
805 # trailing # is omitted because we always cache documents by its canonical (fragmentless) URI
806 'http://json-schema.org/draft-07/schema' => 'draft7/schema.json',
80711.40ms2126µs};
# spent 73µs making 1 call to JSON::Schema::Modern::BEGIN@784 # spent 53µs making 1 call to constant::import
808
809# returns the same as _get_resource
81011736922.2ms
# spent 7.36s (197ms+7.16) within JSON::Schema::Modern::_get_or_load_resource which was called 39123 times, avg 188µs/call: # 39123 times (197ms+7.16s) by JSON::Schema::Modern::_fetch_from_uri at line 857, avg 188µs/call
sub _get_or_load_resource ($self, $uri) {
8113912387.8ms391237.10s my $resource = $self->_get_resource($uri);
# spent 7.10s making 39123 calls to JSON::Schema::Modern::_get_resource, avg 181µs/call
8123912393.3ms return $resource if $resource;
813
814880µs161.00ms if (my $local_filename = $self->CACHED_METASCHEMAS->{$uri}) {
# spent 961µs making 8 calls to Mojo::URL::__ANON__[Mojo/URL.pm:3], avg 120µs/call # spent 42µs making 8 calls to JSON::Schema::Modern::CACHED_METASCHEMAS, avg 5µs/call
815847µs161.09ms my $file = path(dist_dir('JSON-Schema-Modern'), $local_filename);
# spent 1.00ms making 8 calls to File::ShareDir::dist_dir, avg 125µs/call # spent 87µs making 8 calls to Path::Tiny::path, avg 11µs/call
8168383µs24365µs my $schema = $self->_json_decoder->decode($file->slurp_raw);
# spent 275µs making 8 calls to Cpanel::JSON::XS::decode, avg 34µs/call # spent 65µs making 8 calls to Path::Tiny::slurp_raw, avg 8µs/call # spent 25µs making 8 calls to JSON::Schema::Modern::_json_decoder, avg 3µs/call
817852µs855.3ms my $document = JSON::Schema::Modern::Document->new(schema => $schema, evaluator => $self);
# spent 55.3ms making 8 calls to JSON::Schema::Modern::Document::new, avg 6.91ms/call
818
819 # this should be caught by the try/catch in evaluate()
820823µs8232µs die JSON::Schema::Modern::Result->new(
# spent 232µs making 8 calls to JSON::Schema::Modern::Document::has_errors, avg 29µs/call
821 output_format => $self->output_format,
822 valid => 0,
823 errors => [ $document->errors ],
824 exception => 1,
825 ) if $document->has_errors;
826
827 # we have already performed the appropriate collision checks, so we bypass them here
828883µs16397µs $self->_add_resources_unsafe(
# spent 256µs making 8 calls to JSON::Schema::Modern::_add_resources_unsafe, avg 32µs/call # spent 141µs making 8 calls to JSON::Schema::Modern::Document::resource_pairs, avg 18µs/call
829 map +($_->[0] => +{ $_->[1]->%*, document => $document }),
830 $document->resource_pairs
831 );
832
833858µs81.31ms return $self->_get_resource($uri);
# spent 1.31ms making 8 calls to JSON::Schema::Modern::_get_resource, avg 163µs/call
834 }
835
836 # TODO:
837 # - load from network or disk
838
839 return;
840};
841
842# returns information necessary to use a schema found at a particular URI:
843# - a schema (which may not be at a document root)
844# - the canonical uri for that schema,
845# - the JSON::Schema::Modern::Document object that holds that schema
846# - the path relative to the document root for this schema
847# - the specification version that applies to this schema
848# - the vocabularies to use when considering schema keywords
849# - the config overrides to set when considering schema keywords
850# creates a Document and adds it to the resource index, if not already present.
85114064332.9ms
# spent 22.5s (2.53+20.0) within JSON::Schema::Modern::_fetch_from_uri which was called 46881 times, avg 480µs/call: # 41707 times (2.43s+18.7s) by JSON::Schema::Modern::Vocabulary::eval_subschema_at_uri at line 72 of JSON/Schema/Modern/Vocabulary.pm, avg 506µs/call # 2586 times (57.9ms+760ms) by JSON::Schema::Modern::Vocabulary::Core::_eval_keyword_dynamicRef at line 232 of JSON/Schema/Modern/Vocabulary/Core.pm, avg 316µs/call # 2586 times (46.5ms+510ms) by JSON::Schema::Modern::Vocabulary::Core::_eval_keyword_dynamicRef at line 244 of JSON/Schema/Modern/Vocabulary/Core.pm, avg 215µs/call # once (65µs+461µs) by JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_schema at line 127 of JSON/Schema/Modern/Vocabulary/Core.pm # once (32µs+222µs) by JSON::Schema::Modern::evaluate at line 322
sub _fetch_from_uri ($self, $uri) {
8524688120.5ms133µs $uri = Mojo::URL->new($uri) if not is_ref($uri);
# spent 33µs making 1 call to Mojo::URL::new
8534688155.6ms4688139.6ms my $fragment = $uri->fragment;
# spent 39.6ms making 46881 calls to Mojo::URL::fragment, avg 845ns/call
854
8554688177.6ms2101818.3ms if (not length($fragment) or $fragment =~ m{^/}) {
# spent 18.3ms making 21018 calls to JSON::Schema::Modern::CORE:match, avg 870ns/call
8563912377.1ms782462.22s my $base = $uri->clone->fragment(undef);
# spent 2.18s making 39123 calls to Mojo::URL::clone, avg 56µs/call # spent 40.9ms making 39123 calls to Mojo::URL::fragment, avg 1µs/call
8573912383.2ms391237.36s if (my $resource = $self->_get_or_load_resource($base)) {
# spent 7.36s making 39123 calls to JSON::Schema::Modern::_get_or_load_resource, avg 188µs/call
85839123149ms39123894ms my $subschema = $resource->{document}->get(my $document_path = $resource->{path}.($fragment//''));
# spent 894ms making 39123 calls to Mojo::JSON::Pointer::get, avg 23µs/call
8593912315.5ms return if not defined $subschema;
8603912318.6ms my $document = $resource->{document};
861 my $closest_resource = first { !length($_->[1]{path}) # document root
86239123249ms || length($document_path)
863 && $document_path =~ m{^\Q$_->[1]{path}\E(?:/|\z)} } # path is above present location
864 sort { length($b->[1]{path}) <=> length($a->[1]{path}) } # sort by length, descending
86539123764ms2957956.08s grep { not length Mojo::URL->new($_->[0])->fragment } # omit anchors
# spent 4.88s making 89213 calls to Mojo::URL::new, avg 55µs/call # spent 931ms making 39123 calls to JSON::Schema::Modern::Document::resource_pairs, avg 24µs/call # spent 125ms making 39123 calls to List::Util::first, avg 3µs/call # spent 79.0ms making 39123 calls to JSON::Schema::Modern::CORE:sort, avg 2µs/call # spent 59.7ms making 89213 calls to Mojo::URL::fragment, avg 669ns/call
866 $document->resource_pairs;
867
868 my $canonical_uri = $closest_resource->[1]{canonical_uri}->clone
86939123150ms782461.57s ->fragment(substr($document_path, length($closest_resource->[1]{path})));
# spent 1.49s making 39123 calls to Mojo::URL::clone, avg 38µs/call # spent 74.0ms making 39123 calls to Mojo::URL::fragment, avg 2µs/call
8703912355.3ms6498641.7ms $canonical_uri->fragment(undef) if not length($canonical_uri->fragment);
# spent 41.7ms making 64986 calls to Mojo::URL::fragment, avg 641ns/call
871 return {
872 schema => $subschema,
873 canonical_uri => $canonical_uri,
874 document => $document,
875 document_path => $document_path,
87639123461ms $resource->%{qw(specification_version vocabularies configs)}, # reference, not copy
877 };
878 }
879 }
880 else { # we are following a URI with a plain-name fragment
881775813.5ms77581.28s if (my $resource = $self->_get_resource($uri)) {
# spent 1.28s making 7758 calls to JSON::Schema::Modern::_get_resource, avg 165µs/call
882775819.9ms7758179ms my $subschema = $resource->{document}->get($resource->{path});
# spent 179ms making 7758 calls to Mojo::JSON::Pointer::get, avg 23µs/call
88377581.95ms return if not defined $subschema;
884 return {
885 schema => $subschema,
886 canonical_uri => $resource->{canonical_uri}->clone, # this is *not* the anchor-containing URI
887 document => $resource->{document},
888 document_path => $resource->{path},
889775876.1ms7758285ms $resource->%{qw(specification_version vocabularies configs)}, # reference, not copy
# spent 285ms making 7758 calls to Mojo::URL::clone, avg 37µs/call
890 };
891 }
892 }
893}
894
895# used for internal encoding as well (when caching serialized schemas)
896has _json_decoder => (
897 is => 'ro',
898 isa => HasMethods[qw(encode decode)],
899 lazy => 1,
900112µs158µs
# spent 69µs (11+58) within JSON::Schema::Modern::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/JSON/Schema/Modern.pm:900] which was called: # once (11µs+58µs) by JSON::Schema::Modern::_json_decoder at line 23 of (eval 366)[Sub/Quote.pm:3]
default => sub { JSON::MaybeXS->new(allow_nonref => 1, canonical => 1, utf8 => 1, allow_bignum => 1, convert_blessed => 1) },
# spent 58µs making 1 call to JSON::MaybeXS::new
901111µs23.59ms);
# spent 2.25ms making 1 call to Types::Standard::HasMethods # spent 1.34ms making 1 call to MooX::HandlesVia::has
902
903# since media types are case-insensitive, all type names must be foldcased on insertion.
904has _media_type => (
905 is => 'bare',
906 isa => my $media_type_type = Map[Str->where(q{$_ eq CORE::fc($_)}), CodeRef],
907 handles_via => 'Hash',
908 handles => {
909 get_media_type => 'get',
910 add_media_type => 'set',
911 _media_types => 'keys',
912 },
913 lazy => 1,
914 default => sub ($self) {
915 my $_json_media_type = sub ($content_ref) {
916 # utf-8 decoding is always done, as per the JSON spec.
917 # other charsets are not supported: see RFC8259 §11
918 \ JSON::MaybeXS->new(allow_nonref => 1, utf8 => 1)->decode($content_ref->$*);
919 };
920 +{
921 (map +($_ => $_json_media_type),
922 qw(application/json application/schema+json application/schema-instance+json)),
923 map +($_ => sub ($content_ref) { $content_ref }),
924 qw(text/* application/octet-stream),
925 };
926 },
927119µs56.84ms);
# spent 3.84ms making 1 call to MooX::HandlesVia::has # spent 2.77ms making 1 call to Types::Standard::Map # spent 222µs making 1 call to Type::Tiny::where # spent 2µs making 1 call to Types::Standard::Str # spent 1µs making 1 call to Types::Standard::CodeRef
928
929# get_media_type('TExT/bloop') will fall through to matching an entry for 'text/*' or '*/*'
930around get_media_type => sub ($orig, $self, $type) {
931 my $mt = $self->$orig(fc $type);
932 return $mt if $mt;
933
934 return $self->$orig((first { m{([^/]+)/\*$} && fc($type) =~ m{^\Q$1\E/[^/]+$} } $self->_media_types)
935 // '*/*');
93616µs1330µs};
# spent 330µs making 1 call to Moo::around
937
93814µs1200µsbefore add_media_type => sub ($self, $type, $sub) { $media_type_type->({ $type => $sub }) };
# spent 200µs making 1 call to Moo::before
939
940has _encoding => (
941 is => 'bare',
942 isa => HashRef[CodeRef],
943 handles_via => 'Hash',
944 handles => {
945 get_encoding => 'get',
946 add_encoding => 'set',
947 },
948 lazy => 1,
949 default => sub ($self) {
950 +{
951 identity => sub ($content_ref) { $content_ref },
952 base64 => sub ($content_ref) {
953 die "invalid characters\n"
954 if $content_ref->$* =~ m{[^A-Za-z0-9+/=]} or $content_ref->$* =~ m{=(?=[^=])};
955 require MIME::Base64; \ MIME::Base64::decode($content_ref->$*);
956 },
957 };
958 },
959119µs33.29ms);
# spent 2.78ms making 1 call to MooX::HandlesVia::has # spent 506µs making 1 call to Types::Standard::HashRef # spent 5µs making 1 call to Types::Standard::CodeRef
960
961# callback hook for Sereal::Encode
962sub FREEZE ($self, $serializer) {
963 my $data = +{ %$self };
964 # Cpanel::JSON::XS doesn't serialize: https://github.com/Sereal/Sereal/issues/266
965 # coderefs can't serialize cleanly and must be re-added by the user.
966 delete $data->@{qw(_json_decoder _format_validations _media_type _encoding)};
967 return $data;
968}
969
970# callback hook for Sereal::Decode
971sub THAW ($class, $serializer, $data) {
972 my $self = bless($data, $class);
973
974 # load all vocabulary classes
975 require_module($_) foreach uniq map $_->{vocabularies}->@*, $self->_canonical_resources;
976
977 return $self;
978}
979
9801119µs1;
981
9821158µs11.82ms__END__