line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#!/usr/bin/perl |
2
|
|
|
|
|
|
|
|
3
|
37
|
|
|
37
|
|
272
|
use strict; |
|
37
|
|
|
|
|
105
|
|
|
37
|
|
|
|
|
1130
|
|
4
|
37
|
|
|
37
|
|
237
|
use warnings; |
|
37
|
|
|
|
|
100
|
|
|
37
|
|
|
|
|
1092
|
|
5
|
|
|
|
|
|
|
|
6
|
37
|
|
|
37
|
|
246
|
use WWW::Shopify::Liquid; |
|
37
|
|
|
|
|
101
|
|
|
37
|
|
|
|
|
1315
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
package WWW::Shopify::Liquid::Optimizer; |
9
|
37
|
|
|
37
|
|
239
|
use base 'WWW::Shopify::Liquid::Pipeline'; |
|
37
|
|
|
|
|
134
|
|
|
37
|
|
|
|
|
3810
|
|
10
|
37
|
|
|
37
|
|
11928
|
use WWW::Shopify::Liquid::Security; |
|
37
|
|
|
|
|
127
|
|
|
37
|
|
|
|
|
1109
|
|
11
|
|
|
|
|
|
|
|
12
|
37
|
|
|
37
|
|
270
|
use Clone qw(clone); |
|
37
|
|
|
|
|
102
|
|
|
37
|
|
|
|
|
28364
|
|
13
|
|
|
|
|
|
|
sub new { |
14
|
85
|
|
|
85
|
0
|
295
|
my $package = shift; |
15
|
85
|
|
|
|
|
493
|
my $self = bless { |
16
|
|
|
|
|
|
|
clone_hash => 1, |
17
|
|
|
|
|
|
|
remove_assignment => 0, |
18
|
|
|
|
|
|
|
max_unrolling => 1000, |
19
|
|
|
|
|
|
|
max_inclusion_depth => 5, |
20
|
|
|
|
|
|
|
timeout => undef, |
21
|
|
|
|
|
|
|
inclusion_context => undef, |
22
|
|
|
|
|
|
|
inclusion_depth => 0, |
23
|
|
|
|
|
|
|
security => WWW::Shopify::Liquid::Security->new, |
24
|
|
|
|
|
|
|
conditional_state => [], |
25
|
|
|
|
|
|
|
@_ |
26
|
|
|
|
|
|
|
}, $package; |
27
|
85
|
|
|
|
|
838
|
return $self; |
28
|
|
|
|
|
|
|
} |
29
|
110
|
50
|
|
110
|
0
|
312
|
sub clone_hash { $_[0]->{clone_hash} = $_[1] if defined $_[1]; return $_[0]->{clone_hash}; } |
|
110
|
|
|
|
|
1593
|
|
30
|
24
|
100
|
|
24
|
0
|
96
|
sub security { $_[0]->{security} = $_[1] if defined $_[1]; return $_[0]->{security}; } |
|
24
|
|
|
|
|
205
|
|
31
|
0
|
0
|
|
0
|
0
|
0
|
sub max_inclusion_depth { $_[0]->{max_inclusion_depth} = $_[1] if defined $_[1]; return $_[0]->{max_inclusion_depth}; } |
|
0
|
|
|
|
|
0
|
|
32
|
0
|
0
|
|
0
|
0
|
0
|
sub inclusion_context { $_[0]->{inclusion_context} = $_[1] if defined $_[1]; return $_[0]->{inclusion_context}; } |
|
0
|
|
|
|
|
0
|
|
33
|
0
|
0
|
|
0
|
0
|
0
|
sub inclusion_depth { $_[0]->{inclusion_depth} = $_[1] if defined $_[1]; return $_[0]->{inclusion_depth}; } |
|
0
|
|
|
|
|
0
|
|
34
|
|
|
|
|
|
|
# If we're inside a non-fully-resolved branch, then this is flagged as true; means we can't actually assign things. |
35
|
|
|
|
|
|
|
sub push_conditional_state { |
36
|
33
|
|
|
33
|
0
|
91
|
my ($self) = @_; |
37
|
33
|
|
|
|
|
64
|
push(@{$self->{conditional_state}}, { }); |
|
33
|
|
|
|
|
132
|
|
38
|
|
|
|
|
|
|
} |
39
|
|
|
|
|
|
|
sub conditional_state { |
40
|
30
|
100
|
|
30
|
0
|
72
|
return undef unless int(@{$_[0]->{conditional_state}}) > 0; |
|
30
|
|
|
|
|
177
|
|
41
|
5
|
|
|
|
|
16
|
return $_[0]->{conditional_state}->[-1]; |
42
|
|
|
|
|
|
|
} |
43
|
|
|
|
|
|
|
# Removes the variable from the hash, preventing further optimization, as post unevaluated conditional block, the status of the variable will be uncertain. |
44
|
|
|
|
|
|
|
sub flag_conditional_uncertainty { |
45
|
27
|
|
|
27
|
0
|
105
|
my ($self, $idarray) = @_; |
46
|
27
|
|
|
|
|
124
|
my $state = $self->conditional_state; |
47
|
27
|
100
|
|
|
|
120
|
return undef unless defined $state; |
48
|
5
|
|
|
|
|
21
|
my $id = join(".", @$idarray); |
49
|
5
|
|
|
|
|
23
|
$state->{$id} = $idarray; |
50
|
|
|
|
|
|
|
} |
51
|
|
|
|
|
|
|
sub pop_conditional_state { |
52
|
33
|
|
|
33
|
0
|
98
|
my ($self, $hash) = @_; |
53
|
33
|
|
|
|
|
63
|
my $state = pop(@{$self->{conditional_state}}); |
|
33
|
|
|
|
|
99
|
|
54
|
33
|
|
|
|
|
184
|
for (values(%$state)) { |
55
|
5
|
|
|
|
|
32
|
my ($reference, $parent) = $self->variable_reference($hash, $_); |
56
|
|
|
|
|
|
|
# If the parent is a hash, remove the element from the hash. |
57
|
5
|
50
|
|
|
|
44
|
delete $parent->{$_->[-1]} if ref($parent) eq 'HASH'; |
58
|
|
|
|
|
|
|
} |
59
|
|
|
|
|
|
|
} |
60
|
|
|
|
|
|
|
# Depending on the type of optimization, you may or may not want to remove assignment or capture blocks. |
61
|
|
|
|
|
|
|
# In cases where this liquid may be inserted inside other liquid, you may want to set this to 0, as the assignments may affect external objects. |
62
|
|
|
|
|
|
|
# In cases where the liquid is the only thing being evaluated, with no outside context, it's fine to set this 1. |
63
|
33
|
100
|
|
33
|
0
|
9006
|
sub remove_assignment { $_[0]->{remove_assignment} = $_[1] if defined $_[1]; return $_[0]->{remove_assignment}; } |
|
33
|
|
|
|
|
180
|
|
64
|
55
|
50
|
|
55
|
0
|
207
|
sub timeout { $_[0]->{timeout} = $_[1] if defined $_[1]; return $_[0]->{timeout}; } |
|
55
|
|
|
|
|
210
|
|
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
sub optimize { |
67
|
55
|
|
|
55
|
0
|
10063
|
my ($self, $hash, $ast) = @_; |
68
|
55
|
50
|
|
|
|
226
|
return undef unless $ast; |
69
|
55
|
50
|
33
|
|
|
301
|
my $hash_clone = $self->clone_hash && $self->clone_hash == 1 ? clone($hash) : $hash; |
70
|
55
|
|
|
|
|
184
|
my $result; |
71
|
|
|
|
|
|
|
{ |
72
|
55
|
|
|
0
|
|
114
|
local $SIG{ALRM} = sub { die new WWW::Shopify::Liquid::Exception::Timeout(); }; |
|
55
|
|
|
|
|
1017
|
|
|
0
|
|
|
|
|
0
|
|
73
|
55
|
50
|
|
|
|
305
|
alarm $self->timeout if $self->timeout; |
74
|
55
|
|
|
|
|
350
|
$result = $ast->optimize($self, $hash_clone); |
75
|
54
|
|
|
|
|
823
|
alarm 0; |
76
|
|
|
|
|
|
|
} |
77
|
54
|
100
|
|
|
|
422
|
return !ref($result) ? WWW::Shopify::Liquid::Token::Text->new(undef, defined $result ? $result : '') : $result; |
|
|
100
|
|
|
|
|
|
78
|
|
|
|
|
|
|
} |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
1; |