← 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:02 2022

Filename/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/JSON/Schema/Modern.pm
StatementsExecuted 12730331 statements in 15.4s
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
915953212.2s97.2sJSON::Schema::Modern::::_eval_subschemaJSON::Schema::Modern::_eval_subschema (recurses: max depth 74, inclusive time 2188s)
46881532.16s19.3sJSON::Schema::Modern::::_fetch_from_uriJSON::Schema::Modern::_fetch_from_uri
95381931376ms376msJSON::Schema::Modern::::CORE:substJSON::Schema::Modern::CORE:subst (opcode)
111319ms97.6sJSON::Schema::Modern::::evaluateJSON::Schema::Modern::evaluate
212343441307ms307msJSON::Schema::Modern::::CORE:matchJSON::Schema::Modern::CORE:match (opcode)
3912311178ms6.36sJSON::Schema::Modern::::_get_or_load_resourceJSON::Schema::Modern::_get_or_load_resource
285652170ms642msJSON::Schema::Modern::::_traverse_subschemaJSON::Schema::Modern::_traverse_subschema (recurses: max depth 6, inclusive time 674ms)
1289294198.7ms98.7msJSON::Schema::Modern::::CORE:sortJSON::Schema::Modern::CORE:sort (opcode)
873111187.5ms87.5msJSON::Schema::Modern::::CORE:regcompJSON::Schema::Modern::CORE:regcomp (opcode)
873111180.4ms80.4msJSON::Schema::Modern::::CORE:qrJSON::Schema::Modern::CORE:qr (opcode)
7434327.6ms1.25sJSON::Schema::Modern::::traverseJSON::Schema::Modern::traverse (recurses: max depth 1, inclusive time 2.21ms)
11111.0ms15.7msJSON::Schema::Modern::::BEGIN@25JSON::Schema::Modern::BEGIN@25
1118.94ms87.2msJSON::Schema::Modern::::BEGIN@31JSON::Schema::Modern::BEGIN@31
743114.52ms97.2msJSON::Schema::Modern::::_get_metaschema_infoJSON::Schema::Modern::_get_metaschema_info (recurses: max depth 1, inclusive time 30µs)
1113.71ms189msJSON::Schema::Modern::::BEGIN@23JSON::Schema::Modern::BEGIN@23
1113.67ms5.80msJSON::Schema::Modern::::BEGIN@36JSON::Schema::Modern::BEGIN@36
1113.23ms29.8msJSON::Schema::Modern::::BEGIN@27JSON::Schema::Modern::BEGIN@27
1112.72ms3.00msJSON::Schema::Modern::::BEGIN@28JSON::Schema::Modern::BEGIN@28
1112.52ms37.2msJSON::Schema::Modern::::BEGIN@34JSON::Schema::Modern::BEGIN@34
1111.96ms14.6msJSON::Schema::Modern::::BEGIN@18JSON::Schema::Modern::BEGIN@18
1111.84ms49.8msJSON::Schema::Modern::::BEGIN@35JSON::Schema::Modern::BEGIN@35
1111.60ms76.0msJSON::Schema::Modern::::BEGIN@33JSON::Schema::Modern::BEGIN@33
1111.33ms1.64msJSON::Schema::Modern::::BEGIN@30JSON::Schema::Modern::BEGIN@30
9321.13ms133msJSON::Schema::Modern::::add_schemaJSON::Schema::Modern::add_schema
1111.07ms7.30msJSON::Schema::Modern::::BEGIN@29JSON::Schema::Modern::BEGIN@29
1511626µs10.2msJSON::Schema::Modern::::__ANON__[:646]JSON::Schema::Modern::__ANON__[:646]
111171µs64.8msJSON::Schema::Modern::::add_vocabularyJSON::Schema::Modern::add_vocabulary
111118µs56.5msJSON::Schema::Modern::::__ANON__[:670]JSON::Schema::Modern::__ANON__[:670]
11176µs1.09msJSON::Schema::Modern::::__ANON__[:124]JSON::Schema::Modern::__ANON__[:124]
11167µs407µsJSON::Schema::Modern::::BEGIN@11JSON::Schema::Modern::BEGIN@11
11128µs30µsOpenAPI::Modern::::BEGIN@1 OpenAPI::Modern::BEGIN@1
11122µs969µsJSON::Schema::Modern::::BEGIN@12JSON::Schema::Modern::BEGIN@12
11120µs71µsJSON::Schema::Modern::::BEGIN@20JSON::Schema::Modern::BEGIN@20
11119µs46µsJSON::Schema::Modern::::BEGIN@754JSON::Schema::Modern::BEGIN@754
11116µs73µsJSON::Schema::Modern::::BEGIN@748JSON::Schema::Modern::BEGIN@748
11115µs45µsJSON::Schema::Modern::::BEGIN@21JSON::Schema::Modern::BEGIN@21
11115µs76µsJSON::Schema::Modern::::BEGIN@32JSON::Schema::Modern::BEGIN@32
262114µs14µsJSON::Schema::Modern::::CACHED_METASCHEMASJSON::Schema::Modern::CACHED_METASCHEMAS (xsub)
11114µs55µsJSON::Schema::Modern::::BEGIN@14JSON::Schema::Modern::BEGIN@14
11114µs108µsJSON::Schema::Modern::::__ANON__[:712]JSON::Schema::Modern::__ANON__[:712]
11113µs34µsJSON::Schema::Modern::::BEGIN@15JSON::Schema::Modern::BEGIN@15
151112µs12µsJSON::Schema::Modern::::METASCHEMA_URISJSON::Schema::Modern::METASCHEMA_URIS (xsub)
11111µs22µsJSON::Schema::Modern::::BEGIN@16JSON::Schema::Modern::BEGIN@16
11111µs121µsJSON::Schema::Modern::::BEGIN@24JSON::Schema::Modern::BEGIN@24
11110µs10µsJSON::Schema::Modern::::BEGIN@10JSON::Schema::Modern::BEGIN@10
11110µs141µsJSON::Schema::Modern::::BEGIN@13JSON::Schema::Modern::BEGIN@13
11110µs24µsJSON::Schema::Modern::::BEGIN@17JSON::Schema::Modern::BEGIN@17
1119µs16µsJSON::Schema::Modern::::__ANON__[:90]JSON::Schema::Modern::__ANON__[:90]
1118µs26µsJSON::Schema::Modern::::BEGIN@19JSON::Schema::Modern::BEGIN@19
1118µs45µsJSON::Schema::Modern::::BEGIN@26JSON::Schema::Modern::BEGIN@26
1118µs668µsJSON::Schema::Modern::::BEGIN@37JSON::Schema::Modern::BEGIN@37
1118µs50µsJSON::Schema::Modern::::BEGIN@46JSON::Schema::Modern::BEGIN@46
1118µs13µsJSON::Schema::Modern::::__ANON__[:133]JSON::Schema::Modern::__ANON__[:133]
1118µs43µsJSON::Schema::Modern::::__ANON__[:870]JSON::Schema::Modern::__ANON__[:870]
1117µs20µsJSON::Schema::Modern::::BEGIN@22JSON::Schema::Modern::BEGIN@22
1117µs14µsJSON::Schema::Modern::::__ANON__[:69]JSON::Schema::Modern::__ANON__[:69]
1117µs41µsOpenAPI::Modern::::BEGIN@2 OpenAPI::Modern::BEGIN@2
1116µs29µsJSON::Schema::Modern::::BEGIN@47JSON::Schema::Modern::BEGIN@47
1112µs2µsJSON::Schema::Modern::::__ANON__[:610]JSON::Schema::Modern::__ANON__[:610]
1111µs1µsJSON::Schema::Modern::::SPECIFICATION_VERSION_DEFAULTJSON::Schema::Modern::SPECIFICATION_VERSION_DEFAULT (xsub)
2211µs1µsJSON::Schema::Modern::::__ANON__JSON::Schema::Modern::__ANON__ (xsub)
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__[:666]JSON::Schema::Modern::__ANON__[:666]
0000s0sJSON::Schema::Modern::::__ANON__[:833]JSON::Schema::Modern::__ANON__[:833]
0000s0sJSON::Schema::Modern::::__ANON__[:887]JSON::Schema::Modern::__ANON__[:887]
0000s0sJSON::Schema::Modern::::__ANON__[:893]JSON::Schema::Modern::__ANON__[:893]
0000s0sJSON::Schema::Modern::::__ANON__[:896]JSON::Schema::Modern::__ANON__[:896]
0000s0sJSON::Schema::Modern::::__ANON__[:905]JSON::Schema::Modern::__ANON__[:905]
0000s0sJSON::Schema::Modern::::__ANON__[:907]JSON::Schema::Modern::__ANON__[:907]
0000s0sJSON::Schema::Modern::::__ANON__[:909]JSON::Schema::Modern::__ANON__[:909]
0000s0sJSON::Schema::Modern::::__ANON__[:922]JSON::Schema::Modern::__ANON__[:922]
0000s0sJSON::Schema::Modern::::__ANON__[:927]JSON::Schema::Modern::__ANON__[:927]
0000s0sJSON::Schema::Modern::::__ANON__[:929]JSON::Schema::Modern::__ANON__[:929]
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
1231µs232µs
# spent 30µs (28+2) within OpenAPI::Modern::BEGIN@1 which was called: # once (28µs+2µs) by OpenAPI::Modern::BEGIN@26 at line 1
use strict;
# spent 30µs making 1 call to OpenAPI::Modern::BEGIN@1 # spent 2µs making 1 call to strict::import
2249µs275µs
# spent 41µs (7+34) within OpenAPI::Modern::BEGIN@2 which was called: # once (7µs+34µs) by OpenAPI::Modern::BEGIN@26 at line 2
use warnings;
# spent 41µs making 1 call to OpenAPI::Modern::BEGIN@2 # spent 34µs making 1 call to warnings::import
3package JSON::Schema::Modern; # git description: v0.551-3-gb026a1f2
4# vim: set ts=8 sts=2 sw=2 tw=100 et :
5# ABSTRACT: Validate data against a schema
6# KEYWORDS: JSON Schema data validation structure specification
7
812µsour $VERSION = '0.552';
9
10232µs110µs
# spent 10µs within JSON::Schema::Modern::BEGIN@10 which was called: # once (10µs+0s) by OpenAPI::Modern::BEGIN@26 at line 10
use 5.020; # for fc, unicode_strings features
# spent 10µs making 1 call to JSON::Schema::Modern::BEGIN@10
11264µs2747µs
# spent 407µs (67+340) within JSON::Schema::Modern::BEGIN@11 which was called: # once (67µs+340µs) by OpenAPI::Modern::BEGIN@26 at line 11
use Moo;
# spent 407µs making 1 call to JSON::Schema::Modern::BEGIN@11 # spent 340µs making 1 call to Moo::import
12343µs31.92ms
# spent 969µs (22+947) within JSON::Schema::Modern::BEGIN@12 which was called: # once (22µs+947µs) by OpenAPI::Modern::BEGIN@26 at line 12
use strictures 2;
# spent 969µs making 1 call to JSON::Schema::Modern::BEGIN@12 # spent 924µs making 1 call to strictures::import # spent 22µs making 1 call to strictures::VERSION
13250µs2272µs
# spent 141µs (10+131) within JSON::Schema::Modern::BEGIN@13 which was called: # once (10µs+131µs) by OpenAPI::Modern::BEGIN@26 at line 13
use experimental qw(signatures postderef);
# spent 141µs making 1 call to JSON::Schema::Modern::BEGIN@13 # spent 131µs making 1 call to experimental::import
14236µs259µs
# spent 55µs (14+41) within JSON::Schema::Modern::BEGIN@14 which was called: # once (14µs+41µs) by OpenAPI::Modern::BEGIN@26 at line 14
use if "$]" >= 5.022, experimental => 're_strict';
# spent 55µs making 1 call to JSON::Schema::Modern::BEGIN@14 # spent 4µs making 1 call to if::import
15230µs236µs
# spent 34µs (13+21) within JSON::Schema::Modern::BEGIN@15 which was called: # once (13µs+21µs) by OpenAPI::Modern::BEGIN@26 at line 15
no if "$]" >= 5.031009, feature => 'indirect';
# spent 34µs making 1 call to JSON::Schema::Modern::BEGIN@15 # spent 2µs making 1 call to if::unimport
16229µs224µs
# spent 22µs (11+11) within JSON::Schema::Modern::BEGIN@16 which was called: # once (11µs+11µs) by OpenAPI::Modern::BEGIN@26 at line 16
no if "$]" >= 5.033001, feature => 'multidimensional';
# spent 22µs making 1 call to JSON::Schema::Modern::BEGIN@16 # spent 2µs making 1 call to if::unimport
17221µs225µs
# spent 24µs (10+14) within JSON::Schema::Modern::BEGIN@17 which was called: # once (10µs+14µs) by OpenAPI::Modern::BEGIN@26 at line 17
no if "$]" >= 5.033006, feature => 'bareword_filehandles';
# spent 24µs making 1 call to JSON::Schema::Modern::BEGIN@17 # spent 1µs making 1 call to if::unimport
182635µs214.7ms
# spent 14.6ms (1.96+12.7) within JSON::Schema::Modern::BEGIN@18 which was called: # once (1.96ms+12.7ms) by OpenAPI::Modern::BEGIN@26 at line 18
use JSON::MaybeXS;
# spent 14.6ms making 1 call to JSON::Schema::Modern::BEGIN@18 # spent 52µs making 1 call to Exporter::import
19234µs244µs
# spent 26µs (8+18) within JSON::Schema::Modern::BEGIN@19 which was called: # once (8µs+18µs) by OpenAPI::Modern::BEGIN@26 at line 19
use Carp qw(croak carp);
# spent 26µs making 1 call to JSON::Schema::Modern::BEGIN@19 # spent 18µs making 1 call to Exporter::import
20348µs393µs
# spent 71µs (20+51) within JSON::Schema::Modern::BEGIN@20 which was called: # once (20µs+51µs) by OpenAPI::Modern::BEGIN@26 at line 20
use List::Util 1.55 qw(pairs first uniqint pairmap uniq any);
# spent 71µs making 1 call to JSON::Schema::Modern::BEGIN@20 # spent 13µs making 1 call to List::Util::import # spent 9µs making 1 call to UNIVERSAL::VERSION
21338µs375µs
# spent 45µs (15+30) within JSON::Schema::Modern::BEGIN@21 which was called: # once (15µs+30µs) by OpenAPI::Modern::BEGIN@26 at line 21
use Ref::Util 0.100 qw(is_ref is_plain_hashref);
# spent 45µs making 1 call to JSON::Schema::Modern::BEGIN@21 # spent 25µs making 1 call to Exporter::import # spent 5µs making 1 call to UNIVERSAL::VERSION
22220µs233µs
# spent 20µs (7+13) within JSON::Schema::Modern::BEGIN@22 which was called: # once (7µs+13µs) by OpenAPI::Modern::BEGIN@26 at line 22
use Scalar::Util 'refaddr';
# spent 20µs making 1 call to JSON::Schema::Modern::BEGIN@22 # spent 13µs making 1 call to Exporter::import
2321.13ms2189ms
# spent 189ms (3.71+185) within JSON::Schema::Modern::BEGIN@23 which was called: # once (3.71ms+185ms) by OpenAPI::Modern::BEGIN@26 at line 23
use Mojo::URL;
# spent 189ms making 1 call to JSON::Schema::Modern::BEGIN@23 # spent 4µs making 1 call to Mojo::Base::import
24233µs2231µs
# spent 121µs (11+110) within JSON::Schema::Modern::BEGIN@24 which was called: # once (11µs+110µs) by OpenAPI::Modern::BEGIN@26 at line 24
use Safe::Isa;
# spent 121µs making 1 call to JSON::Schema::Modern::BEGIN@24 # spent 110µs making 1 call to Exporter::import
252892µs215.8ms
# spent 15.7ms (11.0+4.72) within JSON::Schema::Modern::BEGIN@25 which was called: # once (11.0ms+4.72ms) by OpenAPI::Modern::BEGIN@26 at line 25
use Path::Tiny;
# spent 15.7ms making 1 call to JSON::Schema::Modern::BEGIN@25 # spent 27µs making 1 call to Exporter::import
26218µs282µs
# spent 45µs (8+37) within JSON::Schema::Modern::BEGIN@26 which was called: # once (8µs+37µs) by OpenAPI::Modern::BEGIN@26 at line 26
use Storable 'dclone';
# spent 45µs making 1 call to JSON::Schema::Modern::BEGIN@26 # spent 37µs making 1 call to Exporter::import
272932µs229.8ms
# spent 29.8ms (3.23+26.5) within JSON::Schema::Modern::BEGIN@27 which was called: # once (3.23ms+26.5ms) by OpenAPI::Modern::BEGIN@26 at line 27
use File::ShareDir 'dist_dir';
# spent 29.8ms making 1 call to JSON::Schema::Modern::BEGIN@27 # spent 22µs making 1 call to Exporter::import
282656µs23.04ms
# spent 3.00ms (2.72+289µs) within JSON::Schema::Modern::BEGIN@28 which was called: # once (2.72ms+289µs) by OpenAPI::Modern::BEGIN@26 at line 28
use Module::Runtime qw(use_module require_module);
# spent 3.00ms making 1 call to JSON::Schema::Modern::BEGIN@28 # spent 38µs making 1 call to Module::Runtime::import
293865µs313.4ms
# spent 7.30ms (1.07+6.24) within JSON::Schema::Modern::BEGIN@29 which was called: # once (1.07ms+6.24ms) by OpenAPI::Modern::BEGIN@26 at line 29
use MooX::TypeTiny 0.002002;
# spent 7.30ms making 1 call to JSON::Schema::Modern::BEGIN@29 # spent 6.09ms making 1 call to MooX::TypeTiny::import # spent 12µs making 1 call to UNIVERSAL::VERSION
302690µs21.75ms
# spent 1.64ms (1.33+313µs) within JSON::Schema::Modern::BEGIN@30 which was called: # once (1.33ms+313µs) by OpenAPI::Modern::BEGIN@26 at line 30
use MooX::HandlesVia;
# spent 1.64ms making 1 call to JSON::Schema::Modern::BEGIN@30 # spent 106µs making 1 call to MooX::HandlesVia::import
3131.03ms389.1ms
# spent 87.2ms (8.94+78.3) within JSON::Schema::Modern::BEGIN@31 which was called: # once (8.94ms+78.3ms) by OpenAPI::Modern::BEGIN@26 at line 31
use Types::Standard 1.010002 qw(Bool Int Str HasMethods Enum InstanceOf HashRef Dict CodeRef Optional slurpy ArrayRef Undef ClassName Tuple Map);
# spent 87.2ms making 1 call to JSON::Schema::Modern::BEGIN@31 # spent 1.89ms making 1 call to Exporter::Tiny::import # spent 9µs making 1 call to UNIVERSAL::VERSION
32237µs2137µs
# spent 76µs (15+61) within JSON::Schema::Modern::BEGIN@32 which was called: # once (15µs+61µs) by OpenAPI::Modern::BEGIN@26 at line 32
use Feature::Compat::Try;
# spent 76µs making 1 call to JSON::Schema::Modern::BEGIN@32 # spent 61µs making 1 call to Feature::Compat::Try::import
332694µs276.0ms
# spent 76.0ms (1.60+74.4) within JSON::Schema::Modern::BEGIN@33 which was called: # once (1.60ms+74.4ms) by OpenAPI::Modern::BEGIN@26 at line 33
use JSON::Schema::Modern::Error;
# spent 76.0ms making 1 call to JSON::Schema::Modern::BEGIN@33 # spent 0s making 1 call to JSON::Schema::Modern::__ANON__
342777µs237.2ms
# spent 37.2ms (2.52+34.6) within JSON::Schema::Modern::BEGIN@34 which was called: # once (2.52ms+34.6ms) by OpenAPI::Modern::BEGIN@26 at line 34
use JSON::Schema::Modern::Result;
# spent 37.2ms making 1 call to JSON::Schema::Modern::BEGIN@34 # spent 1µs making 1 call to JSON::Schema::Modern::__ANON__
352487µs249.8ms
# spent 49.8ms (1.84+47.9) within JSON::Schema::Modern::BEGIN@35 which was called: # once (1.84ms+47.9ms) by OpenAPI::Modern::BEGIN@26 at line 35
use JSON::Schema::Modern::Document;
# spent 49.8ms making 1 call to JSON::Schema::Modern::BEGIN@35 # spent 6µs making 1 call to Mojo::Base::import
362516µs25.88ms
# spent 5.80ms (3.67+2.13) within JSON::Schema::Modern::BEGIN@36 which was called: # once (3.67ms+2.13ms) by OpenAPI::Modern::BEGIN@26 at line 36
use JSON::Schema::Modern::Utilities qw(get_type canonical_uri E abort annotate_self);
# spent 5.80ms making 1 call to JSON::Schema::Modern::BEGIN@36 # spent 79µs making 1 call to Exporter::import
37254µs21.33ms
# spent 668µs (8+660) within JSON::Schema::Modern::BEGIN@37 which was called: # once (8µs+660µs) by OpenAPI::Modern::BEGIN@26 at line 37
use namespace::clean;
# spent 668µs making 1 call to JSON::Schema::Modern::BEGIN@37 # spent 660µ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
46229µs292µs
# spent 50µs (8+42) within JSON::Schema::Modern::BEGIN@46 which was called: # once (8µs+42µs) by OpenAPI::Modern::BEGIN@26 at line 46
use constant SPECIFICATION_VERSION_DEFAULT => 'draft2020-12';
# spent 50µs making 1 call to JSON::Schema::Modern::BEGIN@46 # spent 42µs making 1 call to constant::import
4724.63ms252µs
# spent 29µs (6+23) within JSON::Schema::Modern::BEGIN@47 which was called: # once (6µs+23µs) by OpenAPI::Modern::BEGIN@26 at line 47
use constant SPECIFICATION_VERSIONS_SUPPORTED => [qw(draft7 draft2019-09 draft2020-12)];
# spent 29µs making 1 call to JSON::Schema::Modern::BEGIN@47 # spent 23µ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 },
5716µs21.79ms);
# spent 1.10ms making 1 call to MooX::HandlesVia::has # spent 687µs making 1 call to Types::Standard::Enum
58
59120µs3729µshas output_format => (
# spent 594µs making 1 call to MooX::HandlesVia::has # spent 134µ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,
6916µs17µs
# spent 14µs (7+7) within JSON::Schema::Modern::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/JSON/Schema/Modern.pm:69] which was called: # once (7µs+7µs) by JSON::Schema::Modern::short_circuit at line 23 of (eval 312)[Sub/Quote.pm:3]
default => sub { $_[0]->output_format eq 'flag' && !$_[0]->collect_annotations },
# spent 7µs making 1 call to JSON::Schema::Modern::output_format
70137µs21.18ms);
# spent 1.15ms making 1 call to MooX::HandlesVia::has # spent 29µs making 1 call to Types::Standard::Bool
71
7214µs2825µshas max_traversal_depth => (
# spent 822µ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
7814µs2478µshas validate_formats => (
# spent 476µ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
9017µs17µs
# spent 16µs (9+7) within JSON::Schema::Modern::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/JSON/Schema/Modern.pm:90] which was called: # once (9µs+7µs) by JSON::Schema::Modern::validate_content_schemas at line 23 of (eval 315)[Sub/Quote.pm:3]
default => sub { ($_[0]->specification_version//'') eq 'draft7' },
# spent 7µs making 1 call to JSON::Schema::Modern::specification_version
9114µs2982µs);
# spent 982µs making 1 call to MooX::HandlesVia::has # spent 0s making 1 call to Types::Standard::Bool
92
9313µs2633µshas collect_annotations => (
# spent 631µs making 1 call to MooX::HandlesVia::has # spent 2µs making 1 call to Types::Standard::Bool
94 is => 'ro',
95 isa => Bool,
96);
97
9811µs2421µshas scalarref_booleans => (
# spent 420µs making 1 call to MooX::HandlesVia::has # spent 1µs making 1 call to Types::Standard::Bool
99 is => 'ro',
100 isa => Bool,
101);
102
10313µs2585µshas strict => (
# spent 583µ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,
12112µ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 325)[Sub/Quote.pm:3]
default => sub { {} },
122180µs4532.1ms);
# spent 13.3ms making 2 calls to Types::Standard::Dict, avg 6.64ms/call # spent 10.5ms making 1 call to MooX::HandlesVia::has # spent 3.97ms making 1 call to Types::Standard::slurpy # spent 1.76ms making 1 call to Types::Standard::HashRef # spent 1.50ms making 19 calls to Types::Standard::Optional, avg 79µs/call # spent 1.05ms making 1 call to Types::Standard::Enum # spent 11µs making 20 calls to Types::Standard::CodeRef, avg 550ns/call
123
1245125µs171.17ms
# spent 1.09ms (76µs+1.01) within JSON::Schema::Modern::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/JSON/Schema/Modern.pm:124] which was called: # once (76µs+1.01ms) by JSON::Schema::Modern::add_format_validation at line 4 of (eval 327)[Class/Method/Modifiers.pm:148]
before add_format_validation => sub ($self, @kvs) { $format_type->({ @$_ }) foreach pairs @kvs };
# spent 936µs making 5 calls to Sub::Defer::__ANON__[Sub/Defer.pm:178], avg 187µs/call # spent 201µs making 1 call to Moo::before # spent 31µs making 10 calls to Type::Tiny::__ANON__[Type/Tiny.pm:89], avg 3µs/call # spent 3µs making 1 call to List::Util::pairs
125
12641µs
# spent 13µs (8+5) within JSON::Schema::Modern::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/JSON/Schema/Modern.pm:133] which was called: # once (8µs+5µs) by JSON::Schema::Modern::__ANON__[(eval 329)[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Class/Method/Modifiers.pm:89]:1] at line 1 of (eval 329)[Class/Method/Modifiers.pm:89]
around BUILDARGS => sub ($orig, $class, @args) {
12712µs15µs my $args = $class->$orig(@args);
# spent 5µ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'
13011µs and ($args->{specification_version}//'') ne 'draft2019-09';
131
13213µs return $args;
13314µs1219µs};
# spent 219µs making 1 call to Moo::around
134
135
# spent 133ms (1.13+131) within JSON::Schema::Modern::add_schema which was called 9 times, avg 14.7ms/call: # 6 times (722µs+122ms) by JSON::Schema::Modern::Document::OpenAPI::_add_vocab_and_default_schemas at line 204 of JSON/Schema/Modern/Document/OpenAPI.pm, avg 20.5ms/call # 2 times (81µs+1.33ms) by JSON::Schema::Modern::Document::OpenAPI::_add_vocab_and_default_schemas at line 206 of JSON/Schema/Modern/Document/OpenAPI.pm, avg 707µs/call # once (325µs+7.59ms) 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 {
136931µs croak 'insufficient arguments' if @_ < 2;
137916µs my $self = shift;
138
139 # TODO: resolve $uri against $self->base_uri
140987µs10556µs my $uri = !is_ref($_[0]) ? Mojo::URL->new(shift)
# spent 517µs making 9 calls to Mojo::URL::new, avg 57µs/call # spent 39µs making 1 call to Safe::Isa::__ANON__[Safe/Isa.pm:23]
141 : $_[0]->$_isa('Mojo::URL') ? shift : Mojo::URL->new;
142
14397µs99µs croak 'cannot add a schema with a uri with a fragment' if defined $uri->fragment;
# spent 9µs making 9 calls to Mojo::URL::fragment, avg 1µs/call
144
145911µ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)
152989µs21103ms my $document = $_[0]->$_isa('JSON::Schema::Modern::Document') ? shift
# spent 103ms making 6 calls to JSON::Schema::Modern::Document::new, avg 17.1ms/call # spent 83µs making 9 calls to Safe::Isa::__ANON__[Safe/Isa.pm:23], avg 9µs/call # spent 32µs making 6 calls to Mojo::URL::__ANON__[Mojo/URL.pm:3], avg 5µ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
159933µs9259µs if ($document->has_errors) {
# spent 259µs making 9 calls to JSON::Schema::Modern::Document::has_errors, avg 29µ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
1699314µs189199µs if (not grep refaddr($_->{document}) == refaddr($document), $self->_canonical_resources) {
# spent 169µs making 9 calls to JSON::Schema::Modern::_canonical_resources, avg 19µs/call # spent 30µs making 180 calls to Scalar::Util::refaddr, avg 167ns/call
17076.13ms356.20ms my $schema_content = $document->_serialized_schema
# spent 6.00ms making 7 calls to Cpanel::JSON::XS::encode, avg 856µs/call # spent 150µs making 14 calls to JSON::Schema::Modern::Document::_serialized_schema, avg 11µs/call # spent 46µs making 7 calls to JSON::Schema::Modern::_json_decoder, avg 7µ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
1737189µs21692µs if (my $existing_doc = first {
# spent 548µs making 7 calls to List::Util::first, avg 78µs/call # spent 90µs making 7 calls to JSON::Schema::Modern::_canonical_resources, avg 13µs/call # spent 54µs making 7 calls to List::Util::uniqint, avg 8µs/call
17429357µs61380µs my $existing_content = $_->_serialized_schema
# spent 283µs making 8 calls to Cpanel::JSON::XS::encode, avg 35µs/call # spent 75µs making 37 calls to JSON::Schema::Modern::Document::_serialized_schema, avg 2µs/call # spent 12µs making 8 calls to JSON::Schema::Modern::Document::schema, avg 2µs/call # spent 10µs making 8 calls to JSON::Schema::Modern::_json_decoder, avg 1µs/call
175 // $_->_serialized_schema($self->_json_decoder->encode($_->schema));
1762922µ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 {
1827122µs146.36ms $self->_add_resources(map +($_->[0] => +{ $_->[1]->%*, document => $document }),
# spent 6.25ms making 7 calls to JSON::Schema::Modern::_add_resources, avg 893µs/call # spent 110µs making 7 calls to JSON::Schema::Modern::Document::resource_pairs, avg 16µs/call
183 $document->resource_pairs);
184 }
185 }
186
187932µs9907µs if ("$uri") {
# spent 907µs making 9 calls to Mojo::URL::__ANON__[Mojo/URL.pm:3], avg 101µs/call
188825µs16683µs my $resource = $document->_get_resource($document->canonical_uri);
# spent 671µs making 8 calls to JSON::Schema::Modern::Document::_get_resource, avg 84µs/call # spent 12µ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.10ms });
# spent 4.09ms making 8 calls to JSON::Schema::Modern::_add_resources, avg 511µs/call # spent 12µs making 8 calls to JSON::Schema::Modern::Document::canonical_uri, avg 2µs/call
197 }
198
199950µ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.
2332972789µs
# spent 1.25s (27.6ms+1.22) within JSON::Schema::Modern::traverse which was called 743 times, avg 1.69ms/call: # 727 times (26.8ms+1.09s) by JSON::Schema::Modern::Document::OpenAPI::_traverse_schema at line 218 of JSON/Schema/Modern/Document/OpenAPI.pm, avg 1.53ms/call # 14 times (718µs+137ms) by JSON::Schema::Modern::Document::traverse at line 178 of JSON/Schema/Modern/Document.pm, avg 9.80ms/call # once (48µs+3.03ms) by JSON::Schema::Modern::Document::OpenAPI::traverse at line 115 of JSON/Schema/Modern/Document/OpenAPI.pm # once (46µs+-46µs) by JSON::Schema::Modern::_get_metaschema_info at line 724
sub traverse ($self, $schema_reference, $config_override = {}) {
234 # Note: the starting position is not guaranteed to be at the root of the $document.
2357431.44ms743256ms my $initial_uri = Mojo::URL->new($config_override->{initial_schema_uri} // '');
# spent 256ms making 743 calls to Mojo::URL::new, avg 345µs/call
236743640µs my $initial_path = $config_override->{traversed_schema_path} // '';
2377432.29ms7431.91ms my $spec_version = $self->specification_version//SPECIFICATION_VERSION_DEFAULT;
# spent 1.91ms 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.33ms74358.8ms evaluator => $self,
# spent 58.8ms making 743 calls to Mojo::URL::new, avg 79µs/call
251 };
252
253743352µs try {
254 my $for_canonical_uri = Mojo::URL->new(
255 (is_plain_hashref($schema_reference) && exists $schema_reference->{'$id'}
256 ? Mojo::URL->new($schema_reference->{'$id'}) : undef)
2577431.69ms757170ms // $state->{initial_schema_uri});
# spent 170ms making 757 calls to Mojo::URL::new, avg 224µs/call
258743841µs758389µs $for_canonical_uri->fragment(undef) if not length $for_canonical_uri->fragment;
# spent 389µs making 758 calls to Mojo::URL::fragment, avg 513ns/call
259
260 # a subsequent "$schema" keyword can still change these values
261 $state->@{qw(spec_version vocabularies)} = $self->_get_metaschema_info(
2627435.66ms75897.2ms $config_override->{metaschema_uri} // $self->METASCHEMA_URIS->{$spec_version},
# spent 97.2ms making 743 calls to JSON::Schema::Modern::_get_metaschema_info, avg 131µs/call, recursion: max depth 1, sum of overlapping time 30µs # spent 12µs making 15 calls to JSON::Schema::Modern::METASCHEMA_URIS, avg 800ns/call
263 $for_canonical_uri,
264 );
265 }
266 catch ($e) {
267 if ($e->$_isa('JSON::Schema::Modern::Result')) {
268 push $state->{errors}->@*, $e->errors;
269 }
270 elsif ($e->$_isa('JSON::Schema::Modern::Error')) {
271 push $state->{errors}->@*, $e;
272 }
273 else {
274 ()= E({ %$state, exception => 1 }, 'EXCEPTION: '.$e);
275 }
276
277 return $state;
278 }
279
280743278µs try {
2817432.15ms743642ms $self->_traverse_subschema($schema_reference, $state);
# spent 642ms making 743 calls to JSON::Schema::Modern::_traverse_subschema, avg 864µs/call
282 }
283 catch ($e) {
284 if ($e->$_isa('JSON::Schema::Modern::Error')) {
285 # note: we should never be here, since traversal subs are no longer be fatal
286 push $state->{errors}->@*, $e;
287 }
288 else {
289 E({ %$state, exception => 1 }, 'EXCEPTION: '.$e);
290 }
291 }
292
293743447µs delete $state->{traverse};
2947431.96ms return $state;
295}
296
297# the actual runtime evaluation of the schema against input data.
29850s
# spent 97.6s (319ms+97.3) within JSON::Schema::Modern::evaluate which was called: # once (319ms+97.3s) 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 = {}) {
29911µs croak 'evaluate called in void context' if not defined wantarray;
300
30111µs my $initial_path = $config_override->{traversed_schema_path} // '';
30212µs1194µs my $effective_base_uri = Mojo::URL->new($config_override->{effective_base_uri}//'');
# spent 194µs making 1 call to Mojo::URL::new
303
304 my $state = {
30515µs13µs data_path => $config_override->{data_path} // '',
# spent 3µs making 1 call to Mojo::URL::new
306 traversed_schema_path => $initial_path, # the accumulated path as of the start of evaluation, or last $id or $ref
307 initial_schema_uri => Mojo::URL->new, # the canonical URI as of the start of evaluation, or last $id or $ref
308 schema_path => '', # the rest of the path, since the start of evaluation, or last $id or $ref
309 effective_base_uri => $effective_base_uri, # resolve locations against this for errors and annotations
310 errors => [],
311 };
312
31311µs my $valid;
31410s try {
31510s my $schema_info;
316
31714µs116µs if (not is_ref($schema_reference) or $schema_reference->$_isa('Mojo::URL')) {
# spent 16µs making 1 call to Safe::Isa::__ANON__[Safe/Isa.pm:23]
31814µs1651µs $schema_info = $self->_fetch_from_uri($schema_reference);
# spent 651µs making 1 call to JSON::Schema::Modern::_fetch_from_uri
31914µs1162µs $state->{initial_schema_uri} = Mojo::URL->new($config_override->{initial_schema_uri} // '');
# spent 162µs making 1 call to Mojo::URL::new
320 }
321 else {
322 # traverse is called via add_schema -> ::Document->new -> ::Document->BUILD
323 my $document = $self->add_schema('', $schema_reference);
324 my $base_resource = $document->_get_resource($document->canonical_uri)
325 || croak "couldn't get resource: document parse error";
326
327 $schema_info = {
328 schema => $document->schema,
329 document => $document,
330 document_path => '',
331 $base_resource->%{qw(canonical_uri specification_version vocabularies configs)},
332 };
333 }
334
33511µs abort($state, 'EXCEPTION: unable to find resource %s', $schema_reference)
336 if not $schema_info;
337
338 $state = +{
339 %$state,
340 depth => 0,
341 initial_schema_uri => $schema_info->{canonical_uri}, # the canonical URI as of the start of evaluation, or last $id or $ref
342 document => $schema_info->{document}, # the ::Document object containing this schema
343 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
344 dynamic_scope => [ $schema_info->{canonical_uri} ],
345 annotations => [],
346 seen => {},
347 spec_version => $schema_info->{specification_version},
348 vocabularies => $schema_info->{vocabularies},
349 callbacks => $config_override->{callbacks} // {},
350 evaluator => $self,
351 $schema_info->{configs}->%*,
352 (map {
353741µs658µs my $val = $config_override->{$_} // $self->$_;
# spent 25µs making 1 call to JSON::Schema::Modern::validate_content_schemas # spent 23µs making 1 call to JSON::Schema::Modern::short_circuit # spent 3µs making 1 call to JSON::Schema::Modern::collect_annotations # spent 3µs making 1 call to JSON::Schema::Modern::scalarref_booleans # spent 3µs making 1 call to JSON::Schema::Modern::validate_formats # spent 1µs making 1 call to JSON::Schema::Modern::strict
35460s defined $val ? ( $_ => $val ) : ()
355 } qw(validate_formats validate_content_schemas short_circuit collect_annotations scalarref_booleans strict)),
356 };
357
358149µs197.2s $valid = $self->_eval_subschema($data, $schema_info->{schema}, $state);
# spent 97.2s making 1 call to JSON::Schema::Modern::_eval_subschema
359165µs warn 'result is false but there are no errors' if not $valid and not $state->{errors}->@*;
360 }
361 catch ($e) {
362 if ($e->$_isa('JSON::Schema::Modern::Result')) {
363 return $e;
364 }
365 elsif ($e->$_isa('JSON::Schema::Modern::Error')) {
366 push $state->{errors}->@*, $e;
367 }
368 else {
369 $valid = E({ %$state, exception => 1 }, 'EXCEPTION: '.$e);
370 }
371 }
372
373120µs die 'evaluate validity inconstent with error count' if $valid xor !$state->{errors}->@*;
374
375 return JSON::Schema::Modern::Result->new(
376 output_format => $self->output_format,
377 valid => $valid,
378 $valid
379 # strip annotations from result if user didn't explicitly ask for them
380 ? ($config_override->{collect_annotations} // $self->collect_annotations
381 ? (annotations => $state->{annotations}) : ())
3821319ms36.66ms : (errors => $state->{errors}),
# spent 6.49ms making 1 call to JSON::Schema::Modern::Result::new # spent 103µs making 1 call to JSON::Schema::Modern::output_format # spent 66µs making 1 call to JSON::Schema::Modern::collect_annotations
383 );
384}
385
386sub validate_schema ($self, $schema, $config_override = {}) {
387 croak 'validate_schema called in void context' if not defined wantarray;
388
389 my $metaschema_uri = is_plain_hashref($schema) && $schema->{'$schema'} ? $schema->{'$schema'}
390 : $self->METASCHEMA_URIS->{$self->specification_version // $self->SPECIFICATION_VERSION_DEFAULT};
391
392 return $self->evaluate($schema, $metaschema_uri, $config_override);
393}
394
395sub get ($self, $uri) {
396 my $schema_info = $self->_fetch_from_uri($uri);
397 return if not $schema_info;
398 my $subschema = is_ref($schema_info->{schema}) ? dclone($schema_info->{schema}) : $schema_info->{schema};
399 return wantarray ? ($subschema, $schema_info->{canonical_uri}) : $subschema;
400}
401
402# defined lower down:
403# sub add_vocabulary { ... }
404# sub add_encoding { ... }
405# sub add_media_type { ... }
406
407######## NO PUBLIC INTERFACES FOLLOW THIS POINT ########
408
409# current spec version => { keyword => undef, or arrayref of alternatives }
410113µsmy %removed_keywords = (
411 'draft7' => {
412 id => [ '$id' ],
413 },
414 'draft2019-09' => {
415 id => [ '$id' ],
416 definitions => [ '$defs' ],
417 dependencies => [ qw(dependentSchemas dependentRequired) ],
418 },
419 'draft2020-12' => {
420 id => [ '$id' ],
421 definitions => [ '$defs' ],
422 dependencies => [ qw(dependentSchemas dependentRequired) ],
423 '$recursiveAnchor' => [ '$dynamicAnchor' ],
424 '$recursiveRef' => [ '$dynamicRef' ],
425 additionalItems => [ 'items' ],
426 },
427);
428
429114243.00ms
# spent 642ms (170+472) within JSON::Schema::Modern::_traverse_subschema which was called 2856 times, avg 225µs/call: # 1340 times (76.5ms+-76.5ms) by JSON::Schema::Modern::Vocabulary::traverse_object_schemas at line 55 of JSON/Schema/Modern/Vocabulary.pm, avg 0s/call # 743 times (62.4ms+580ms) by JSON::Schema::Modern::traverse at line 281, avg 864µs/call # 561 times (19.6ms+-19.6ms) by JSON::Schema::Modern::Vocabulary::traverse_subschema at line 34 of JSON/Schema/Modern/Vocabulary.pm, avg 0s/call # 205 times (11.6ms+-11.6ms) by JSON::Schema::Modern::Vocabulary::traverse_array_schemas at line 44 of JSON/Schema/Modern/Vocabulary.pm, avg 0s/call # 7 times (204µs+-204µ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) {
4302856911µs delete $state->{keyword};
431
432 return E($state, 'EXCEPTION: maximum traversal depth exceeded')
43328564.68ms28563.87ms if $state->{depth}++ > $self->max_traversal_depth;
# spent 3.87ms making 2856 calls to JSON::Schema::Modern::max_traversal_depth, avg 1µs/call
434
43528563.30ms28569.04ms my $schema_type = get_type($schema);
# spent 9.04ms making 2856 calls to JSON::Schema::Modern::Utilities::get_type, avg 3µs/call
43628561.26ms return 1 if $schema_type eq 'boolean';
437
4382483473µs return E($state, 'invalid schema type: %s', $schema_type) if $schema_type ne 'object';
439
44024831.38ms return 1 if not keys %$schema;
441
4422480349µs my $valid = 1;
443248010.1ms my %unknown_keywords = map +($_ => undef), keys %$schema;
444 # we must check the array length on every iteration because some keywords can change it!
445248013.6ms for (my $idx = 0; $idx <= $state->{vocabularies}->$#*; ++$idx) {
446193786.90ms my $vocabulary = $state->{vocabularies}[$idx];
4471937847.4ms1937875.7ms foreach my $keyword ($vocabulary->keywords($state->{spec_version})) {
# spent 37.4ms making 2480 calls to JSON::Schema::Modern::Vocabulary::Applicator::keywords, avg 15µs/call # spent 8.59ms making 2480 calls to JSON::Schema::Modern::Vocabulary::Unevaluated::keywords, avg 3µs/call # spent 7.89ms making 2480 calls to JSON::Schema::Modern::Vocabulary::Validation::keywords, avg 3µs/call # spent 7.26ms making 2480 calls to JSON::Schema::Modern::Vocabulary::Core::keywords, avg 3µs/call # spent 5.03ms making 2480 calls to JSON::Schema::Modern::Vocabulary::Content::keywords, avg 2µs/call # spent 4.89ms making 2480 calls to JSON::Schema::Modern::Vocabulary::MetaData::keywords, avg 2µs/call # spent 2.46ms making 2018 calls to JSON::Schema::Modern::Vocabulary::OpenAPI::keywords, avg 1µs/call # spent 2.18ms making 2480 calls to JSON::Schema::Modern::Vocabulary::FormatAnnotation::keywords, avg 880ns/call
44814943218.3ms next if not exists $schema->{$keyword};
449
450 # keywords adjacent to $ref are not evaluated before draft2019-09
45143811.70ms next if $keyword ne '$ref' and exists $schema->{'$ref'} and $state->{spec_version} eq 'draft7';
452
45343811.52ms delete $unknown_keywords{$keyword};
45443811.28ms $state->{keyword} = $keyword;
45543818.00ms43811.86ms my $method = '_traverse_keyword_'.($keyword =~ s/^\$//r);
# spent 1.86ms making 4381 calls to JSON::Schema::Modern::CORE:subst, avg 425ns/call
456
45743818.00ms4381991ms if (not $vocabulary->$method($schema, $state)) {
# spent 360ms making 387 calls to JSON::Schema::Modern::Vocabulary::Applicator::_traverse_keyword_properties, avg 929µs/call, recursion: max depth 3, sum of overlapping time 34.2ms # spent 165ms making 703 calls to JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_ref, avg 235µs/call # spent 101ms making 98 calls to JSON::Schema::Modern::Vocabulary::Applicator::_traverse_keyword_items, avg 1.03ms/call, recursion: max depth 1, sum of overlapping time 3.98ms # spent 94.5ms making 12 calls to JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_defs, avg 7.87ms/call, recursion: max depth 1, sum of overlapping time 13.6ms # spent 73.9ms making 276 calls to JSON::Schema::Modern::Vocabulary::Validation::_traverse_keyword_required, avg 268µs/call # spent 37.9ms making 1381 calls to JSON::Schema::Modern::Vocabulary::Validation::_traverse_keyword_type, avg 27µs/call # spent 39.4ms making 130 calls to JSON::Schema::Modern::Vocabulary::Applicator::_traverse_keyword_additionalProperties, avg 303µs/call, recursion: max depth 1, sum of overlapping time 7.30ms # spent 25.4ms making 23 calls to JSON::Schema::Modern::Vocabulary::Applicator::_traverse_keyword_allOf, avg 1.10ms/call # spent 19.5ms making 65 calls to JSON::Schema::Modern::Vocabulary::Applicator::_traverse_keyword_then, avg 300µs/call # spent 18.9ms making 32 calls to JSON::Schema::Modern::Vocabulary::Applicator::_traverse_keyword_anyOf, avg 590µs/call, recursion: max depth 1, sum of overlapping time 186µs # spent 15.9ms making 22 calls to JSON::Schema::Modern::Vocabulary::Applicator::_traverse_keyword_oneOf, avg 723µs/call # spent 15.0ms making 65 calls to JSON::Schema::Modern::Vocabulary::Applicator::_traverse_keyword_if, avg 230µs/call # spent 12.3ms making 60 calls to JSON::Schema::Modern::Vocabulary::Validation::_traverse_keyword_enum, avg 205µs/call # spent 6.74ms making 3 calls to JSON::Schema::Modern::Vocabulary::Applicator::_traverse_keyword_contains, avg 2.25ms/call # spent 6.00ms making 2 calls to JSON::Schema::Modern::Vocabulary::Applicator::_traverse_keyword_dependentSchemas, avg 3.00ms/call # spent 5.94ms making 11 calls to JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_vocabulary, avg 540µs/call # spent 5.94ms making 14 calls to JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_id, avg 424µs/call # spent 5.63ms making 22 calls to JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_dynamicRef, avg 256µs/call # spent 5.62ms making 156 calls to JSON::Schema::Modern::Vocabulary::Unevaluated::_traverse_keyword_unevaluatedProperties, avg 36µs/call # spent 4.58ms making 15 calls to JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_schema, avg 305µs/call # spent 4.33ms making 69 calls to JSON::Schema::Modern::Vocabulary::Validation::_traverse_keyword_pattern, avg 63µs/call # spent 4.10ms making 14 calls to JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_dynamicAnchor, avg 293µs/call # spent 3.69ms making 15 calls to JSON::Schema::Modern::Vocabulary::Applicator::_traverse_keyword_else, avg 246µs/call # spent 3.63ms making 14 calls to JSON::Schema::Modern::Vocabulary::Applicator::_traverse_keyword_propertyNames, avg 259µs/call # spent 2.64ms making 135 calls to JSON::Schema::Modern::Vocabulary::MetaData::_traverse_keyword_readOnly, avg 20µs/call # spent 2.33ms making 118 calls to JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_comment, avg 20µs/call # spent 1.82ms making 7 calls to JSON::Schema::Modern::Vocabulary::Applicator::_traverse_keyword_patternProperties, avg 260µs/call # spent 1.72ms making 14 calls to JSON::Schema::Modern::Vocabulary::Applicator::_traverse_keyword_not, avg 123µs/call # spent 1.38ms making 97 calls to JSON::Schema::Modern::Vocabulary::MetaData::_traverse_keyword_description, avg 14µs/call # spent 1.07ms making 50 calls to JSON::Schema::Modern::Vocabulary::Validation::_traverse_keyword_minProperties, avg 21µs/call # spent 718µs making 50 calls to JSON::Schema::Modern::Vocabulary::FormatAnnotation::_traverse_keyword_format, avg 14µs/call # spent 532µs making 34 calls to JSON::Schema::Modern::Vocabulary::MetaData::_traverse_keyword_title, avg 16µs/call # spent 368µs making 21 calls to JSON::Schema::Modern::Vocabulary::Validation::_traverse_keyword_minimum, avg 18µs/call # spent 362µs making 1 call to JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_anchor # spent 265µs making 14 calls to JSON::Schema::Modern::Vocabulary::Validation::_traverse_keyword_minItems, avg 19µs/call # spent 222µs making 8 calls to JSON::Schema::Modern::Vocabulary::Validation::_traverse_keyword_maxLength, avg 28µs/call # spent 210µs making 15 calls to JSON::Schema::Modern::Vocabulary::MetaData::_traverse_keyword_deprecated, avg 14µs/call # spent 181µs making 1 call to JSON::Schema::Modern::Vocabulary::Content::_traverse_keyword_contentSchema # spent 176µs making 8 calls to JSON::Schema::Modern::Vocabulary::Validation::_traverse_keyword_minLength, avg 22µs/call # spent 150µs making 8 calls to JSON::Schema::Modern::Vocabulary::Validation::_traverse_keyword_maximum, avg 19µs/call # spent 108µs making 95 calls to JSON::Schema::Modern::Vocabulary::Validation::_traverse_keyword_const, avg 1µs/call # spent 82µs making 3 calls to JSON::Schema::Modern::Vocabulary::Validation::_traverse_keyword_maxProperties, avg 27µs/call # spent 76µs making 3 calls to JSON::Schema::Modern::Vocabulary::Validation::_traverse_keyword_uniqueItems, avg 25µs/call # spent 66µs making 2 calls to JSON::Schema::Modern::Vocabulary::Validation::_traverse_keyword_maxContains, avg 33µs/call # spent 63µs making 98 calls to JSON::Schema::Modern::Vocabulary::MetaData::_traverse_keyword_default, avg 643ns/call # spent 60µs making 1 call to JSON::Schema::Modern::Vocabulary::Validation::_traverse_keyword_dependentRequired # spent 36µs making 1 call to JSON::Schema::Modern::Vocabulary::Content::_traverse_keyword_contentMediaType # spent 29µs making 1 call to JSON::Schema::Modern::Vocabulary::Validation::_traverse_keyword_maxItems # spent 19µs making 1 call to JSON::Schema::Modern::Vocabulary::Validation::_traverse_keyword_exclusiveMinimum # spent 18µs making 1 call to JSON::Schema::Modern::Vocabulary::Validation::_traverse_keyword_minContains # spent 5µs making 5 calls to JSON::Schema::Modern::Vocabulary::OpenAPI::_traverse_keyword_externalDocs, avg 1µs/call
458 die 'traverse returned false but we have no errors' if not $state->{errors}->@*;
459 $valid = 0;
460 next;
461 }
462
46343812.72ms if (my $sub = $state->{callbacks}{$keyword}) {
464 $sub->($schema, $state);
465 }
466 }
467 }
468
4692480844µs delete $state->{keyword};
470
47124803.45ms24802.72ms if ($self->strict and keys %unknown_keywords) {
# spent 2.72ms making 2480 calls to JSON::Schema::Modern::strict, avg 1µs/call
472 ()= E($state, 'unknown keyword%s found: %s', keys %unknown_keywords > 1 ? 's' : '',
473 join(', ', sort keys %unknown_keywords));
474 }
475
476 # check for previously-supported but now removed keywords
477248012.1ms24802.92ms foreach my $keyword (sort keys $removed_keywords{$state->{spec_version}}->%*) {
# spent 2.92ms making 2480 calls to JSON::Schema::Modern::CORE:sort, avg 1µs/call
478148801.49ms next if not exists $schema->{$keyword};
479 my $message ='no-longer-supported "'.$keyword.'" keyword present (at location "'
480 .canonical_uri($state).'")';
481 if (my $alternates = $removed_keywords{$state->{spec_version}}->{$keyword}) {
482 my @list = map '"'.$_.'"', @$alternates;
483 @list = ((map $_.',', @list[0..$#list-1]), $list[-1]) if @list > 2;
484 splice(@list, -1, 0, 'or') if @list > 1;
485 $message .= ': this should be rewritten as '.join(' ', @list);
486 }
487 carp $message;
488 }
489
49024805.37ms return $valid;
491}
492
49345797584.0ms
# spent 97.2s (12.2+85.1) within JSON::Schema::Modern::_eval_subschema which was called 91595 times, avg 1.06ms/call: # 49887 times (5.72s+-5.72s) by JSON::Schema::Modern::Vocabulary::eval at line 68 of JSON/Schema/Modern/Vocabulary.pm, avg 0s/call # 41707 times (6.45s+-6.45s) by JSON::Schema::Modern::Vocabulary::eval_subschema_at_uri at line 89 of JSON/Schema/Modern/Vocabulary.pm, avg 0s/call # once (19.9ms+97.2s) by JSON::Schema::Modern::evaluate at line 358
sub _eval_subschema ($self, $data, $schema, $state) {
4949159526.2ms croak '_eval_subschema called in void context' if not defined wantarray;
495
496 # callers created a new $state for us, so we do not propagate upwards changes to depth, traversed
497 # paths; but annotations, errors are arrayrefs so their contents will be shared
49891595110ms $state->{dynamic_scope} = [ ($state->{dynamic_scope}//[])->@* ];
499915952.19s2015087238ms delete $state->@{'keyword', grep /^_/, keys %$state};
# spent 238ms making 2015087 calls to JSON::Schema::Modern::CORE:match, avg 118ns/call
500
501 abort($state, 'EXCEPTION: maximum evaluation depth exceeded')
50291595205ms91595156ms if $state->{depth}++ > $self->max_traversal_depth;
# spent 156ms making 91595 calls to JSON::Schema::Modern::max_traversal_depth, avg 2µs/call
503
504 # find all schema locations in effect at this data path + canonical_uri combination
505 # if any of them are absolute prefix of this schema location, we are in a loop.
50691595104ms915954.21s my $canonical_uri = canonical_uri($state);
# spent 4.21s making 91595 calls to JSON::Schema::Modern::Utilities::canonical_uri, avg 46µs/call
5079159564.8ms my $schema_location = $state->{traversed_schema_path}.$state->{schema_path};
508 abort($state, 'EXCEPTION: infinite loop detected (same location evaluated twice)')
509 if grep substr($schema_location, 0, length) eq $_,
51091595425ms915958.16s keys $state->{seen}{$state->{data_path}}{$canonical_uri}->%*;
# spent 8.16s making 91595 calls to Mojo::URL::__ANON__[Mojo/URL.pm:3], avg 89µs/call
51191595318ms915956.92s $state->{seen}{$state->{data_path}}{$canonical_uri}{$schema_location}++;
# spent 6.92s making 91595 calls to Mojo::URL::__ANON__[Mojo/URL.pm:3], avg 76µs/call
512
51391595127ms91595179ms my $schema_type = get_type($schema);
# spent 179ms making 91595 calls to JSON::Schema::Modern::Utilities::get_type, avg 2µs/call
5149159534.9ms return $schema || E($state, 'subschema is false') if $schema_type eq 'boolean';
515
516 # this should never happen, due to checks in traverse
5179159524.4ms abort($state, 'invalid schema type: %s', $schema_type) if $schema_type ne 'object';
518
5199159531.6ms return 1 if not keys %$schema;
520
5219159520.0ms my $valid = 1;
52291595318ms my %unknown_keywords = map +($_ => undef), keys %$schema;
5239159531.7ms my $orig_annotations = $state->{annotations};
5249159539.6ms $state->{annotations} = [];
5259159518.4ms my @new_annotations;
526
5279159591.5ms my @vocabularies = $state->{vocabularies}->@*; # override locally only (copy, not reference)
5289159535.2ms if ($state->{validate_formats}) {
52991595931ms641165232ms s/^JSON::Schema::Modern::Vocabulary::Format\KAnnotation$/Assertion/ foreach @vocabularies;
# spent 232ms making 641165 calls to JSON::Schema::Modern::CORE:subst, avg 363ns/call
5309159573.9ms require JSON::Schema::Modern::Vocabulary::FormatAssertion;
531 }
532
533 ALL_KEYWORDS:
5349159549.7ms foreach my $vocabulary (@vocabularies) {
5356411651.97s6411652.93s foreach my $keyword ($vocabulary->keywords($state->{spec_version})) {
# spent 1.52s making 91595 calls to JSON::Schema::Modern::Vocabulary::Applicator::keywords, avg 17µs/call # spent 333ms making 91595 calls to JSON::Schema::Modern::Vocabulary::Unevaluated::keywords, avg 4µs/call # spent 325ms making 91595 calls to JSON::Schema::Modern::Vocabulary::Validation::keywords, avg 4µs/call # spent 324ms making 91595 calls to JSON::Schema::Modern::Vocabulary::Core::keywords, avg 4µs/call # spent 191ms making 91595 calls to JSON::Schema::Modern::Vocabulary::MetaData::keywords, avg 2µs/call # spent 155ms making 91595 calls to JSON::Schema::Modern::Vocabulary::Content::keywords, avg 2µs/call # spent 85.7ms making 91595 calls to JSON::Schema::Modern::Vocabulary::FormatAssertion::keywords, avg 936ns/call
5365220915725ms next if not exists $schema->{$keyword};
537
538 # keywords adjacent to $ref are not evaluated before draft2019-09
53930827391.2ms next if $keyword ne '$ref' and exists $schema->{'$ref'} and $state->{spec_version} eq 'draft7';
540
54130827394.7ms delete $unknown_keywords{$keyword};
54230827392.9ms $state->{keyword} = $keyword;
543
544308273565ms308273141ms my $method = '_eval_keyword_'.($keyword =~ s/^\$//r);
# spent 141ms making 308273 calls to JSON::Schema::Modern::CORE:subst, avg 459ns/call
5453082731.08s308273525ms if (my $sub = $vocabulary->can($method)) {
# spent 525ms making 308273 calls to UNIVERSAL::can, avg 2µs/call
54620271866.2ms my $error_count = $state->{errors}->@*;
547
548202718318ms202718601s if (not $sub->($vocabulary, $data, $schema, $state)) {
# spent 1036s making 39121 calls to JSON::Schema::Modern::Vocabulary::Core::_eval_keyword_ref, avg 26.5ms/call, recursion: max depth 31, sum of overlapping time 939s # spent 391s making 32492 calls to JSON::Schema::Modern::Vocabulary::Applicator::_eval_keyword_properties, avg 12.0ms/call, recursion: max depth 10, sum of overlapping time 294s # spent 185s making 3616 calls to JSON::Schema::Modern::Vocabulary::Applicator::_eval_keyword_patternProperties, avg 51.2ms/call, recursion: max depth 3, sum of overlapping time 105s # spent 77.0s making 3013 calls to JSON::Schema::Modern::Vocabulary::Applicator::_eval_keyword_if, avg 25.6ms/call, recursion: max depth 1, sum of overlapping time 4.31s # spent 262s making 6002 calls to JSON::Schema::Modern::Vocabulary::Applicator::_eval_keyword_allOf, avg 43.6ms/call, recursion: max depth 13, sum of overlapping time 190s # spent 141s making 2586 calls to JSON::Schema::Modern::Vocabulary::Core::_eval_keyword_dynamicRef, avg 54.5ms/call, recursion: max depth 6, sum of overlapping time 72.9s # spent 108s making 977 calls to JSON::Schema::Modern::Vocabulary::Applicator::_eval_keyword_additionalProperties, avg 111ms/call, recursion: max depth 4, sum of overlapping time 40.8s # spent 26.5s making 1758 calls to JSON::Schema::Modern::Vocabulary::Applicator::_eval_keyword_items, avg 15.1ms/call, recursion: max depth 4, sum of overlapping time 2.66s # spent 6.46s making 25860 calls to JSON::Schema::Modern::Vocabulary::MetaData::_eval_keyword_title, avg 250µs/call # spent 4.33s making 305 calls to JSON::Schema::Modern::Vocabulary::Applicator::_eval_keyword_dependentSchemas, avg 14.2ms/call # spent 3.16s making 1182 calls to JSON::Schema::Modern::Vocabulary::Applicator::_eval_keyword_anyOf, avg 2.68ms/call # spent 1.99s making 3747 calls to JSON::Schema::Modern::Vocabulary::Unevaluated::_eval_keyword_unevaluatedProperties, avg 531µs/call # spent 1.87s making 25862 calls to JSON::Schema::Modern::Vocabulary::Core::_eval_keyword_id, avg 72µs/call # spent 1.20s making 5174 calls to JSON::Schema::Modern::Vocabulary::MetaData::_eval_keyword_description, avg 233µs/call # spent 1.09s making 2230 calls to JSON::Schema::Modern::Vocabulary::FormatAssertion::_eval_keyword_format, avg 487µs/call # spent 896ms making 35648 calls to JSON::Schema::Modern::Vocabulary::Validation::_eval_keyword_type, avg 25µs/call # spent 496ms making 627 calls to JSON::Schema::Modern::Vocabulary::Applicator::_eval_keyword_propertyNames, avg 791µs/call # spent 446ms making 4795 calls to JSON::Schema::Modern::Vocabulary::Validation::_eval_keyword_required, avg 93µs/call # spent 350ms making 1180 calls to JSON::Schema::Modern::Vocabulary::MetaData::_eval_keyword_default, avg 297µs/call # spent 324ms making 305 calls to JSON::Schema::Modern::Vocabulary::Applicator::_eval_keyword_oneOf, avg 1.06ms/call # spent 273ms making 1208 calls to JSON::Schema::Modern::Vocabulary::Validation::_eval_keyword_const, avg 226µs/call # spent 218ms making 1538 calls to JSON::Schema::Modern::Vocabulary::Validation::_eval_keyword_enum, avg 141µs/call # spent 80.0ms making 1403 calls to JSON::Schema::Modern::Vocabulary::Validation::_eval_keyword_uniqueItems, avg 57µs/call # spent 9.58ms making 1244 calls to JSON::Schema::Modern::Vocabulary::Validation::_eval_keyword_minItems, avg 8µs/call # spent 6.07ms making 262 calls to JSON::Schema::Modern::Vocabulary::Validation::_eval_keyword_pattern, avg 23µs/call # spent 4.38ms making 485 calls to JSON::Schema::Modern::Vocabulary::Validation::_eval_keyword_minProperties, avg 9µs/call # spent 2.63ms making 4 calls to JSON::Schema::Modern::Vocabulary::Applicator::_eval_keyword_not, avg 657µs/call # spent 1.42ms making 79 calls to JSON::Schema::Modern::Vocabulary::Validation::_eval_keyword_minimum, avg 18µs/call # spent 107µs making 15 calls to JSON::Schema::Modern::Vocabulary::Validation::_eval_keyword_maxProperties, avg 7µs/call
549 warn 'result is false but there are no errors (keyword: '.$keyword.')'
55042832.68ms if $error_count == $state->{errors}->@*;
55142831.16ms $valid = 0;
552
55342831.01ms last ALL_KEYWORDS if $state->{short_circuit};
55442833.52ms next;
555 }
556 }
557
558303990222ms41641128ms if (my $sub = $state->{callbacks}{$keyword}) {
559 $sub->($data, $schema, $state);
560 }
561
562303990429ms push @new_annotations, $state->{annotations}->@[$#new_annotations+1 .. $state->{annotations}->$#*];
563 }
564 }
565
5669159545.8ms delete $state->{keyword};
567
5689159531.4ms if ($state->{strict} and keys %unknown_keywords) {
569 abort($state, 'unknown keyword%s found: %s', keys %unknown_keywords > 1 ? 's' : '',
570 join(', ', sort keys %unknown_keywords));
571 }
572
5739159579.4ms $state->{annotations} = $orig_annotations;
574
5759159572.0ms if ($valid) {
57687312153ms push $state->{annotations}->@*, @new_annotations;
57787312724ms349244243ms if ($state->{collect_annotations} and $state->{spec_version} !~ qr/^draft(7|2019-09)$/) {
# spent 87.5ms making 87311 calls to JSON::Schema::Modern::CORE:regcomp, avg 1µs/call # spent 80.4ms making 87311 calls to JSON::Schema::Modern::CORE:qr, avg 921ns/call # spent 51.7ms making 87311 calls to JSON::Schema::Modern::CORE:match, avg 592ns/call # spent 23.3ms making 87311 calls to JSON::Schema::Modern::CORE:sort, avg 267ns/call
578 annotate_self(+{ %$state, keyword => $_, _unknown => 1 }, $schema)
579 foreach sort keys %unknown_keywords;
580 }
581 }
582
58391595527ms return $valid;
584}
585
586has _resource_index => (
587 is => 'bare',
588 isa => HashRef[my $resource_type = Dict[
589 canonical_uri => InstanceOf['Mojo::URL'],
590 path => Str,
591 specification_version => my $spec_version_type = Enum(SPECIFICATION_VERSIONS_SUPPORTED),
592 document => InstanceOf['JSON::Schema::Modern::Document'],
593 # the vocabularies used when evaluating instance data against schema
594 vocabularies => ArrayRef[my $vocabulary_class_type = ClassName->where(q{$_->DOES('JSON::Schema::Modern::Vocabulary')})],
595 configs => HashRef,
596 slurpy HashRef[Undef], # no other fields allowed
597 ]],
598 handles_via => 'Hash',
599 handles => {
600 _add_resources => 'set',
601 _get_resource => 'get',
602 _remove_resource => 'delete',
603 _resource_index => 'elements',
604 _resource_keys => 'keys',
605 _add_resources_unsafe => 'set',
606 _canonical_resources => 'values',
607 _resource_exists => 'exists',
608 },
609 lazy => 1,
61012µs
# spent 2µs within JSON::Schema::Modern::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/JSON/Schema/Modern.pm:610] which was called: # once (2µs+0s) by JSON::Schema::Modern::_assert__resource_index at line 23 of (eval 344)[Sub/Quote.pm:3]
default => sub { {} },
611144µs1421.8ms);
# spent 11.0ms making 1 call to MooX::HandlesVia::has # spent 5.12ms making 1 call to Types::Standard::Dict # spent 4.29ms making 3 calls to Types::Standard::HashRef, avg 1.43ms/call # spent 560µs making 1 call to Types::Standard::ArrayRef # spent 524µs making 2 calls to Types::Standard::InstanceOf, avg 262µs/call # spent 181µs making 1 call to Type::Tiny::where # spent 93µs making 1 call to Types::Standard::Enum # spent 60µs making 1 call to Types::Standard::slurpy # spent 3µs making 1 call to Types::Standard::Str # spent 2µs making 1 call to Types::Standard::ClassName # spent 1µs making 1 call to Types::Standard::Undef
612
613
# spent 10.2ms (626µs+9.59) within JSON::Schema::Modern::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/JSON/Schema/Modern.pm:646] which was called 15 times, avg 681µs/call: # 15 times (626µs+9.59ms) by JSON::Schema::Modern::__ANON__[(eval 346)[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Class/Method/Modifiers.pm:89]:1] at line 1 of (eval 329)[Class/Method/Modifiers.pm:89], avg 681µs/call
around _add_resources => sub {
6141548µs my ($orig, $self) = (shift, shift);
615
616153µs my @resources;
61715200µs3066µs foreach my $pair (sort { $a->[0] cmp $b->[0] } pairs @_) {
# spent 38µs making 15 calls to List::Util::pairs, avg 3µs/call # spent 28µs making 15 calls to JSON::Schema::Modern::CORE:sort, avg 2µs/call
618249µs my ($key, $value) = @$pair;
619
62024123µs725.14ms $resource_type->($value); # check type of hash value against Dict
# spent 2.90ms making 24 calls to Sub::Defer::__ANON__[Sub/Defer.pm:178], avg 121µs/call # spent 2.24ms making 48 calls to Type::Tiny::__ANON__[Type/Tiny.pm:89], avg 47µs/call
621
62224164µs441.49ms if (my $existing = $self->_get_resource($key)) {
# spent 1.37ms making 24 calls to JSON::Schema::Modern::_get_resource, avg 57µs/call # spent 119µs making 2 calls to Mojo::URL::__ANON__[Mojo/URL.pm:3], avg 60µs/call # spent 9µs making 18 calls to JSON::Schema::Modern::CACHED_METASCHEMAS, avg 500ns/call
623 # we allow overwriting canonical_uri = '' to allow for ad hoc evaluation of schemas that
624 # lack all identifiers altogether, but preserve other resources from the original document
625611µs6523µs if ($key ne '') {
# spent 523µs making 6 calls to Mojo::URL::__ANON__[Mojo/URL.pm:3], avg 87µs/call
626 next if $existing->{path} eq $value->{path}
627 and $existing->{canonical_uri} eq $value->{canonical_uri}
628 and $existing->{specification_version} eq $value->{specification_version}
629667µs24867µs and refaddr($existing->{document}) == refaddr($value->{document});
# spent 859µs making 12 calls to Mojo::URL::__ANON__[Mojo/URL.pm:3], avg 72µs/call # spent 8µs making 12 calls to Scalar::Util::refaddr, avg 667ns/call
630 croak 'uri "'.$key.'" conflicts with an existing schema resource';
631 }
632 }
633 elsif ($self->CACHED_METASCHEMAS->{$key}) {
634 croak 'uri "'.$key.'" conflicts with an existing meta-schema resource';
635 }
636
6371823µs1819µs my $fragment = $value->{canonical_uri}->fragment;
# spent 19µs making 18 calls to Mojo::URL::fragment, avg 1µs/call
638 croak sprintf('canonical_uri cannot contain an empty fragment (%s)', $value->{canonical_uri})
639185µs if defined $fragment and $fragment eq '';
640
641 croak sprintf('canonical_uri cannot contain a plain-name fragment (%s)', $value->{canonical_uri})
6421830µs187µs if ($fragment // '') =~ m{^[^/]};
# spent 7µs making 18 calls to JSON::Schema::Modern::CORE:match, avg 389ns/call
643
6441843µs18562µs $self->$orig($key, $value);
# spent 562µs making 18 calls to JSON::Schema::Modern::_add_resources, avg 31µs/call
645 }
64615µs1189µs};
# spent 189µs making 1 call to Moo::around
647
648# $vocabulary uri (not its $id!) => [ spec_version, class ]
649has _vocabulary_classes => (
650 is => 'bare',
651 isa => HashRef[
652 Tuple[
653 $spec_version_type,
654 $vocabulary_class_type,
655 ]
656 ],
657 handles_via => 'Hash',
658 handles => {
659 _get_vocabulary_class => 'get',
660 _set_vocabulary_class => 'set',
661 _get_vocabulary_values => 'values',
662 },
663 lazy => 1,
664
# spent 56.5ms (118µs+56.4) within JSON::Schema::Modern::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/JSON/Schema/Modern.pm:670] which was called: # once (118µs+56.4ms) by JSON::Schema::Modern::_assert__vocabulary_classes at line 23 of (eval 355)[Sub/Quote.pm:3]
default => sub {
665 +{
66631734µs2456.4ms map { my $class = $_; pairmap { $a => [ $b, $class ] } $class->vocabulary }
# spent 55.8ms making 8 calls to Module::Runtime::use_module, avg 6.97ms/call # spent 631µs making 8 calls to List::Util::pairmap, avg 79µ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::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 1µs making 1 call to JSON::Schema::Modern::Vocabulary::Core::vocabulary # spent 1µs making 1 call to JSON::Schema::Modern::Vocabulary::FormatAnnotation::vocabulary # spent 1µs making 1 call to JSON::Schema::Modern::Vocabulary::FormatAssertion::vocabulary # spent 1µs making 1 call to JSON::Schema::Modern::Vocabulary::MetaData::vocabulary
667 map use_module('JSON::Schema::Modern::Vocabulary::'.$_),
668 qw(Core Applicator Validation FormatAssertion FormatAnnotation Content MetaData Unevaluated)
669 }
670 },
671115µs37.38ms);
# spent 4.18ms making 1 call to Types::Standard::Tuple # spent 2.60ms making 1 call to MooX::HandlesVia::has # spent 594µs making 1 call to Types::Standard::HashRef
672
67331µs
# spent 64.8ms (171µs+64.6) within JSON::Schema::Modern::add_vocabulary which was called: # once (171µs+64.6ms) 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) {
67417µs157.1ms return if grep $_->[1] eq $classname, $self->_get_vocabulary_values;
# spent 57.1ms making 1 call to JSON::Schema::Modern::_get_vocabulary_values
675
676111µs45.88ms $vocabulary_class_type->(use_module($classname));
# spent 4.97ms making 1 call to Module::Runtime::use_module # spent 660µs making 1 call to Sub::Defer::__ANON__[Sub/Defer.pm:178] # spent 247µs making 2 calls to Type::Tiny::__ANON__[Type/Tiny.pm:89], avg 124µs/call
677
678 # uri => version, uri => version
679155µs218µs foreach my $pair (pairs $classname->vocabulary) {
# spent 18µs making 1 call to List::Util::pairs # spent 0s making 1 call to JSON::Schema::Modern::Vocabulary::OpenAPI::vocabulary
68014µs my ($uri_string, $spec_version) = @$pair;
68118µs51.29ms Str->where(q{my $uri = Mojo::URL->new($_); $uri->is_abs && !defined $uri->fragment})->($uri_string);
# spent 751µs making 1 call to Sub::Defer::__ANON__[Sub/Defer.pm:178] # spent 271µs making 1 call to Type::Tiny::where # spent 261µs making 2 calls to Type::Tiny::__ANON__[Type/Tiny.pm:89], avg 130µs/call # spent 3µs making 1 call to Types::Standard::Str
6821118µs4516µs $spec_version_type->($spec_version);
# spent 486µs making 1 call to Sub::Defer::__ANON__[Sub/Defer.pm:178] # spent 20µs making 1 call to Type::Tiny::DESTROY # spent 10µs making 2 calls to Type::Tiny::__ANON__[Type/Tiny.pm:89], avg 5µs/call
68312µs1105µs $self->_set_vocabulary_class($uri_string => [ $spec_version, $classname ])
# spent 105µs making 1 call to JSON::Schema::Modern::_set_vocabulary_class
684 }
685}
686
687# $schema uri => [ spec_version, [ vocab classes ] ].
688has _metaschema_vocabulary_classes => (
689 is => 'bare',
690 isa => HashRef[
691 Tuple[
692 $spec_version_type,
693 ArrayRef[$vocabulary_class_type],
694 ]
695 ],
696 handles_via => 'Hash',
697 handles => {
698 _get_metaschema_vocabulary_classes => 'get',
699 _set_metaschema_vocabulary_classes => 'set',
700 __all_metaschema_vocabulary_classes => 'values',
701 },
702 lazy => 1,
703
# spent 108µs (14+94) within JSON::Schema::Modern::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/JSON/Schema/Modern.pm:712] which was called: # once (14µs+94µs) by JSON::Schema::Modern::_assert__metaschema_vocabulary_classes at line 23 of (eval 360)[Sub/Quote.pm:3]
default => sub {
70417µs794µs my @modules = map use_module('JSON::Schema::Modern::Vocabulary::'.$_),
# spent 94µs making 7 calls to Module::Runtime::use_module, avg 13µs/call
705 qw(Core Applicator Validation FormatAnnotation Content MetaData Unevaluated);
706 +{
707 'https://json-schema.org/draft/2020-12/schema' => [ 'draft2020-12', [ @modules ] ],
70835µs do { pop @modules; () },
709 'https://json-schema.org/draft/2019-09/schema' => [ 'draft2019-09', \@modules ],
710 'http://json-schema.org/draft-07/schema#' => [ 'draft7', \@modules ],
711 },
712 },
713128µs47.38ms);
# spent 3.57ms making 1 call to MooX::HandlesVia::has # spent 2.70ms making 1 call to Types::Standard::Tuple # spent 1.03ms making 1 call to Types::Standard::HashRef # spent 85µs making 1 call to Types::Standard::ArrayRef
714
715# retrieves metaschema info either from cache or by parsing the schema for vocabularies
716# throws a JSON::Schema::Modern::Result on error
7172972764µs
# spent 97.2ms (4.52+92.7) within JSON::Schema::Modern::_get_metaschema_info which was called 743 times, avg 131µs/call: # 743 times (4.52ms+92.7ms) by JSON::Schema::Modern::traverse at line 262, avg 131µs/call
sub _get_metaschema_info ($self, $metaschema_uri, $for_canonical_uri) {
718 # check the cache
7197432.25ms74390.5ms my $metaschema_info = $self->_get_metaschema_vocabulary_classes($metaschema_uri);
# spent 90.5ms making 743 calls to JSON::Schema::Modern::_get_metaschema_vocabulary_classes, avg 122µs/call
7207431.70ms return @$metaschema_info if $metaschema_info;
721
722 # otherwise, fetch the metaschema and parse its $vocabulary keyword.
723 # we do this by traversing a baby schema with just the $schema keyword.
72418µs10s my $state = $self->traverse({ '$schema' => $metaschema_uri.'' });
# spent 2.21ms making 1 call to JSON::Schema::Modern::traverse, recursion: max depth 1, sum of overlapping time 2.21ms
725 die JSON::Schema::Modern::Result->new(
726 output_format => $self->output_format,
727 valid => JSON::PP::false,
728 errors => [
729 map {
730 my $e = $_;
731 # absolute location is undef iff the location = '/$schema'
732 my $absolute_location = $e->absolute_keyword_location // $for_canonical_uri;
733 JSON::Schema::Modern::Error->new(
734 keyword => $e->keyword eq '$schema' ? '' : $e->keyword,
735 instance_location => $e->instance_location,
736 keyword_location => ($for_canonical_uri->fragment//'').($e->keyword_location =~ s{^/\$schema\b}{}r),
737 length $absolute_location ? ( absolute_keyword_location => $absolute_location ) : (),
738 error => $e->error,
739 )
740 }
741 $state->{errors}->@* ],
742 exception => 1,
74310s ) if $state->{errors}->@*;
744111µs return ($state->{spec_version}, $state->{vocabularies});
745}
746
747# used for determining a default '$schema' keyword where there is none
74811µs
# spent 73µs (16+57) within JSON::Schema::Modern::BEGIN@748 which was called: # once (16µs+57µs) by OpenAPI::Modern::BEGIN@26 at line 752
use constant METASCHEMA_URIS => {
749 'draft2020-12' => 'https://json-schema.org/draft/2020-12/schema',
750 'draft2019-09' => 'https://json-schema.org/draft/2019-09/schema',
751 'draft7' => 'http://json-schema.org/draft-07/schema#',
7521101µs2130µs};
# spent 73µs making 1 call to JSON::Schema::Modern::BEGIN@748 # spent 57µs making 1 call to constant::import
753
75411µs
# spent 46µs (19+27) within JSON::Schema::Modern::BEGIN@754 which was called: # once (19µs+27µs) by OpenAPI::Modern::BEGIN@26 at line 777
use constant CACHED_METASCHEMAS => {
755 'https://json-schema.org/draft/2020-12/meta/applicator' => 'draft2020-12/meta/applicator.json',
756 'https://json-schema.org/draft/2020-12/meta/content' => 'draft2020-12/meta/content.json',
757 'https://json-schema.org/draft/2020-12/meta/core' => 'draft2020-12/meta/core.json',
758 'https://json-schema.org/draft/2020-12/meta/format-annotation' => 'draft2020-12/meta/format-annotation.json',
759 'https://json-schema.org/draft/2020-12/meta/format-assertion' => 'draft2020-12/meta/format-assertion.json',
760 'https://json-schema.org/draft/2020-12/meta/meta-data' => 'draft2020-12/meta/meta-data.json',
761 'https://json-schema.org/draft/2020-12/meta/unevaluated' => 'draft2020-12/meta/unevaluated.json',
762 'https://json-schema.org/draft/2020-12/meta/validation' => 'draft2020-12/meta/validation.json',
763 'https://json-schema.org/draft/2020-12/output/schema' => 'draft2020-12/output/schema.json',
764 'https://json-schema.org/draft/2020-12/schema' => 'draft2020-12/schema.json',
765
766 'https://json-schema.org/draft/2019-09/meta/applicator' => 'draft2019-09/meta/applicator.json',
767 'https://json-schema.org/draft/2019-09/meta/content' => 'draft2019-09/meta/content.json',
768 'https://json-schema.org/draft/2019-09/meta/core' => 'draft2019-09/meta/core.json',
769 'https://json-schema.org/draft/2019-09/meta/format' => 'draft2019-09/meta/format.json',
770 'https://json-schema.org/draft/2019-09/meta/meta-data' => 'draft2019-09/meta/meta-data.json',
771 'https://json-schema.org/draft/2019-09/meta/validation' => 'draft2019-09/meta/validation.json',
772 'https://json-schema.org/draft/2019-09/output/schema' => 'draft2019-09/output/schema.json',
773 'https://json-schema.org/draft/2019-09/schema' => 'draft2019-09/schema.json',
774
775 # trailing # is omitted because we always cache documents by its canonical (fragmentless) URI
776 'http://json-schema.org/draft-07/schema' => 'draft7/schema.json',
77711.26ms273µs};
# spent 46µs making 1 call to JSON::Schema::Modern::BEGIN@754 # spent 27µs making 1 call to constant::import
778
779# returns the same as _get_resource
78011736922.2ms
# spent 6.36s (178ms+6.18) within JSON::Schema::Modern::_get_or_load_resource which was called 39123 times, avg 163µs/call: # 39123 times (178ms+6.18s) by JSON::Schema::Modern::_fetch_from_uri at line 827, avg 163µs/call
sub _get_or_load_resource ($self, $uri) {
7813912376.8ms391236.11s my $resource = $self->_get_resource($uri);
# spent 6.11s making 39123 calls to JSON::Schema::Modern::_get_resource, avg 156µs/call
78239123102ms return $resource if $resource;
783
784843µs16968µs if (my $local_filename = $self->CACHED_METASCHEMAS->{$uri}) {
# spent 963µs making 8 calls to Mojo::URL::__ANON__[Mojo/URL.pm:3], avg 120µs/call # spent 5µs making 8 calls to JSON::Schema::Modern::CACHED_METASCHEMAS, avg 625ns/call
785839µs161.06ms my $file = path(dist_dir('JSON-Schema-Modern'), $local_filename);
# spent 970µs making 8 calls to File::ShareDir::dist_dir, avg 121µs/call # spent 87µs making 8 calls to Path::Tiny::path, avg 11µs/call
7868359µs24338µs my $schema = $self->_json_decoder->decode($file->slurp_raw);
# spent 282µs making 8 calls to Cpanel::JSON::XS::decode, avg 35µs/call # spent 29µs making 8 calls to Path::Tiny::slurp_raw, avg 4µs/call # spent 27µs making 8 calls to JSON::Schema::Modern::_json_decoder, avg 3µs/call
787853µs859.5ms my $document = JSON::Schema::Modern::Document->new(schema => $schema, evaluator => $self);
# spent 59.5ms making 8 calls to JSON::Schema::Modern::Document::new, avg 7.44ms/call
788
789 # this should be caught by the try/catch in evaluate()
790820µs8185µs die JSON::Schema::Modern::Result->new(
# spent 185µs making 8 calls to JSON::Schema::Modern::Document::has_errors, avg 23µs/call
791 output_format => $self->output_format,
792 valid => 0,
793 errors => [ $document->errors ],
794 exception => 1,
795 ) if $document->has_errors;
796
797 # we have already performed the appropriate collision checks, so we bypass them here
798885µs16322µs $self->_add_resources_unsafe(
# spent 207µs making 8 calls to JSON::Schema::Modern::_add_resources_unsafe, avg 26µs/call # spent 115µs making 8 calls to JSON::Schema::Modern::Document::resource_pairs, avg 14µs/call
799 map +($_->[0] => +{ $_->[1]->%*, document => $document }),
800 $document->resource_pairs
801 );
802
803858µs81.10ms return $self->_get_resource($uri);
# spent 1.10ms making 8 calls to JSON::Schema::Modern::_get_resource, avg 138µs/call
804 }
805
806 # TODO:
807 # - load from network or disk
808
809 return;
810};
811
812# returns information necessary to use a schema found at a particular URI:
813# - a schema (which may not be at a document root)
814# - the canonical uri for that schema,
815# - the JSON::Schema::Modern::Document object that holds that schema
816# - the path relative to the document root for this schema
817# - the specification version that applies to this schema
818# - the vocabularies to use when considering schema keywords
819# - the config overrides to set when considering schema keywords
820# creates a Document and adds it to the resource index, if not already present.
82114064327.6ms
# spent 19.3s (2.16+17.1) within JSON::Schema::Modern::_fetch_from_uri which was called 46881 times, avg 412µs/call: # 41707 times (2.07s+16.1s) by JSON::Schema::Modern::Vocabulary::eval_subschema_at_uri at line 72 of JSON/Schema/Modern/Vocabulary.pm, avg 435µs/call # 2586 times (53.1ms+609ms) by JSON::Schema::Modern::Vocabulary::Core::_eval_keyword_dynamicRef at line 223 of JSON/Schema/Modern/Vocabulary/Core.pm, avg 256µs/call # 2586 times (41.4ms+441ms) by JSON::Schema::Modern::Vocabulary::Core::_eval_keyword_dynamicRef at line 235 of JSON/Schema/Modern/Vocabulary/Core.pm, avg 187µs/call # once (73µs+578µs) by JSON::Schema::Modern::evaluate at line 318 # once (88µs+463µs) by JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_schema at line 118 of JSON/Schema/Modern/Vocabulary/Core.pm
sub _fetch_from_uri ($self, $uri) {
8224688118.0ms145µs $uri = Mojo::URL->new($uri) if not is_ref($uri);
# spent 45µs making 1 call to Mojo::URL::new
8234688150.9ms4688136.7ms my $fragment = $uri->fragment;
# spent 36.7ms making 46881 calls to Mojo::URL::fragment, avg 783ns/call
824
8254688163.7ms2101817.1ms if (not length($fragment) or $fragment =~ m{^/}) {
# spent 17.1ms making 21018 calls to JSON::Schema::Modern::CORE:match, avg 814ns/call
8263912367.9ms782461.96s my $base = $uri->clone->fragment(undef);
# spent 1.92s making 39123 calls to Mojo::URL::clone, avg 49µs/call # spent 43.2ms making 39123 calls to Mojo::URL::fragment, avg 1µs/call
8273912367.6ms391236.36s if (my $resource = $self->_get_or_load_resource($base)) {
# spent 6.36s making 39123 calls to JSON::Schema::Modern::_get_or_load_resource, avg 163µs/call
82839123138ms39123752ms my $subschema = $resource->{document}->get(my $document_path = $resource->{path}.($fragment//''));
# spent 752ms making 39123 calls to Mojo::JSON::Pointer::get, avg 19µs/call
8293912311.5ms return if not defined $subschema;
8303912316.5ms my $document = $resource->{document};
831 my $closest_resource = first { !length($_->[1]{path}) # document root
83239123212ms || length($document_path)
833 && $document_path =~ m{^\Q$_->[1]{path}\E(?:/|\z)} } # path is above present location
834 sort { length($b->[1]{path}) <=> length($a->[1]{path}) } # sort by length, descending
83539123614ms2957955.13s grep { not length Mojo::URL->new($_->[0])->fragment } # omit anchors
# spent 4.19s making 89213 calls to Mojo::URL::new, avg 47µs/call # spent 702ms making 39123 calls to JSON::Schema::Modern::Document::resource_pairs, avg 18µs/call # spent 115ms making 39123 calls to List::Util::first, avg 3µs/call # spent 72.4ms making 39123 calls to JSON::Schema::Modern::CORE:sort, avg 2µs/call # spent 55.8ms making 89213 calls to Mojo::URL::fragment, avg 625ns/call
836 $document->resource_pairs;
837
838 my $canonical_uri = $closest_resource->[1]{canonical_uri}->clone
83939123136ms782461.38s ->fragment(substr($document_path, length($closest_resource->[1]{path})));
# spent 1.32s making 39123 calls to Mojo::URL::clone, avg 34µs/call # spent 67.7ms making 39123 calls to Mojo::URL::fragment, avg 2µs/call
8403912356.6ms6498639.7ms $canonical_uri->fragment(undef) if not length($canonical_uri->fragment);
# spent 39.7ms making 64986 calls to Mojo::URL::fragment, avg 611ns/call
841 return {
842 schema => $subschema,
843 canonical_uri => $canonical_uri,
844 document => $document,
845 document_path => $document_path,
84639123416ms $resource->%{qw(specification_version vocabularies configs)}, # reference, not copy
847 };
848 }
849 }
850 else { # we are following a URI with a plain-name fragment
851775812.1ms77581.03s if (my $resource = $self->_get_resource($uri)) {
# spent 1.03s making 7758 calls to JSON::Schema::Modern::_get_resource, avg 133µs/call
852775817.0ms7758174ms my $subschema = $resource->{document}->get($resource->{path});
# spent 174ms making 7758 calls to Mojo::JSON::Pointer::get, avg 22µs/call
8537758946µs return if not defined $subschema;
854 return {
855 schema => $subschema,
856 canonical_uri => $resource->{canonical_uri}->clone, # this is *not* the anchor-containing URI
857 document => $resource->{document},
858 document_path => $resource->{path},
859775871.7ms7758249ms $resource->%{qw(specification_version vocabularies configs)}, # reference, not copy
# spent 249ms making 7758 calls to Mojo::URL::clone, avg 32µs/call
860 };
861 }
862 }
863}
864
865# used for internal encoding as well (when caching serialized schemas)
866has _json_decoder => (
867 is => 'ro',
868 isa => HasMethods[qw(encode decode)],
869 lazy => 1,
87017µs135µs
# spent 43µs (8+35) within JSON::Schema::Modern::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/JSON/Schema/Modern.pm:870] which was called: # once (8µs+35µs) by JSON::Schema::Modern::_json_decoder at line 23 of (eval 362)[Sub/Quote.pm:3]
default => sub { JSON::MaybeXS->new(allow_nonref => 1, canonical => 1, utf8 => 1, allow_bignum => 1, convert_blessed => 1) },
# spent 35µs making 1 call to JSON::MaybeXS::new
87119µs23.72ms);
# spent 2.37ms making 1 call to Types::Standard::HasMethods # spent 1.35ms making 1 call to MooX::HandlesVia::has
872
873# since media types are case-insensitive, all type names must be foldcased on insertion.
874has _media_type => (
875 is => 'bare',
876 isa => my $media_type_type = Map[Str->where(q{$_ eq CORE::fc($_)}), CodeRef],
877 handles_via => 'Hash',
878 handles => {
879 get_media_type => 'get',
880 add_media_type => 'set',
881 _media_types => 'keys',
882 },
883 lazy => 1,
884 default => sub ($self) {
885 my $_json_media_type = sub ($content_ref) {
886 \ JSON::MaybeXS->new(allow_nonref => 1, utf8 => 0)->decode($content_ref->$*);
887 };
888 +{
889 # note: utf-8 decoding is NOT done, as we can't be sure that's the correct charset!
890 'application/json' => $_json_media_type,
891 'application/schema+json' => $_json_media_type,
892 'application/schema-instance+json' => $_json_media_type,
893 map +($_ => sub ($content_ref) { $content_ref }),
894 qw(text/plain application/octet-stream),
895 };
896 },
897117µs55.54ms);
# spent 2.81ms making 1 call to MooX::HandlesVia::has # spent 2.53ms making 1 call to Types::Standard::Map # spent 196µs making 1 call to Type::Tiny::where # spent 3µs making 1 call to Types::Standard::Str # spent 1µs making 1 call to Types::Standard::CodeRef
898
899# get_media_type('TExT/bloop') will match an entry for 'text/*' or '*/*'
900# TODO: support queries for application/schema+json to match entry of application/json
901around get_media_type => sub ($orig, $self, $type) {
902 my $mt = $self->$orig(fc $type);
903 return $mt if $mt;
904
905 return $self->$orig((first { m{([^/]+)/\*$} && fc($type) =~ m{^\Q$1\E/[^/]+$} } $self->_media_types)
906 // '*/*');
90715µs1244µs};
# spent 244µs making 1 call to Moo::around
908
90914µs1312µsbefore add_media_type => sub ($self, $type, $sub) { $media_type_type->({ $type => $sub }) };
# spent 312µs making 1 call to Moo::before
910
911has _encoding => (
912 is => 'bare',
913 isa => HashRef[CodeRef],
914 handles_via => 'Hash',
915 handles => {
916 get_encoding => 'get',
917 add_encoding => 'set',
918 },
919 lazy => 1,
920 default => sub ($self) {
921 +{
922 identity => sub ($content_ref) { $content_ref },
923 base64 => sub ($content_ref) {
924 die "invalid characters in base64 string"
925 if $content_ref->$* =~ m{[^A-Za-z0-9+/=]} or $content_ref->$* =~ m{=(?=[^=])};
926 require MIME::Base64; \ MIME::Base64::decode($content_ref->$*);
927 },
928 };
929 },
930113µs32.79ms);
# spent 2.40ms making 1 call to MooX::HandlesVia::has # spent 383µs making 1 call to Types::Standard::HashRef # spent 3µs making 1 call to Types::Standard::CodeRef
931
932sub FREEZE ($self, $serializer) {
933 my $data = +{ %$self };
934 # Cpanel::JSON::XS doesn't serialize: https://github.com/Sereal/Sereal/issues/266
935 # coderefs can't serialize cleanly and must be re-added by the user.
936 delete $data->@{qw(_json_decoder _format_validations _media_type _encoding)};
937 return $data;
938}
939
940sub THAW ($class, $serializer, $data) {
941 my $self = bless($data, $class);
942
943 # load all vocabulary classes
944 require_module($_) foreach uniq map $_->{vocabularies}->@*, $self->_canonical_resources;
945
946 return $self;
947}
948
9491108µs1;
950
9511171µs11.55ms__END__
 
# spent 14µs within JSON::Schema::Modern::CACHED_METASCHEMAS which was called 26 times, avg 538ns/call: # 18 times (9µs+0s) by JSON::Schema::Modern::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/JSON/Schema/Modern.pm:646] at line 622, avg 500ns/call # 8 times (5µs+0s) by JSON::Schema::Modern::_get_or_load_resource at line 784, avg 625ns/call
sub JSON::Schema::Modern::CACHED_METASCHEMAS; # xsub
# spent 307ms within JSON::Schema::Modern::CORE:match which was called 2123434 times, avg 145ns/call: # 2015087 times (238ms+0s) by JSON::Schema::Modern::_eval_subschema at line 499, avg 118ns/call # 87311 times (51.7ms+0s) by JSON::Schema::Modern::_eval_subschema at line 577, avg 592ns/call # 21018 times (17.1ms+0s) by JSON::Schema::Modern::_fetch_from_uri at line 825, avg 814ns/call # 18 times (7µs+0s) by JSON::Schema::Modern::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/JSON/Schema/Modern.pm:646] at line 642, avg 389ns/call
sub JSON::Schema::Modern::CORE:match; # opcode
# spent 80.4ms within JSON::Schema::Modern::CORE:qr which was called 87311 times, avg 921ns/call: # 87311 times (80.4ms+0s) by JSON::Schema::Modern::_eval_subschema at line 577, avg 921ns/call
sub JSON::Schema::Modern::CORE:qr; # opcode
# spent 87.5ms within JSON::Schema::Modern::CORE:regcomp which was called 87311 times, avg 1µs/call: # 87311 times (87.5ms+0s) by JSON::Schema::Modern::_eval_subschema at line 577, avg 1µs/call
sub JSON::Schema::Modern::CORE:regcomp; # opcode
# spent 98.7ms within JSON::Schema::Modern::CORE:sort which was called 128929 times, avg 766ns/call: # 87311 times (23.3ms+0s) by JSON::Schema::Modern::_eval_subschema at line 577, avg 267ns/call # 39123 times (72.4ms+0s) by JSON::Schema::Modern::_fetch_from_uri at line 835, avg 2µs/call # 2480 times (2.92ms+0s) by JSON::Schema::Modern::_traverse_subschema at line 477, avg 1µs/call # 15 times (28µs+0s) by JSON::Schema::Modern::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/JSON/Schema/Modern.pm:646] at line 617, avg 2µs/call
sub JSON::Schema::Modern::CORE:sort; # opcode
# spent 376ms within JSON::Schema::Modern::CORE:subst which was called 953819 times, avg 394ns/call: # 641165 times (232ms+0s) by JSON::Schema::Modern::_eval_subschema at line 529, avg 363ns/call # 308273 times (141ms+0s) by JSON::Schema::Modern::_eval_subschema at line 544, avg 459ns/call # 4381 times (1.86ms+0s) by JSON::Schema::Modern::_traverse_subschema at line 455, avg 425ns/call
sub JSON::Schema::Modern::CORE:subst; # opcode
# spent 12µs within JSON::Schema::Modern::METASCHEMA_URIS which was called 15 times, avg 800ns/call: # 15 times (12µs+0s) by JSON::Schema::Modern::traverse at line 262, avg 800ns/call
sub JSON::Schema::Modern::METASCHEMA_URIS; # xsub
# spent 1µs within JSON::Schema::Modern::SPECIFICATION_VERSION_DEFAULT which was called: # once (1µs+0s) by JSON::Schema::Modern::Document::OpenAPI::traverse at line 76 of JSON/Schema/Modern/Document/OpenAPI.pm
sub JSON::Schema::Modern::SPECIFICATION_VERSION_DEFAULT; # xsub
# spent 1µs within JSON::Schema::Modern::__ANON__ which was called 2 times, avg 500ns/call: # once (1µs+0s) by JSON::Schema::Modern::BEGIN@34 at line 34 # once (0s+0s) by JSON::Schema::Modern::BEGIN@33 at line 33
sub JSON::Schema::Modern::__ANON__; # xsub