line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package JSV::Context; |
2
|
|
|
|
|
|
|
|
3
|
44
|
|
|
44
|
|
1101
|
use strict; |
|
44
|
|
|
|
|
73
|
|
|
44
|
|
|
|
|
3338
|
|
4
|
44
|
|
|
44
|
|
224
|
use warnings; |
|
44
|
|
|
|
|
63
|
|
|
44
|
|
|
|
|
6095
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
use Class::Accessor::Lite ( |
7
|
44
|
|
|
|
|
497
|
new => 1, |
8
|
|
|
|
|
|
|
rw => [qw/ |
9
|
|
|
|
|
|
|
keywords |
10
|
|
|
|
|
|
|
reference |
11
|
|
|
|
|
|
|
original_schema |
12
|
|
|
|
|
|
|
throw_error |
13
|
|
|
|
|
|
|
throw_immediate |
14
|
|
|
|
|
|
|
enable_history |
15
|
|
|
|
|
|
|
enable_format |
16
|
|
|
|
|
|
|
formats |
17
|
|
|
|
|
|
|
history |
18
|
|
|
|
|
|
|
json |
19
|
|
|
|
|
|
|
loose_type |
20
|
|
|
|
|
|
|
/], |
21
|
|
|
|
|
|
|
ro => [qw/ |
22
|
|
|
|
|
|
|
errors |
23
|
|
|
|
|
|
|
current_type |
24
|
|
|
|
|
|
|
current_keyword |
25
|
|
|
|
|
|
|
current_pointer |
26
|
|
|
|
|
|
|
current_instance |
27
|
|
|
|
|
|
|
current_schema |
28
|
|
|
|
|
|
|
current_schema_pointer |
29
|
|
|
|
|
|
|
schema_pointer_history |
30
|
|
|
|
|
|
|
/], |
31
|
44
|
|
|
44
|
|
203
|
); |
|
44
|
|
|
|
|
64
|
|
32
|
|
|
|
|
|
|
|
33
|
44
|
|
|
44
|
|
14699
|
use Carp qw(croak); |
|
44
|
|
|
|
|
79
|
|
|
44
|
|
|
|
|
2563
|
|
34
|
44
|
|
|
44
|
|
186
|
use JSON; |
|
44
|
|
|
|
|
307
|
|
|
44
|
|
|
|
|
274
|
|
35
|
44
|
|
|
44
|
|
7147
|
use JSV::Keyword qw(:constants); |
|
44
|
|
|
|
|
71
|
|
|
44
|
|
|
|
|
8244
|
|
36
|
44
|
|
|
44
|
|
21081
|
use JSV::Util::Type qw(detect_instance_type detect_instance_type_loose); |
|
44
|
|
|
|
|
333
|
|
|
44
|
|
|
|
|
4699
|
|
37
|
44
|
|
|
44
|
|
30263
|
use JSV::Result; |
|
44
|
|
|
|
|
122
|
|
|
44
|
|
|
|
|
1243
|
|
38
|
44
|
|
|
44
|
|
221
|
use Clone qw(clone); |
|
44
|
|
|
|
|
72
|
|
|
44
|
|
|
|
|
59305
|
|
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
sub validate { |
41
|
1381
|
|
|
1381
|
0
|
2494
|
my ($self, $schema, $instance) = @_; |
42
|
|
|
|
|
|
|
|
43
|
1381
|
100
|
|
|
|
3603
|
local $self->{current_type} = !$self->loose_type ? detect_instance_type($instance) |
44
|
|
|
|
|
|
|
: detect_instance_type_loose($instance); |
45
|
|
|
|
|
|
|
|
46
|
1381
|
|
|
|
|
3999
|
local $self->{cleanup_callbacks} = []; |
47
|
|
|
|
|
|
|
|
48
|
1381
|
|
|
|
|
1820
|
my $rv; |
49
|
1381
|
|
|
|
|
2113
|
eval { |
50
|
1381
|
|
|
|
|
1788
|
for my $keyword (@{ $self->keywords->{INSTANCE_TYPE_ANY()} }) { |
|
1381
|
|
|
|
|
6965
|
|
51
|
11048
|
100
|
|
|
|
47853
|
next unless exists $schema->{$keyword->keyword}; |
52
|
1222
|
|
|
|
|
2974
|
$self->apply_keyword($keyword, $schema, $instance); |
53
|
|
|
|
|
|
|
} |
54
|
|
|
|
|
|
|
|
55
|
1381
|
100
|
|
|
|
9891
|
if ($self->is_matched_types(qw/integer_or_string number_or_string/)) { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
56
|
210
|
|
|
|
|
272
|
for my $keyword ( |
57
|
210
|
|
|
|
|
781
|
@{ $self->keywords->{INSTANCE_TYPE_NUMERIC()} }, |
58
|
210
|
|
|
|
|
1320
|
@{ $self->keywords->{INSTANCE_TYPE_STRING()} } |
59
|
|
|
|
|
|
|
) { |
60
|
1470
|
100
|
|
|
|
7217
|
next unless exists $schema->{$keyword->keyword}; |
61
|
83
|
|
|
|
|
672
|
$self->apply_keyword($keyword, $schema, $instance); |
62
|
|
|
|
|
|
|
} |
63
|
|
|
|
|
|
|
} |
64
|
|
|
|
|
|
|
elsif ($self->is_matched_types(qw/integer number/)) { |
65
|
237
|
|
|
|
|
353
|
for my $keyword (@{ $self->keywords->{INSTANCE_TYPE_NUMERIC()} }) { |
|
237
|
|
|
|
|
1166
|
|
66
|
711
|
100
|
|
|
|
4897
|
next unless exists $schema->{$keyword->keyword}; |
67
|
62
|
|
|
|
|
180
|
$self->apply_keyword($keyword, $schema, $instance); |
68
|
|
|
|
|
|
|
} |
69
|
|
|
|
|
|
|
} |
70
|
|
|
|
|
|
|
elsif ($self->is_matched_types(qw/string/)) { |
71
|
403
|
|
|
|
|
545
|
for my $keyword (@{ $self->keywords->{INSTANCE_TYPE_STRING()} }) { |
|
403
|
|
|
|
|
1290
|
|
72
|
1612
|
100
|
|
|
|
8223
|
next unless exists $schema->{$keyword->keyword}; |
73
|
72
|
|
|
|
|
174
|
$self->apply_keyword($keyword, $schema, $instance); |
74
|
|
|
|
|
|
|
} |
75
|
|
|
|
|
|
|
} |
76
|
|
|
|
|
|
|
elsif ($self->current_type eq "array") { |
77
|
155
|
|
|
|
|
1026
|
for my $keyword (@{ $self->keywords->{INSTANCE_TYPE_ARRAY()} }) { |
|
155
|
|
|
|
|
413
|
|
78
|
620
|
100
|
|
|
|
4227
|
next unless exists $schema->{$keyword->keyword}; |
79
|
137
|
|
|
|
|
329
|
$self->apply_keyword($keyword, $schema, $instance); |
80
|
|
|
|
|
|
|
} |
81
|
|
|
|
|
|
|
} |
82
|
|
|
|
|
|
|
elsif ($self->current_type eq "object") { |
83
|
328
|
|
|
|
|
3845
|
for my $keyword (@{ $self->keywords->{INSTANCE_TYPE_OBJECT()} }) { |
|
328
|
|
|
|
|
891
|
|
84
|
|
|
|
|
|
|
### for addtionalProperties, patternProperties keyword without properties keyword |
85
|
1640
|
50
|
|
|
|
7833
|
next unless ( ( grep { defined $_ && exists $schema->{$_} } ($keyword->keyword, @{$keyword->additional_keywords}) ) > 0 ); |
|
2296
|
100
|
|
|
|
10157
|
|
|
1640
|
|
|
|
|
4641
|
|
86
|
|
|
|
|
|
|
# next unless exists $schema->{$_->keyword}; |
87
|
418
|
|
|
|
|
1097
|
$self->apply_keyword($keyword, $schema, $instance); |
88
|
|
|
|
|
|
|
} |
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
|
91
|
1381
|
50
|
|
|
|
6177
|
$rv = JSV::Result->new( |
92
|
|
|
|
|
|
|
($self->enable_history ? (history => $self->history) : ()), |
93
|
|
|
|
|
|
|
); |
94
|
|
|
|
|
|
|
}; |
95
|
1381
|
50
|
|
|
|
3711
|
if ( my $e = $@ ) { |
96
|
0
|
|
|
|
|
0
|
$self->log_error(sprintf("Unexpected error: %s", $e)); |
97
|
|
|
|
|
|
|
} |
98
|
|
|
|
|
|
|
|
99
|
1381
|
|
|
|
|
1705
|
while (my $cb = pop @{ $self->{cleanup_callbacks} }) { |
|
1502
|
|
|
|
|
4676
|
|
100
|
121
|
|
|
|
|
282
|
$cb->(); |
101
|
|
|
|
|
|
|
} |
102
|
|
|
|
|
|
|
|
103
|
1381
|
100
|
|
|
|
1721
|
if ( scalar @{ $self->errors } ) { |
|
1381
|
|
|
|
|
4260
|
|
104
|
562
|
50
|
|
|
|
4312
|
$rv = JSV::Result->new( |
105
|
|
|
|
|
|
|
errors => $self->errors, |
106
|
|
|
|
|
|
|
($self->enable_history ? (history => $self->history) : ()), |
107
|
|
|
|
|
|
|
); |
108
|
562
|
50
|
|
|
|
2591
|
if ( $self->throw_error ) { |
109
|
0
|
|
|
|
|
0
|
croak $rv; |
110
|
|
|
|
|
|
|
} |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
|
113
|
1381
|
|
|
|
|
21944
|
return $rv; |
114
|
|
|
|
|
|
|
} |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
sub apply_keyword { |
117
|
1994
|
|
|
1994
|
0
|
3925
|
my ($self, $keyword, $schema, $instance) = @_; |
118
|
|
|
|
|
|
|
|
119
|
1994
|
|
|
|
|
5838
|
local $self->{current_keyword} = $keyword->keyword; |
120
|
1994
|
|
|
|
|
3623
|
local $self->{current_schema} = $schema; |
121
|
1994
|
|
|
|
|
3861
|
local $self->{current_instance} = $instance; |
122
|
|
|
|
|
|
|
|
123
|
1994
|
|
|
|
|
6702
|
$keyword->validate($self, $schema, $instance); |
124
|
|
|
|
|
|
|
|
125
|
1994
|
50
|
33
|
|
|
8589
|
if ( $ENV{JSV_DEBUG} || $self->enable_history ) { |
126
|
0
|
|
|
|
|
0
|
push @{ $self->history }, +{ |
|
0
|
|
|
|
|
0
|
|
127
|
|
|
|
|
|
|
keyword => $self->current_keyword, |
128
|
|
|
|
|
|
|
pointer => $self->current_pointer, |
129
|
|
|
|
|
|
|
schema => $self->current_schema, |
130
|
|
|
|
|
|
|
instance => $self->resolve_current_instance, |
131
|
|
|
|
|
|
|
}; |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
} |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
sub log_error { |
136
|
394
|
|
|
394
|
0
|
765
|
my ($self, $message) = @_; |
137
|
|
|
|
|
|
|
|
138
|
394
|
|
|
|
|
1145
|
my $error = +{ |
139
|
|
|
|
|
|
|
keyword => $self->current_keyword, |
140
|
|
|
|
|
|
|
pointer => $self->current_pointer, |
141
|
|
|
|
|
|
|
schema => $self->current_schema, |
142
|
|
|
|
|
|
|
instance => $self->resolve_current_instance, |
143
|
|
|
|
|
|
|
schema_pointer => $self->current_schema_pointer, |
144
|
|
|
|
|
|
|
schema_pointer_history => clone($self->schema_pointer_history), |
145
|
|
|
|
|
|
|
message => $message, |
146
|
|
|
|
|
|
|
}; |
147
|
|
|
|
|
|
|
|
148
|
394
|
50
|
|
|
|
10585
|
if ( $ENV{JSV_DEBUG} ) { |
149
|
0
|
|
|
|
|
0
|
require Data::Dump; |
150
|
0
|
|
|
|
|
0
|
warn "history = " . Data::Dump::dump($self->history); |
151
|
0
|
|
|
|
|
0
|
warn "error = " . Data::Dump::dump($error); |
152
|
|
|
|
|
|
|
} |
153
|
|
|
|
|
|
|
|
154
|
394
|
50
|
|
|
|
1178
|
if ( $self->throw_immediate ) { |
155
|
0
|
0
|
|
|
|
0
|
croak JSV::Result->new( |
156
|
|
|
|
|
|
|
error => $error, |
157
|
|
|
|
|
|
|
($self->enable_history ? (history => $self->history) : ()), |
158
|
|
|
|
|
|
|
); |
159
|
|
|
|
|
|
|
} |
160
|
|
|
|
|
|
|
else { |
161
|
394
|
|
|
|
|
2063
|
push @{ $self->{errors} }, $error; |
|
394
|
|
|
|
|
1821
|
|
162
|
|
|
|
|
|
|
} |
163
|
|
|
|
|
|
|
} |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
sub resolve_current_instance { |
166
|
394
|
|
|
394
|
0
|
5156
|
my $self = shift; |
167
|
|
|
|
|
|
|
|
168
|
394
|
|
|
|
|
504
|
my $instance; |
169
|
394
|
100
|
|
|
|
1025
|
if ( JSON::is_bool($self->current_instance) ) { |
170
|
11
|
100
|
|
|
|
125
|
if ( $self->current_instance == JSON::true ) { |
171
|
9
|
|
|
|
|
164
|
$instance = "true"; |
172
|
|
|
|
|
|
|
} |
173
|
|
|
|
|
|
|
else { |
174
|
2
|
|
|
|
|
29
|
$instance = "false"; |
175
|
|
|
|
|
|
|
} |
176
|
|
|
|
|
|
|
} |
177
|
|
|
|
|
|
|
else { |
178
|
383
|
|
|
|
|
4456
|
$instance = $self->current_instance; |
179
|
|
|
|
|
|
|
} |
180
|
|
|
|
|
|
|
|
181
|
394
|
|
|
|
|
3111
|
return $instance; |
182
|
|
|
|
|
|
|
} |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
sub is_matched_types { |
185
|
3486
|
|
|
3486
|
0
|
7094
|
my ($self, @types) = @_; |
186
|
|
|
|
|
|
|
|
187
|
3486
|
100
|
|
|
|
4879
|
return (grep { $self->{current_type} eq $_ } @types) > 0 ? 1 : 0; |
|
6038
|
|
|
|
|
23193
|
|
188
|
|
|
|
|
|
|
} |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
sub register_cleanup_callback { |
191
|
121
|
|
|
121
|
0
|
209
|
my ($self, $cb) = @_; |
192
|
|
|
|
|
|
|
|
193
|
121
|
|
|
|
|
141
|
push @{ $self->{cleanup_callbacks} }, $cb; |
|
121
|
|
|
|
|
341
|
|
194
|
|
|
|
|
|
|
} |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
1; |