line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Mason::Interp; |
2
|
|
|
|
|
|
|
$Mason::Interp::VERSION = '2.22'; |
3
|
20
|
|
|
20
|
|
122
|
use Carp; |
|
20
|
|
|
|
|
52
|
|
|
20
|
|
|
|
|
1314
|
|
4
|
20
|
|
|
20
|
|
18160
|
use Devel::GlobalDestruction; |
|
20
|
|
|
|
|
63935
|
|
|
20
|
|
|
|
|
324
|
|
5
|
20
|
|
|
20
|
|
1889
|
use File::Basename; |
|
20
|
|
|
|
|
58
|
|
|
20
|
|
|
|
|
1300
|
|
6
|
20
|
|
|
20
|
|
119
|
use File::Path; |
|
20
|
|
|
|
|
218
|
|
|
20
|
|
|
|
|
1011
|
|
7
|
20
|
|
|
20
|
|
104
|
use File::Temp qw(tempdir); |
|
20
|
|
|
|
|
32
|
|
|
20
|
|
|
|
|
783
|
|
8
|
20
|
|
|
20
|
|
65691
|
use Guard; |
|
20
|
|
|
|
|
23464
|
|
|
20
|
|
|
|
|
1256
|
|
9
|
20
|
|
|
20
|
|
11674
|
use Mason::CodeCache; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
use Mason::Request; |
11
|
|
|
|
|
|
|
use Mason::Result; |
12
|
|
|
|
|
|
|
use Mason::Types; |
13
|
|
|
|
|
|
|
use Mason::Util |
14
|
|
|
|
|
|
|
qw(can_load catdir catfile combine_similar_paths find_wanted first_index is_absolute json_decode mason_canon_path read_file taint_is_on touch_file uniq write_file); |
15
|
|
|
|
|
|
|
use Class::Load; |
16
|
|
|
|
|
|
|
use Memoize; |
17
|
|
|
|
|
|
|
use Moose::Util::TypeConstraints; |
18
|
|
|
|
|
|
|
use Mason::Moose; |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
my $default_out = sub { print( $_[0] ) }; |
21
|
|
|
|
|
|
|
my $next_id = 0; |
22
|
|
|
|
|
|
|
my $max_depth = 16; |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
# Passed attributes |
25
|
|
|
|
|
|
|
# |
26
|
|
|
|
|
|
|
has 'allow_globals' => ( isa => 'ArrayRef[Str]', default => sub { [] }, trigger => sub { shift->_validate_allow_globals } ); |
27
|
|
|
|
|
|
|
has 'autobase_names' => ( isa => 'ArrayRef[Str]', lazy_build => 1 ); |
28
|
|
|
|
|
|
|
has 'autoextend_request_path' => ( isa => 'Bool', default => 1 ); |
29
|
|
|
|
|
|
|
has 'class_header' => ( default => '' ); |
30
|
|
|
|
|
|
|
has 'comp_root' => ( required => 1, isa => 'Mason::Types::CompRoot', coerce => 1 ); |
31
|
|
|
|
|
|
|
has 'component_class_prefix' => ( lazy_build => 1 ); |
32
|
|
|
|
|
|
|
has 'data_dir' => ( lazy_build => 1 ); |
33
|
|
|
|
|
|
|
has 'dhandler_names' => ( isa => 'ArrayRef[Str]', lazy_build => 1 ); |
34
|
|
|
|
|
|
|
has 'index_names' => ( isa => 'ArrayRef[Str]', lazy_build => 1 ); |
35
|
|
|
|
|
|
|
has 'mason_root_class' => ( required => 1 ); |
36
|
|
|
|
|
|
|
has 'no_source_line_numbers' => ( default => 0 ); |
37
|
|
|
|
|
|
|
has 'object_file_extension' => ( default => '.mobj' ); |
38
|
|
|
|
|
|
|
has 'plugins' => ( default => sub { [] } ); |
39
|
|
|
|
|
|
|
has 'pure_perl_extensions' => ( default => sub { ['.mp'] } ); |
40
|
|
|
|
|
|
|
has 'static_source' => (); |
41
|
|
|
|
|
|
|
has 'static_source_touch_file' => (); |
42
|
|
|
|
|
|
|
has 'top_level_extensions' => ( default => sub { ['.mc', '.mp'] } ); |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
# Derived attributes |
45
|
|
|
|
|
|
|
# |
46
|
|
|
|
|
|
|
has 'allowed_globals_hash' => ( init_arg => undef, lazy_build => 1 ); |
47
|
|
|
|
|
|
|
has 'code_cache' => ( init_arg => undef, lazy_build => 1 ); |
48
|
|
|
|
|
|
|
has 'distinct_string_count' => ( init_arg => undef, default => 0 ); |
49
|
|
|
|
|
|
|
has 'globals_package' => ( init_arg => undef, lazy_build => 1 ); |
50
|
|
|
|
|
|
|
has 'id' => ( init_arg => undef, default => sub { $next_id++ } ); |
51
|
|
|
|
|
|
|
has 'match_request_path' => ( init_arg => undef, lazy_build => 1 ); |
52
|
|
|
|
|
|
|
has 'pure_perl_regex' => ( lazy_build => 1 ); |
53
|
|
|
|
|
|
|
has 'request_params' => ( init_arg => undef ); |
54
|
|
|
|
|
|
|
has 'top_level_regex' => ( lazy_build => 1 ); |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
# Class overrides |
57
|
|
|
|
|
|
|
# |
58
|
|
|
|
|
|
|
CLASS->_define_class_override_methods(); |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
# Allow access to current interp while in load() |
61
|
|
|
|
|
|
|
# |
62
|
|
|
|
|
|
|
our ($current_load_interp); |
63
|
|
|
|
|
|
|
method current_load_interp () { $current_load_interp } |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
# |
66
|
|
|
|
|
|
|
# BUILD |
67
|
|
|
|
|
|
|
# |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
method BUILD ($params) { |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
# Initialize static source mode |
72
|
|
|
|
|
|
|
# |
73
|
|
|
|
|
|
|
if ( $self->{static_source} ) { |
74
|
|
|
|
|
|
|
$self->{static_source_touch_file} ||= catfile( $self->data_dir, 'purge.dat' ); |
75
|
|
|
|
|
|
|
$self->{static_source_touch_lastmod} = 0; |
76
|
|
|
|
|
|
|
$self->_check_static_source_touch_file(); |
77
|
|
|
|
|
|
|
} |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
# Separate out request parameters |
80
|
|
|
|
|
|
|
# |
81
|
|
|
|
|
|
|
$self->{request_params} = {}; |
82
|
|
|
|
|
|
|
my %is_request_attribute = |
83
|
|
|
|
|
|
|
map { ( $_->init_arg || $_->name, 1 ) } $self->request_class->meta->get_all_attributes(); |
84
|
|
|
|
|
|
|
foreach my $key ( keys(%$params) ) { |
85
|
|
|
|
|
|
|
if ( $is_request_attribute{$key} ) { |
86
|
|
|
|
|
|
|
$self->{request_params}->{$key} = delete( $params->{$key} ); |
87
|
|
|
|
|
|
|
} |
88
|
|
|
|
|
|
|
} |
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
method _build_allowed_globals_hash () { |
92
|
|
|
|
|
|
|
my @allow_globals = uniq( @{ $self->allow_globals } ); |
93
|
|
|
|
|
|
|
my @canon_globals = map { join( "", $self->_parse_global_spec($_) ) } @allow_globals; |
94
|
|
|
|
|
|
|
return { map { ( $_, 1 ) } @canon_globals }; |
95
|
|
|
|
|
|
|
} |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
method _build_globals_package () { |
98
|
|
|
|
|
|
|
return "Mason::Globals" . $self->id; |
99
|
|
|
|
|
|
|
} |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
method _build_autobase_names () { |
102
|
|
|
|
|
|
|
return [ map { "Base" . $_ } @{ $self->top_level_extensions } ]; |
103
|
|
|
|
|
|
|
} |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
method _build_code_cache () { |
106
|
|
|
|
|
|
|
return $self->code_cache_class->new(); |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
method _build_component_class_prefix () { |
110
|
|
|
|
|
|
|
return "MC" . $self->id; |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
method _build_data_dir () { |
114
|
|
|
|
|
|
|
return tempdir( 'mason-data-XXXX', TMPDIR => 1, CLEANUP => 1 ); |
115
|
|
|
|
|
|
|
} |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
method _build_dhandler_names () { |
118
|
|
|
|
|
|
|
return [ map { "dhandler" . $_ } @{ $self->top_level_extensions } ]; |
119
|
|
|
|
|
|
|
} |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
method _build_index_names () { |
122
|
|
|
|
|
|
|
return [ map { "index" . $_ } @{ $self->top_level_extensions } ]; |
123
|
|
|
|
|
|
|
} |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
method _build_pure_perl_regex () { |
126
|
|
|
|
|
|
|
my $extensions = $self->pure_perl_extensions; |
127
|
|
|
|
|
|
|
if ( !@$extensions ) { |
128
|
|
|
|
|
|
|
return qr/(?!)/; # matches nothing |
129
|
|
|
|
|
|
|
} |
130
|
|
|
|
|
|
|
else { |
131
|
|
|
|
|
|
|
my $regex = join( '|', @$extensions ) . '$'; |
132
|
|
|
|
|
|
|
return qr/$regex/; |
133
|
|
|
|
|
|
|
} |
134
|
|
|
|
|
|
|
} |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
method _build_top_level_regex () { |
137
|
|
|
|
|
|
|
my $extensions = $self->top_level_extensions; |
138
|
|
|
|
|
|
|
if ( !@$extensions ) { |
139
|
|
|
|
|
|
|
return qr/./; # matches everything |
140
|
|
|
|
|
|
|
} |
141
|
|
|
|
|
|
|
else { |
142
|
|
|
|
|
|
|
my $regex = join( '|', @$extensions ); |
143
|
|
|
|
|
|
|
if ( my @other_names = grep { !/$regex/ } @{ $self->dhandler_names }, |
144
|
|
|
|
|
|
|
@{ $self->index_names } ) |
145
|
|
|
|
|
|
|
{ |
146
|
|
|
|
|
|
|
$regex .= '|(?:/(?:' . join( '|', @other_names ) . '))'; |
147
|
|
|
|
|
|
|
} |
148
|
|
|
|
|
|
|
$regex = '(?:' . $regex . ')$'; |
149
|
|
|
|
|
|
|
return qr/$regex/; |
150
|
|
|
|
|
|
|
} |
151
|
|
|
|
|
|
|
} |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
# |
154
|
|
|
|
|
|
|
# PUBLIC METHODS |
155
|
|
|
|
|
|
|
# |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
method all_paths ($dir_path) { |
158
|
|
|
|
|
|
|
$dir_path ||= '/'; |
159
|
|
|
|
|
|
|
$self->_assert_absolute_path($dir_path); |
160
|
|
|
|
|
|
|
return $self->_collect_paths_for_all_comp_roots( |
161
|
|
|
|
|
|
|
sub { |
162
|
|
|
|
|
|
|
my $root_path = shift; |
163
|
|
|
|
|
|
|
my $dir = $root_path . $dir_path; |
164
|
|
|
|
|
|
|
return ( -d $dir ) ? find_wanted( sub { -f }, $dir ) : (); |
165
|
|
|
|
|
|
|
} |
166
|
|
|
|
|
|
|
); |
167
|
|
|
|
|
|
|
} |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
method comp_exists ($path) { |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
# Canonicalize path |
172
|
|
|
|
|
|
|
# |
173
|
|
|
|
|
|
|
croak "path required" if !defined($path); |
174
|
|
|
|
|
|
|
$path = Mason::Util::mason_canon_path($path); |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
return ( ( $self->static_source && $self->code_cache->get($path) ) |
177
|
|
|
|
|
|
|
|| $self->_source_file_for_path($path) ) ? 1 : 0; |
178
|
|
|
|
|
|
|
} |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
method flush_code_cache () { |
181
|
|
|
|
|
|
|
my $code_cache = $self->code_cache; |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
foreach my $key ( $code_cache->get_keys() ) { |
184
|
|
|
|
|
|
|
$code_cache->remove($key); |
185
|
|
|
|
|
|
|
} |
186
|
|
|
|
|
|
|
} |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
method glob_paths ($glob_pattern) { |
189
|
|
|
|
|
|
|
return $self->_collect_paths_for_all_comp_roots( |
190
|
|
|
|
|
|
|
sub { |
191
|
|
|
|
|
|
|
my $root_path = shift; |
192
|
|
|
|
|
|
|
return glob( $root_path . $glob_pattern ); |
193
|
|
|
|
|
|
|
} |
194
|
|
|
|
|
|
|
); |
195
|
|
|
|
|
|
|
} |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
our $in_load = 0; |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
method load ($path) { |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
local $current_load_interp = $self; |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
my $code_cache = $self->code_cache; |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
# Canonicalize path |
206
|
|
|
|
|
|
|
# |
207
|
|
|
|
|
|
|
croak "path required" if !defined($path); |
208
|
|
|
|
|
|
|
$path = Mason::Util::mason_canon_path($path); |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
# Quick check memory cache in static source mode |
211
|
|
|
|
|
|
|
# |
212
|
|
|
|
|
|
|
if ( $self->static_source ) { |
213
|
|
|
|
|
|
|
if ( my $entry = $code_cache->get($path) ) { |
214
|
|
|
|
|
|
|
return $entry->{compc}; |
215
|
|
|
|
|
|
|
} |
216
|
|
|
|
|
|
|
} |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
local $in_load = $in_load + 1; |
219
|
|
|
|
|
|
|
if ( $in_load > $max_depth ) { |
220
|
|
|
|
|
|
|
die ">$max_depth levels deep in inheritance determination (inheritance cycle?)" |
221
|
|
|
|
|
|
|
if $in_load >= $max_depth; |
222
|
|
|
|
|
|
|
} |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
my $compile = 0; |
225
|
|
|
|
|
|
|
my ( |
226
|
|
|
|
|
|
|
$default_parent_path, $source_file, $source_lastmod, $object_file, |
227
|
|
|
|
|
|
|
$object_lastmod, @source_stat, @object_stat |
228
|
|
|
|
|
|
|
); |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
my $stat_source_file = sub { |
231
|
|
|
|
|
|
|
if ( $source_file = $self->_source_file_for_path($path) ) { |
232
|
|
|
|
|
|
|
@source_stat = stat $source_file; |
233
|
|
|
|
|
|
|
if ( @source_stat && !-f _ ) { |
234
|
|
|
|
|
|
|
die "source file '$source_file' exists but it is not a file"; |
235
|
|
|
|
|
|
|
} |
236
|
|
|
|
|
|
|
} |
237
|
|
|
|
|
|
|
$source_lastmod = @source_stat ? $source_stat[9] : 0; |
238
|
|
|
|
|
|
|
}; |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
my $stat_object_file = sub { |
241
|
|
|
|
|
|
|
$object_file = $self->_object_file_for_path($path); |
242
|
|
|
|
|
|
|
@object_stat = stat $object_file; |
243
|
|
|
|
|
|
|
if ( @object_stat && !-f _ ) { |
244
|
|
|
|
|
|
|
die "object file '$object_file' exists but it is not a file"; |
245
|
|
|
|
|
|
|
} |
246
|
|
|
|
|
|
|
$object_lastmod = @object_stat ? $object_stat[9] : 0; |
247
|
|
|
|
|
|
|
}; |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
# Determine source and object files and their modified times |
250
|
|
|
|
|
|
|
# |
251
|
|
|
|
|
|
|
$stat_source_file->() or return; |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
# Determine default parent comp |
254
|
|
|
|
|
|
|
# |
255
|
|
|
|
|
|
|
$default_parent_path = $self->_default_parent_path($path); |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
if ( $self->static_source ) { |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
if ( $stat_object_file->() ) { |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
# If touch file is more recent than object file, we can't trust object file. |
262
|
|
|
|
|
|
|
# |
263
|
|
|
|
|
|
|
if ( $self->{static_source_touch_lastmod} >= $object_lastmod ) { |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
# If source file is more recent, recompile. Otherwise, touch |
266
|
|
|
|
|
|
|
# the object file so it will be trusted. |
267
|
|
|
|
|
|
|
# |
268
|
|
|
|
|
|
|
if ( $source_lastmod > $object_lastmod ) { |
269
|
|
|
|
|
|
|
$compile = 1; |
270
|
|
|
|
|
|
|
} |
271
|
|
|
|
|
|
|
else { |
272
|
|
|
|
|
|
|
touch_file($object_file); |
273
|
|
|
|
|
|
|
} |
274
|
|
|
|
|
|
|
} |
275
|
|
|
|
|
|
|
} |
276
|
|
|
|
|
|
|
else { |
277
|
|
|
|
|
|
|
$compile = 1; |
278
|
|
|
|
|
|
|
} |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
} |
281
|
|
|
|
|
|
|
else { |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
# Check memory cache |
284
|
|
|
|
|
|
|
# |
285
|
|
|
|
|
|
|
if ( my $entry = $code_cache->get($path) ) { |
286
|
|
|
|
|
|
|
if ( $entry->{source_lastmod} >= $source_lastmod |
287
|
|
|
|
|
|
|
&& $entry->{source_file} eq $source_file |
288
|
|
|
|
|
|
|
&& $entry->{default_parent_path} eq $default_parent_path ) |
289
|
|
|
|
|
|
|
{ |
290
|
|
|
|
|
|
|
my $compc = $entry->{compc}; |
291
|
|
|
|
|
|
|
if ( $entry->{superclass_signature} eq $self->_superclass_signature($compc) ) { |
292
|
|
|
|
|
|
|
return $compc; |
293
|
|
|
|
|
|
|
} |
294
|
|
|
|
|
|
|
} |
295
|
|
|
|
|
|
|
$code_cache->remove($path); |
296
|
|
|
|
|
|
|
} |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
# Determine object file and its last modified time |
299
|
|
|
|
|
|
|
# |
300
|
|
|
|
|
|
|
$stat_object_file->(); |
301
|
|
|
|
|
|
|
$compile = ( !$object_lastmod || $object_lastmod < $source_lastmod ); |
302
|
|
|
|
|
|
|
} |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
$self->_compile_to_file( $source_file, $path, $object_file ) if $compile; |
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
my $compc = $self->_comp_class_for_path($path); |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
$self->_load_class_from_object_file( $compc, $object_file, $path, $default_parent_path ); |
309
|
|
|
|
|
|
|
$compc->meta->make_immutable(); |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
# Save component class in the cache. |
312
|
|
|
|
|
|
|
# |
313
|
|
|
|
|
|
|
$code_cache->set( |
314
|
|
|
|
|
|
|
$path, |
315
|
|
|
|
|
|
|
{ |
316
|
|
|
|
|
|
|
source_file => $source_file, |
317
|
|
|
|
|
|
|
source_lastmod => $source_lastmod, |
318
|
|
|
|
|
|
|
default_parent_path => $default_parent_path, |
319
|
|
|
|
|
|
|
compc => $compc, |
320
|
|
|
|
|
|
|
superclass_signature => $self->_superclass_signature($compc), |
321
|
|
|
|
|
|
|
} |
322
|
|
|
|
|
|
|
); |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
return $compc; |
325
|
|
|
|
|
|
|
} |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
method _superclass_signature ($compc) { |
328
|
|
|
|
|
|
|
my @superclasses = $compc->meta->superclasses; |
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
# Recursively load the superclasses for an existing component class in |
331
|
|
|
|
|
|
|
# case they have changed. |
332
|
|
|
|
|
|
|
# |
333
|
|
|
|
|
|
|
foreach my $superclass (@superclasses) { |
334
|
|
|
|
|
|
|
if ( my $cmeta = $superclass->cmeta ) { |
335
|
|
|
|
|
|
|
my $path = $cmeta->path; |
336
|
|
|
|
|
|
|
$self->load( $cmeta->path ); |
337
|
|
|
|
|
|
|
} |
338
|
|
|
|
|
|
|
} |
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
# Return a unique signature representing the component class's superclasses |
341
|
|
|
|
|
|
|
# and their versions. |
342
|
|
|
|
|
|
|
# |
343
|
|
|
|
|
|
|
return join( ",", map { join( "-", $_, $_->cmeta ? $_->cmeta->id : 0 ) } @superclasses ); |
344
|
|
|
|
|
|
|
} |
345
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
# Memoize comp_exists() and load() - this helps both with components used |
347
|
|
|
|
|
|
|
# multiple times in a request, and with determining default parent |
348
|
|
|
|
|
|
|
# components. The memoize cache is cleared at the beginning of each |
349
|
|
|
|
|
|
|
# request, or in static_source_mode, when the purge file is touched. |
350
|
|
|
|
|
|
|
# |
351
|
|
|
|
|
|
|
memoize('comp_exists'); |
352
|
|
|
|
|
|
|
memoize('load'); |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
method object_dir () { |
355
|
|
|
|
|
|
|
return catdir( $self->data_dir, 'obj' ); |
356
|
|
|
|
|
|
|
} |
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
method run () { |
359
|
|
|
|
|
|
|
my %request_params; |
360
|
|
|
|
|
|
|
if ( ref( $_[0] ) eq 'HASH' ) { |
361
|
|
|
|
|
|
|
%request_params = %{ shift(@_) }; |
362
|
|
|
|
|
|
|
} |
363
|
|
|
|
|
|
|
my $path = shift; |
364
|
|
|
|
|
|
|
my $request = $self->_make_request(%request_params); |
365
|
|
|
|
|
|
|
$request->run( $path, @_ ); |
366
|
|
|
|
|
|
|
} |
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
method set_global () { |
369
|
|
|
|
|
|
|
my ( $spec, $value ) = @_; |
370
|
|
|
|
|
|
|
croak "set_global expects a var name and value" unless $value; |
371
|
|
|
|
|
|
|
my ( $sigil, $name ) = $self->_parse_global_spec($spec); |
372
|
|
|
|
|
|
|
croak "${sigil}${name} is not in the allowed globals list" |
373
|
|
|
|
|
|
|
unless $self->allowed_globals_hash->{"${sigil}${name}"}; |
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
my $varname = sprintf( "%s::%s", $self->globals_package, $name ); |
376
|
|
|
|
|
|
|
no strict 'refs'; |
377
|
|
|
|
|
|
|
no warnings 'once'; |
378
|
|
|
|
|
|
|
$$varname = $value; |
379
|
|
|
|
|
|
|
} |
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
# |
382
|
|
|
|
|
|
|
# MODIFIABLE METHODS |
383
|
|
|
|
|
|
|
# |
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
method DEMOLISH () { |
386
|
|
|
|
|
|
|
return if in_global_destruction; |
387
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
# We have to check for code_cache slot directly, in case the object gets |
389
|
|
|
|
|
|
|
# destroyed before it has been fully formed (e.g. missing required attr). |
390
|
|
|
|
|
|
|
# |
391
|
|
|
|
|
|
|
$self->flush_code_cache() if defined( $self->{code_cache} ); |
392
|
|
|
|
|
|
|
} |
393
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
method _compile ($source_file, $path) { |
395
|
|
|
|
|
|
|
my $compilation = $self->compilation_class->new( |
396
|
|
|
|
|
|
|
source_file => $source_file, |
397
|
|
|
|
|
|
|
path => $path, |
398
|
|
|
|
|
|
|
interp => $self |
399
|
|
|
|
|
|
|
); |
400
|
|
|
|
|
|
|
return $compilation->compile(); |
401
|
|
|
|
|
|
|
} |
402
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
method _compile_to_file ($source_file, $path, $object_file) { |
404
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
# We attempt to handle several cases in which a file already exists |
406
|
|
|
|
|
|
|
# and we wish to create a directory, or vice versa. However, not |
407
|
|
|
|
|
|
|
# every case is handled; to be complete, mkpath would have to unlink |
408
|
|
|
|
|
|
|
# any existing file in its way. |
409
|
|
|
|
|
|
|
# |
410
|
|
|
|
|
|
|
if ( defined $object_file && !-f $object_file ) { |
411
|
|
|
|
|
|
|
my ($dirname) = dirname($object_file); |
412
|
|
|
|
|
|
|
if ( !-d $dirname ) { |
413
|
|
|
|
|
|
|
unlink($dirname) if ( -e _ ); |
414
|
|
|
|
|
|
|
mkpath( $dirname, 0, 0775 ); |
415
|
|
|
|
|
|
|
} |
416
|
|
|
|
|
|
|
rmtree($object_file) if ( -d $object_file ); |
417
|
|
|
|
|
|
|
} |
418
|
|
|
|
|
|
|
my $object_contents = $self->_compile( $source_file, $path ); |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
$self->write_object_file( $object_file, $object_contents ); |
421
|
|
|
|
|
|
|
} |
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
method is_pure_perl_comp_path ($path) { |
424
|
|
|
|
|
|
|
return ( $path =~ $self->pure_perl_regex ) ? 1 : 0; |
425
|
|
|
|
|
|
|
} |
426
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
method is_top_level_comp_path ($path) { |
428
|
|
|
|
|
|
|
return ( $path =~ $self->top_level_regex ) ? 1 : 0; |
429
|
|
|
|
|
|
|
} |
430
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
method _load_class_from_object_file ($compc, $object_file, $path, $default_parent_path) { |
432
|
|
|
|
|
|
|
my $flags = $self->_extract_flags_from_object_file($object_file); |
433
|
|
|
|
|
|
|
my $parent_compc = |
434
|
|
|
|
|
|
|
$self->_determine_parent_compc( $path, $flags ) |
435
|
|
|
|
|
|
|
|| ( $default_parent_path eq '/' && $self->component_class ) |
436
|
|
|
|
|
|
|
|| $self->load($default_parent_path); |
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
my $code = sprintf( 'package %s; use Moose; extends \'%s\'; do(\'%s\'); die $@ if $@', |
439
|
|
|
|
|
|
|
$compc, $parent_compc, $object_file ); |
440
|
|
|
|
|
|
|
($code) = ( $code =~ /^(.*)/s ) if taint_is_on(); |
441
|
|
|
|
|
|
|
eval($code); |
442
|
|
|
|
|
|
|
die $@ if $@; |
443
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
$compc->_set_class_cmeta($self); |
445
|
|
|
|
|
|
|
$self->modify_loaded_class($compc); |
446
|
|
|
|
|
|
|
} |
447
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
method modify_loaded_class ($compc) { |
449
|
|
|
|
|
|
|
$self->_add_default_wrap_method($compc); |
450
|
|
|
|
|
|
|
} |
451
|
|
|
|
|
|
|
|
452
|
|
|
|
|
|
|
method write_object_file ($object_file, $object_contents) { |
453
|
|
|
|
|
|
|
write_file( $object_file, $object_contents ); |
454
|
|
|
|
|
|
|
} |
455
|
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
# Given /foo/bar, look for (by default): |
457
|
|
|
|
|
|
|
# /foo/bar/index.{mp,mc}, |
458
|
|
|
|
|
|
|
# /foo/bar/dhandler.{mp,mc}, |
459
|
|
|
|
|
|
|
# /foo/bar.{mp,mc}, |
460
|
|
|
|
|
|
|
# /dhandler.{mp,mc}, |
461
|
|
|
|
|
|
|
# /foo.{mp,mc} |
462
|
|
|
|
|
|
|
# |
463
|
|
|
|
|
|
|
method _build_match_request_path ($interp:) { |
464
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
# Create a closure for efficiency - all this data is immutable for an interp. |
466
|
|
|
|
|
|
|
# |
467
|
|
|
|
|
|
|
my @dhandler_subpaths = map { "/$_" } @{ $interp->dhandler_names }; |
468
|
|
|
|
|
|
|
my $ignore_file_regex = |
469
|
|
|
|
|
|
|
'(/' . join( "|", @{ $interp->autobase_names }, @{ $interp->dhandler_names } ) . ')$'; |
470
|
|
|
|
|
|
|
$ignore_file_regex = qr/$ignore_file_regex/; |
471
|
|
|
|
|
|
|
my @autoextensions = $interp->autoextend_request_path ? @{ $interp->top_level_extensions } : (); |
472
|
|
|
|
|
|
|
my @index_names = @{ $interp->index_names }; |
473
|
|
|
|
|
|
|
undef $interp; # So this doesn't end up in closure and cause cycle |
474
|
|
|
|
|
|
|
|
475
|
|
|
|
|
|
|
return sub { |
476
|
|
|
|
|
|
|
my ( $request, $request_path ) = @_; |
477
|
|
|
|
|
|
|
my $interp = $request->interp; |
478
|
|
|
|
|
|
|
my $path_info = ''; |
479
|
|
|
|
|
|
|
my $declined_paths = $request->declined_paths; |
480
|
|
|
|
|
|
|
my @index_subpaths = map { "/$_" } @index_names; |
481
|
|
|
|
|
|
|
my $path = $request_path; |
482
|
|
|
|
|
|
|
my @tried_paths; |
483
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
# Deal with trailing slash |
485
|
|
|
|
|
|
|
# |
486
|
|
|
|
|
|
|
$path_info = chop($path) if $path ne '/' && substr( $path, -1 ) eq '/'; |
487
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
while (1) { |
489
|
|
|
|
|
|
|
my @candidate_paths = |
490
|
|
|
|
|
|
|
( $path_info eq '' && !@autoextensions ) ? ($path) |
491
|
|
|
|
|
|
|
: ( $path eq '/' ) ? ( @index_subpaths, @dhandler_subpaths ) |
492
|
|
|
|
|
|
|
: ( |
493
|
|
|
|
|
|
|
( grep { !/$ignore_file_regex/ } map { $path . $_ } @autoextensions ), |
494
|
|
|
|
|
|
|
( map { $path . $_ } ( @index_subpaths, @dhandler_subpaths ) ) |
495
|
|
|
|
|
|
|
); |
496
|
|
|
|
|
|
|
push( @tried_paths, @candidate_paths ); |
497
|
|
|
|
|
|
|
foreach my $candidate_path (@candidate_paths) { |
498
|
|
|
|
|
|
|
next if $declined_paths->{$candidate_path}; |
499
|
|
|
|
|
|
|
if ( my $compc = $interp->load($candidate_path) ) { |
500
|
|
|
|
|
|
|
if ( |
501
|
|
|
|
|
|
|
$compc->cmeta->is_top_level |
502
|
|
|
|
|
|
|
&& ( $path_info eq '' |
503
|
|
|
|
|
|
|
|| $compc->cmeta->is_dhandler |
504
|
|
|
|
|
|
|
|| $compc->allow_path_info ) |
505
|
|
|
|
|
|
|
) |
506
|
|
|
|
|
|
|
{ |
507
|
|
|
|
|
|
|
$request->{path_info} = $path_info; |
508
|
|
|
|
|
|
|
return $compc->cmeta->path; |
509
|
|
|
|
|
|
|
} |
510
|
|
|
|
|
|
|
} |
511
|
|
|
|
|
|
|
} |
512
|
|
|
|
|
|
|
$interp->_top_level_not_found( $request_path, \@tried_paths ) if $path eq '/'; |
513
|
|
|
|
|
|
|
my $name = basename($path); |
514
|
|
|
|
|
|
|
$path_info = |
515
|
|
|
|
|
|
|
$path_info eq '/' ? "$name/" |
516
|
|
|
|
|
|
|
: length($path_info) ? "$name/$path_info" |
517
|
|
|
|
|
|
|
: $name; |
518
|
|
|
|
|
|
|
$path = dirname($path); |
519
|
|
|
|
|
|
|
@index_subpaths = (); # only match index file in same directory |
520
|
|
|
|
|
|
|
} |
521
|
|
|
|
|
|
|
}; |
522
|
|
|
|
|
|
|
} |
523
|
|
|
|
|
|
|
|
524
|
|
|
|
|
|
|
# |
525
|
|
|
|
|
|
|
# PRIVATE METHODS |
526
|
|
|
|
|
|
|
# |
527
|
|
|
|
|
|
|
|
528
|
|
|
|
|
|
|
method _parse_global_spec () { |
529
|
|
|
|
|
|
|
my $spec = shift; |
530
|
|
|
|
|
|
|
croak "only scalar globals supported at this time (not '$spec')" if $spec =~ /^[@%]/; |
531
|
|
|
|
|
|
|
$spec =~ s/^\$//; |
532
|
|
|
|
|
|
|
die "'$spec' is not a valid global var name" unless $spec =~ qr/^[[:alpha:]_]\w*$/; |
533
|
|
|
|
|
|
|
return ( '$', $spec ); |
534
|
|
|
|
|
|
|
} |
535
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
method _add_default_wrap_method ($compc) { |
537
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
# Default wrap method for any component that doesn't define one. |
539
|
|
|
|
|
|
|
# Call inner() until we're back down at the page component ($self), |
540
|
|
|
|
|
|
|
# then call main(). |
541
|
|
|
|
|
|
|
# |
542
|
|
|
|
|
|
|
unless ( $compc->meta->has_method('wrap') ) { |
543
|
|
|
|
|
|
|
my $path = $compc->cmeta->path; |
544
|
|
|
|
|
|
|
my $code = sub { |
545
|
|
|
|
|
|
|
my $self = shift; |
546
|
|
|
|
|
|
|
if ( $self->cmeta->path eq $path ) { |
547
|
|
|
|
|
|
|
if ( $self->can('main') ) { |
548
|
|
|
|
|
|
|
$self->main(@_); |
549
|
|
|
|
|
|
|
} |
550
|
|
|
|
|
|
|
else { |
551
|
|
|
|
|
|
|
die sprintf( |
552
|
|
|
|
|
|
|
"component '%s' ('%s') was called but has no main method - did you forget to define 'main' or 'handle'?", |
553
|
|
|
|
|
|
|
$path, $compc->cmeta->source_file ); |
554
|
|
|
|
|
|
|
} |
555
|
|
|
|
|
|
|
} |
556
|
|
|
|
|
|
|
else { |
557
|
|
|
|
|
|
|
$compc->_inner(); |
558
|
|
|
|
|
|
|
} |
559
|
|
|
|
|
|
|
}; |
560
|
|
|
|
|
|
|
$compc->meta->add_augment_method_modifier( wrap => $code ); |
561
|
|
|
|
|
|
|
} |
562
|
|
|
|
|
|
|
} |
563
|
|
|
|
|
|
|
|
564
|
|
|
|
|
|
|
method _assert_absolute_path ($path) { |
565
|
|
|
|
|
|
|
$path ||= ''; |
566
|
|
|
|
|
|
|
croak "'$path' is not an absolute path" unless is_absolute($path); |
567
|
|
|
|
|
|
|
} |
568
|
|
|
|
|
|
|
|
569
|
|
|
|
|
|
|
method _check_static_source_touch_file () { |
570
|
|
|
|
|
|
|
|
571
|
|
|
|
|
|
|
# Check the static_source_touch_file, if one exists, to see if it has |
572
|
|
|
|
|
|
|
# changed since we last checked. If it has, clear the code cache. |
573
|
|
|
|
|
|
|
# |
574
|
|
|
|
|
|
|
if ( my $touch_file = $self->static_source_touch_file ) { |
575
|
|
|
|
|
|
|
return unless -f $touch_file; |
576
|
|
|
|
|
|
|
my $touch_file_lastmod = ( stat($touch_file) )[9]; |
577
|
|
|
|
|
|
|
if ( $touch_file_lastmod > $self->{static_source_touch_lastmod} ) { |
578
|
|
|
|
|
|
|
$self->flush_code_cache; |
579
|
|
|
|
|
|
|
$self->{static_source_touch_lastmod} = $touch_file_lastmod; |
580
|
|
|
|
|
|
|
} |
581
|
|
|
|
|
|
|
} |
582
|
|
|
|
|
|
|
} |
583
|
|
|
|
|
|
|
|
584
|
|
|
|
|
|
|
method _collect_paths_for_all_comp_roots ($code) { |
585
|
|
|
|
|
|
|
my @paths; |
586
|
|
|
|
|
|
|
foreach my $root_path ( @{ $self->comp_root } ) { |
587
|
|
|
|
|
|
|
my $root_path_length = length($root_path); |
588
|
|
|
|
|
|
|
my @files = $code->($root_path); |
589
|
|
|
|
|
|
|
push( @paths, map { substr( $_, $root_path_length ) } @files ); |
590
|
|
|
|
|
|
|
} |
591
|
|
|
|
|
|
|
return uniq(@paths); |
592
|
|
|
|
|
|
|
} |
593
|
|
|
|
|
|
|
|
594
|
|
|
|
|
|
|
method _comp_class_for_path ($path) { |
595
|
|
|
|
|
|
|
my $classname = substr( $path, 1 ); |
596
|
|
|
|
|
|
|
$classname =~ s/[^\w]/_/g; |
597
|
|
|
|
|
|
|
$classname =~ s/\//::/g; |
598
|
|
|
|
|
|
|
$classname = join( "::", $self->component_class_prefix, $classname ); |
599
|
|
|
|
|
|
|
return $classname; |
600
|
|
|
|
|
|
|
} |
601
|
|
|
|
|
|
|
|
602
|
|
|
|
|
|
|
method _construct_distinct_string () { |
603
|
|
|
|
|
|
|
my $number = ++$self->{distinct_string_count}; |
604
|
|
|
|
|
|
|
my $str = $self->_construct_distinct_string_for_number($number); |
605
|
|
|
|
|
|
|
return $str; |
606
|
|
|
|
|
|
|
} |
607
|
|
|
|
|
|
|
|
608
|
|
|
|
|
|
|
method _construct_distinct_string_for_number ($number) { |
609
|
|
|
|
|
|
|
my $distinct_delimeter = "__MASON__"; |
610
|
|
|
|
|
|
|
return sprintf( "%s%d%s", $distinct_delimeter, $number, $distinct_delimeter ); |
611
|
|
|
|
|
|
|
} |
612
|
|
|
|
|
|
|
|
613
|
|
|
|
|
|
|
method _default_parent_path ($orig_path) { |
614
|
|
|
|
|
|
|
|
615
|
|
|
|
|
|
|
# Given /foo/bar.mc, look for (by default): |
616
|
|
|
|
|
|
|
# /foo/Base.mp, /foo/Base.mc, |
617
|
|
|
|
|
|
|
# /Base.mp, /Base.mc |
618
|
|
|
|
|
|
|
# |
619
|
|
|
|
|
|
|
# Split path into dir_path and base_name - validate that it has a |
620
|
|
|
|
|
|
|
# starting slash and ends with at least one non-slash character |
621
|
|
|
|
|
|
|
# |
622
|
|
|
|
|
|
|
my ( $dir_path, $base_name ) = ( $orig_path =~ m{^(/.*?)/?([^/]+)$} ) |
623
|
|
|
|
|
|
|
or die "not a valid absolute component path - '$orig_path'"; |
624
|
|
|
|
|
|
|
my $path = $dir_path; |
625
|
|
|
|
|
|
|
|
626
|
|
|
|
|
|
|
my @autobase_subpaths = map { "/$_" } @{ $self->autobase_names }; |
627
|
|
|
|
|
|
|
while (1) { |
628
|
|
|
|
|
|
|
my @candidate_paths = |
629
|
|
|
|
|
|
|
( $path eq '/' ) |
630
|
|
|
|
|
|
|
? @autobase_subpaths |
631
|
|
|
|
|
|
|
: ( map { $path . $_ } @autobase_subpaths ); |
632
|
|
|
|
|
|
|
if ( ( my $index = first_index { $_ eq $orig_path } @candidate_paths ) != -1 ) { |
633
|
|
|
|
|
|
|
splice( @candidate_paths, 0, $index + 1 ); |
634
|
|
|
|
|
|
|
} |
635
|
|
|
|
|
|
|
foreach my $candidate_path (@candidate_paths) { |
636
|
|
|
|
|
|
|
if ( $self->comp_exists($candidate_path) ) { |
637
|
|
|
|
|
|
|
return $candidate_path; |
638
|
|
|
|
|
|
|
} |
639
|
|
|
|
|
|
|
} |
640
|
|
|
|
|
|
|
if ( $path eq '/' ) { |
641
|
|
|
|
|
|
|
return '/'; |
642
|
|
|
|
|
|
|
} |
643
|
|
|
|
|
|
|
$path = dirname($path); |
644
|
|
|
|
|
|
|
} |
645
|
|
|
|
|
|
|
} |
646
|
|
|
|
|
|
|
|
647
|
|
|
|
|
|
|
method _determine_parent_compc ($path, $flags) { |
648
|
|
|
|
|
|
|
my $parent_compc; |
649
|
|
|
|
|
|
|
if ( exists( $flags->{extends} ) ) { |
650
|
|
|
|
|
|
|
my $extends = $flags->{extends}; |
651
|
|
|
|
|
|
|
if ( defined($extends) ) { |
652
|
|
|
|
|
|
|
$extends = mason_canon_path( join( "/", dirname($path), $extends ) ) |
653
|
|
|
|
|
|
|
if substr( $extends, 0, 1 ) ne '/'; |
654
|
|
|
|
|
|
|
$parent_compc = $self->load($extends) |
655
|
|
|
|
|
|
|
or die "could not load '$extends' for extends flag"; |
656
|
|
|
|
|
|
|
} |
657
|
|
|
|
|
|
|
else { |
658
|
|
|
|
|
|
|
$parent_compc = $self->component_class; |
659
|
|
|
|
|
|
|
} |
660
|
|
|
|
|
|
|
} |
661
|
|
|
|
|
|
|
return $parent_compc; |
662
|
|
|
|
|
|
|
} |
663
|
|
|
|
|
|
|
|
664
|
|
|
|
|
|
|
method _extract_flags_from_object_file ($object_file) { |
665
|
|
|
|
|
|
|
my $flags = {}; |
666
|
|
|
|
|
|
|
open( my $fh, "<", $object_file ) or die "could not open '$object_file': $!"; |
667
|
|
|
|
|
|
|
my $line = <$fh>; |
668
|
|
|
|
|
|
|
if ( my ($flags_str) = ( $line =~ /\# FLAGS: (.*)/ ) ) { |
669
|
|
|
|
|
|
|
$flags = json_decode($flags_str); |
670
|
|
|
|
|
|
|
} |
671
|
|
|
|
|
|
|
return $flags; |
672
|
|
|
|
|
|
|
} |
673
|
|
|
|
|
|
|
|
674
|
|
|
|
|
|
|
method _flush_load_cache () { |
675
|
|
|
|
|
|
|
Memoize::flush_cache('comp_exists'); |
676
|
|
|
|
|
|
|
Memoize::flush_cache('load'); |
677
|
|
|
|
|
|
|
} |
678
|
|
|
|
|
|
|
|
679
|
|
|
|
|
|
|
method _make_request () { |
680
|
|
|
|
|
|
|
return $self->request_class->new( interp => $self, %{ $self->request_params }, @_ ); |
681
|
|
|
|
|
|
|
} |
682
|
|
|
|
|
|
|
|
683
|
|
|
|
|
|
|
method _object_file_for_path ($path) { |
684
|
|
|
|
|
|
|
return catfile( $self->object_dir, ( split /\//, $path ) ) . $self->object_file_extension; |
685
|
|
|
|
|
|
|
} |
686
|
|
|
|
|
|
|
|
687
|
|
|
|
|
|
|
method _source_file_for_path ($path) { |
688
|
|
|
|
|
|
|
$self->_assert_absolute_path($path); |
689
|
|
|
|
|
|
|
foreach my $root_path ( @{ $self->comp_root } ) { |
690
|
|
|
|
|
|
|
my $source_file = $root_path . $path; |
691
|
|
|
|
|
|
|
return $source_file if -f $source_file; |
692
|
|
|
|
|
|
|
} |
693
|
|
|
|
|
|
|
return undef; |
694
|
|
|
|
|
|
|
} |
695
|
|
|
|
|
|
|
|
696
|
|
|
|
|
|
|
method _top_level_not_found ($path, $tried_paths) { |
697
|
|
|
|
|
|
|
my @combined_paths = combine_similar_paths(@$tried_paths); |
698
|
|
|
|
|
|
|
Mason::Exception::TopLevelNotFound->throw( |
699
|
|
|
|
|
|
|
error => sprintf( |
700
|
|
|
|
|
|
|
"could not resolve request path '%s'; searched for components (%s) under %s\n", |
701
|
|
|
|
|
|
|
$path, |
702
|
|
|
|
|
|
|
join( ", ", map { "'$_'" } @combined_paths ), |
703
|
|
|
|
|
|
|
@{ $self->comp_root } > 1 |
704
|
|
|
|
|
|
|
? "component roots " . join( ", ", map { "'$_'" } @{ $self->comp_root } ) |
705
|
|
|
|
|
|
|
: "component root '" . $self->comp_root->[0] . "'" |
706
|
|
|
|
|
|
|
) |
707
|
|
|
|
|
|
|
); |
708
|
|
|
|
|
|
|
} |
709
|
|
|
|
|
|
|
|
710
|
|
|
|
|
|
|
method _validate_allow_globals () { |
711
|
|
|
|
|
|
|
|
712
|
|
|
|
|
|
|
# Will build allowed_globals_hash and also validate the param |
713
|
|
|
|
|
|
|
# |
714
|
|
|
|
|
|
|
$self->allowed_globals_hash; |
715
|
|
|
|
|
|
|
} |
716
|
|
|
|
|
|
|
|
717
|
|
|
|
|
|
|
# |
718
|
|
|
|
|
|
|
# Class overrides. Put here at the bottom because it strangely messes up |
719
|
|
|
|
|
|
|
# Perl line numbering if at the top. |
720
|
|
|
|
|
|
|
# |
721
|
|
|
|
|
|
|
sub _define_class_override_methods { |
722
|
|
|
|
|
|
|
my %class_overrides = ( |
723
|
|
|
|
|
|
|
code_cache_class => 'CodeCache', |
724
|
|
|
|
|
|
|
compilation_class => 'Compilation', |
725
|
|
|
|
|
|
|
component_class => 'Component', |
726
|
|
|
|
|
|
|
component_class_meta_class => 'Component::ClassMeta', |
727
|
|
|
|
|
|
|
component_import_class => 'Component::Import', |
728
|
|
|
|
|
|
|
component_moose_class => 'Component::Moose', |
729
|
|
|
|
|
|
|
request_class => 'Request', |
730
|
|
|
|
|
|
|
result_class => 'Result', |
731
|
|
|
|
|
|
|
); |
732
|
|
|
|
|
|
|
|
733
|
|
|
|
|
|
|
# e.g. |
734
|
|
|
|
|
|
|
# $method_name = component_moose_class |
735
|
|
|
|
|
|
|
# $base_method_name = base_component_moose_class |
736
|
|
|
|
|
|
|
# $name = Component::Moose |
737
|
|
|
|
|
|
|
# $default_base_class = Mason::Component::Moose |
738
|
|
|
|
|
|
|
# |
739
|
|
|
|
|
|
|
while ( my ( $method_name, $name ) = each(%class_overrides) ) { |
740
|
|
|
|
|
|
|
my $base_method_name = "base_$method_name"; |
741
|
|
|
|
|
|
|
has $method_name => ( init_arg => undef, lazy_build => 1 ); |
742
|
|
|
|
|
|
|
has $base_method_name => ( isa => 'Str', lazy_build => 1 ); |
743
|
|
|
|
|
|
|
__PACKAGE__->meta->add_method( |
744
|
|
|
|
|
|
|
"_build_$method_name" => sub { |
745
|
|
|
|
|
|
|
my $self = shift; |
746
|
|
|
|
|
|
|
my $base_class = $self->$base_method_name; |
747
|
|
|
|
|
|
|
Class::Load::load_class($base_class); |
748
|
|
|
|
|
|
|
return Mason::PluginManager->apply_plugins_to_class( $base_class, $name, |
749
|
|
|
|
|
|
|
$self->plugins ); |
750
|
|
|
|
|
|
|
} |
751
|
|
|
|
|
|
|
); |
752
|
|
|
|
|
|
|
__PACKAGE__->meta->add_method( |
753
|
|
|
|
|
|
|
"_build_$base_method_name" => sub { |
754
|
|
|
|
|
|
|
my $self = shift; |
755
|
|
|
|
|
|
|
my @candidates = |
756
|
|
|
|
|
|
|
map { join( '::', $_, $name ) } ( uniq( $self->mason_root_class, 'Mason' ) ); |
757
|
|
|
|
|
|
|
my ($base_class) = grep { can_load($_) } @candidates |
758
|
|
|
|
|
|
|
or die |
759
|
|
|
|
|
|
|
sprintf( "cannot load %s for %s", join( ', ', @candidates ), $base_method_name ); |
760
|
|
|
|
|
|
|
return $base_class; |
761
|
|
|
|
|
|
|
} |
762
|
|
|
|
|
|
|
); |
763
|
|
|
|
|
|
|
} |
764
|
|
|
|
|
|
|
} |
765
|
|
|
|
|
|
|
|
766
|
|
|
|
|
|
|
__PACKAGE__->meta->make_immutable(); |
767
|
|
|
|
|
|
|
|
768
|
|
|
|
|
|
|
1; |
769
|
|
|
|
|
|
|
|
770
|
|
|
|
|
|
|
__END__ |
771
|
|
|
|
|
|
|
|
772
|
|
|
|
|
|
|
=pod |
773
|
|
|
|
|
|
|
|
774
|
|
|
|
|
|
|
=head1 NAME |
775
|
|
|
|
|
|
|
|
776
|
|
|
|
|
|
|
Mason::Interp - Mason Interpreter |
777
|
|
|
|
|
|
|
|
778
|
|
|
|
|
|
|
=head1 SYNOPSIS |
779
|
|
|
|
|
|
|
|
780
|
|
|
|
|
|
|
my $interp = Mason->new( |
781
|
|
|
|
|
|
|
comp_root => '/path/to/comps', |
782
|
|
|
|
|
|
|
data_dir => '/path/to/data', |
783
|
|
|
|
|
|
|
... |
784
|
|
|
|
|
|
|
); |
785
|
|
|
|
|
|
|
my $output = $interp->run( '/request/path', foo => 5 )->output(); |
786
|
|
|
|
|
|
|
|
787
|
|
|
|
|
|
|
=head1 DESCRIPTION |
788
|
|
|
|
|
|
|
|
789
|
|
|
|
|
|
|
Interp is the central Mason object, returned from C<< Mason->new >>. It is |
790
|
|
|
|
|
|
|
responsible for creating new requests, compiling components, and maintaining |
791
|
|
|
|
|
|
|
the cache of loaded components. |
792
|
|
|
|
|
|
|
|
793
|
|
|
|
|
|
|
=head1 PARAMETERS TO THE new() CONSTRUCTOR |
794
|
|
|
|
|
|
|
|
795
|
|
|
|
|
|
|
=over |
796
|
|
|
|
|
|
|
|
797
|
|
|
|
|
|
|
=item allow_globals (varnames) |
798
|
|
|
|
|
|
|
|
799
|
|
|
|
|
|
|
List of one or more global variable names that will be available in all |
800
|
|
|
|
|
|
|
components, like C<< $m >> is by default. |
801
|
|
|
|
|
|
|
|
802
|
|
|
|
|
|
|
allow_globals => [qw($dbh)] |
803
|
|
|
|
|
|
|
|
804
|
|
|
|
|
|
|
As in any programming environment, globals should be created sparingly (if at |
805
|
|
|
|
|
|
|
all) and only when other mechanisms (parameter passing, attributes, singletons) |
806
|
|
|
|
|
|
|
will not suffice. L<Catalyst::View::Mason2|Catalyst::View::Mason2>, for |
807
|
|
|
|
|
|
|
example, creates a C<< $c >> global set to the context object in each request. |
808
|
|
|
|
|
|
|
|
809
|
|
|
|
|
|
|
Set the values of globals with L<set_global|/set_global>. |
810
|
|
|
|
|
|
|
|
811
|
|
|
|
|
|
|
=item autobase_names |
812
|
|
|
|
|
|
|
|
813
|
|
|
|
|
|
|
Array reference of L<autobase|Mason::Manual/Autobase components> filenames to |
814
|
|
|
|
|
|
|
check in order when determining a component's superclass. Default is C<< |
815
|
|
|
|
|
|
|
["Base.mp", "Base.mc"] >>. |
816
|
|
|
|
|
|
|
|
817
|
|
|
|
|
|
|
=item autoextend_request_path |
818
|
|
|
|
|
|
|
|
819
|
|
|
|
|
|
|
Whether to automatically add the L<top level extensions|/top_level_extensions> |
820
|
|
|
|
|
|
|
(by default ".mp" and ".mc") to the request path when searching for a matching |
821
|
|
|
|
|
|
|
page component. Defaults to true. |
822
|
|
|
|
|
|
|
|
823
|
|
|
|
|
|
|
=item class_header |
824
|
|
|
|
|
|
|
|
825
|
|
|
|
|
|
|
Perl code to be added at the top of the compiled class for every component, |
826
|
|
|
|
|
|
|
e.g. to bring in common features or import common methods. Default is the empty |
827
|
|
|
|
|
|
|
string. |
828
|
|
|
|
|
|
|
|
829
|
|
|
|
|
|
|
# Add to the top of every component class: |
830
|
|
|
|
|
|
|
# use Modern::Perl; |
831
|
|
|
|
|
|
|
# use JSON::XS qw(encode_json decode_json); |
832
|
|
|
|
|
|
|
# |
833
|
|
|
|
|
|
|
my $mason = Mason->new( |
834
|
|
|
|
|
|
|
... |
835
|
|
|
|
|
|
|
class_header => qq( |
836
|
|
|
|
|
|
|
use Modern::Perl; |
837
|
|
|
|
|
|
|
use JSON::XS qw(encode_json decode_json); |
838
|
|
|
|
|
|
|
), |
839
|
|
|
|
|
|
|
); |
840
|
|
|
|
|
|
|
|
841
|
|
|
|
|
|
|
This is used by |
842
|
|
|
|
|
|
|
L<Mason::Compilation::output_class_header|Mason::Compilation/output_class_header>. |
843
|
|
|
|
|
|
|
For more advanced usage you can override that method in a subclass or plugin. |
844
|
|
|
|
|
|
|
|
845
|
|
|
|
|
|
|
=item comp_root |
846
|
|
|
|
|
|
|
|
847
|
|
|
|
|
|
|
Required. The component root marks the top of your component hierarchy and |
848
|
|
|
|
|
|
|
defines how component paths are translated into real file paths. For example, |
849
|
|
|
|
|
|
|
if your component root is F</usr/local/httpd/docs>, a component path of |
850
|
|
|
|
|
|
|
F</products/sales.mc> translates to the file |
851
|
|
|
|
|
|
|
F</usr/local/httpd/docs/products/sales.mc>. |
852
|
|
|
|
|
|
|
|
853
|
|
|
|
|
|
|
This parameter may be either a single path or an array reference of paths. If |
854
|
|
|
|
|
|
|
it is an array reference, the paths will be searched in the provided order |
855
|
|
|
|
|
|
|
whenever a component path is resolved, much like Perl's C<< @INC >>. |
856
|
|
|
|
|
|
|
|
857
|
|
|
|
|
|
|
=item component_class_prefix |
858
|
|
|
|
|
|
|
|
859
|
|
|
|
|
|
|
Prefix to use in generated component classnames. Defaults to 'MC' plus the |
860
|
|
|
|
|
|
|
interpreter's count, e.g. MC0. So a component '/foo/bar' would get a classname |
861
|
|
|
|
|
|
|
like 'MC0::foo::bar'. |
862
|
|
|
|
|
|
|
|
863
|
|
|
|
|
|
|
=item data_dir |
864
|
|
|
|
|
|
|
|
865
|
|
|
|
|
|
|
The data directory is a writable directory that Mason uses for various features |
866
|
|
|
|
|
|
|
and optimizations: for example, component object files and data cache files. |
867
|
|
|
|
|
|
|
Mason will create the directory on startup if necessary. |
868
|
|
|
|
|
|
|
|
869
|
|
|
|
|
|
|
Defaults to a temporary directory that will be cleaned up at process end. This |
870
|
|
|
|
|
|
|
will hurt performance as Mason will have to recompile components on each run. |
871
|
|
|
|
|
|
|
|
872
|
|
|
|
|
|
|
=item dhandler_names |
873
|
|
|
|
|
|
|
|
874
|
|
|
|
|
|
|
Array reference of dhandler file names to check in order when resolving a |
875
|
|
|
|
|
|
|
top-level path. Default is C<< ["dhandler.mp", "dhandler.mc"] >>. An empty list |
876
|
|
|
|
|
|
|
disables this feature. |
877
|
|
|
|
|
|
|
|
878
|
|
|
|
|
|
|
=item index_names |
879
|
|
|
|
|
|
|
|
880
|
|
|
|
|
|
|
Array reference of index file names to check in order when resolving a |
881
|
|
|
|
|
|
|
top-level path. Default is C<< ["index.mp", "index.mc"] >>. An empty list |
882
|
|
|
|
|
|
|
disables this feature. |
883
|
|
|
|
|
|
|
|
884
|
|
|
|
|
|
|
=item no_source_line_numbers |
885
|
|
|
|
|
|
|
|
886
|
|
|
|
|
|
|
Do not put in source line number comments when generating code. Setting this |
887
|
|
|
|
|
|
|
to true will cause error line numbers to reflect the real object file, rather |
888
|
|
|
|
|
|
|
than the source component. |
889
|
|
|
|
|
|
|
|
890
|
|
|
|
|
|
|
=item object_file_extension |
891
|
|
|
|
|
|
|
|
892
|
|
|
|
|
|
|
Extension to add to the end of object files. Default is ".mobj". |
893
|
|
|
|
|
|
|
|
894
|
|
|
|
|
|
|
=item plugins |
895
|
|
|
|
|
|
|
|
896
|
|
|
|
|
|
|
A list of plugins and/or plugin bundles: |
897
|
|
|
|
|
|
|
|
898
|
|
|
|
|
|
|
plugins => [ |
899
|
|
|
|
|
|
|
'OnePlugin', |
900
|
|
|
|
|
|
|
'AnotherPlugin', |
901
|
|
|
|
|
|
|
'+My::Mason::Plugin::AThirdPlugin', |
902
|
|
|
|
|
|
|
'@APluginBundle', |
903
|
|
|
|
|
|
|
'-DontLikeThisPlugin', |
904
|
|
|
|
|
|
|
]); |
905
|
|
|
|
|
|
|
|
906
|
|
|
|
|
|
|
See L<Mason::Manual::Plugins>. |
907
|
|
|
|
|
|
|
|
908
|
|
|
|
|
|
|
=item out_method |
909
|
|
|
|
|
|
|
|
910
|
|
|
|
|
|
|
Default L<out_method|Mason::Request/out_method> passed to each new request. |
911
|
|
|
|
|
|
|
|
912
|
|
|
|
|
|
|
=item pure_perl_extensions |
913
|
|
|
|
|
|
|
|
914
|
|
|
|
|
|
|
A listref of file extensions of components to be considered as pure perl (see |
915
|
|
|
|
|
|
|
L<Pure Perl Components|Mason::Manual::Syntax/Pure_Perl_Components>). Default is |
916
|
|
|
|
|
|
|
C<< ['.mp'] >>. If an empty list is specified, then no components will be |
917
|
|
|
|
|
|
|
considered pure perl. |
918
|
|
|
|
|
|
|
|
919
|
|
|
|
|
|
|
=item static_source |
920
|
|
|
|
|
|
|
|
921
|
|
|
|
|
|
|
True or false, default is false. When false, Mason checks the timestamp of the |
922
|
|
|
|
|
|
|
component source file each time the component is used to see if it has changed. |
923
|
|
|
|
|
|
|
This provides the instant feedback for source changes that is expected for |
924
|
|
|
|
|
|
|
development. However it does entail a file stat for each component executed. |
925
|
|
|
|
|
|
|
|
926
|
|
|
|
|
|
|
When true, Mason assumes that the component source tree is unchanging: it will |
927
|
|
|
|
|
|
|
not check component source files to determine if the memory cache or object |
928
|
|
|
|
|
|
|
file has expired. This can save many file stats per request. However, in order |
929
|
|
|
|
|
|
|
to get Mason to recognize a component source change, you must touch the |
930
|
|
|
|
|
|
|
L<static_source_touch_file|/static_source_touch_file>. |
931
|
|
|
|
|
|
|
|
932
|
|
|
|
|
|
|
We recommend turning this mode on in your production sites if possible, if |
933
|
|
|
|
|
|
|
performance is of any concern. |
934
|
|
|
|
|
|
|
|
935
|
|
|
|
|
|
|
=item static_source_touch_file |
936
|
|
|
|
|
|
|
|
937
|
|
|
|
|
|
|
Specifies a filename that Mason will check once at the beginning of every |
938
|
|
|
|
|
|
|
request when in L<static_source|/static_source> mode. When the file timestamp |
939
|
|
|
|
|
|
|
changes (indicating that a component has changed), Mason will clear its |
940
|
|
|
|
|
|
|
in-memory component cache and recheck existing object files. |
941
|
|
|
|
|
|
|
|
942
|
|
|
|
|
|
|
=item top_level_extensions |
943
|
|
|
|
|
|
|
|
944
|
|
|
|
|
|
|
A listref of file extensions of components to be considered "top level", |
945
|
|
|
|
|
|
|
accessible directly from C<< $interp->run >> or a web request. Default is C<< |
946
|
|
|
|
|
|
|
['.mp', '.mc'] >>. If an empty list is specified, then there will be I<no> |
947
|
|
|
|
|
|
|
restriction; that is, I<all> components will be considered top level. |
948
|
|
|
|
|
|
|
|
949
|
|
|
|
|
|
|
=back |
950
|
|
|
|
|
|
|
|
951
|
|
|
|
|
|
|
=head1 CUSTOM MASON CLASSES |
952
|
|
|
|
|
|
|
|
953
|
|
|
|
|
|
|
These parameters specify alternate classes to use instead of the default |
954
|
|
|
|
|
|
|
Mason:: classes. |
955
|
|
|
|
|
|
|
|
956
|
|
|
|
|
|
|
For example, to use your own Compilation base class: |
957
|
|
|
|
|
|
|
|
958
|
|
|
|
|
|
|
my $interp = Mason->new(base_compilation_class => 'MyApp::Mason::Compilation', ...); |
959
|
|
|
|
|
|
|
|
960
|
|
|
|
|
|
|
L<Relevant plugins|Mason::Manual::Plugins>, if any, will applied to this class |
961
|
|
|
|
|
|
|
to create a final class, which you can get with |
962
|
|
|
|
|
|
|
|
963
|
|
|
|
|
|
|
$interp->compilation_class |
964
|
|
|
|
|
|
|
|
965
|
|
|
|
|
|
|
=over |
966
|
|
|
|
|
|
|
|
967
|
|
|
|
|
|
|
=item base_code_cache_class |
968
|
|
|
|
|
|
|
|
969
|
|
|
|
|
|
|
Specify alternate to L<Mason::CodeCache|Mason::CodeCache> |
970
|
|
|
|
|
|
|
|
971
|
|
|
|
|
|
|
=item base_compilation_class |
972
|
|
|
|
|
|
|
|
973
|
|
|
|
|
|
|
Specify alternate to L<Mason::Compilation|Mason::Compilation> |
974
|
|
|
|
|
|
|
|
975
|
|
|
|
|
|
|
=item base_component_class |
976
|
|
|
|
|
|
|
|
977
|
|
|
|
|
|
|
Specify alternate to L<Mason::Component|Mason::Component> |
978
|
|
|
|
|
|
|
|
979
|
|
|
|
|
|
|
=item base_component_moose_class |
980
|
|
|
|
|
|
|
|
981
|
|
|
|
|
|
|
Specify alternate to L<Mason::Component::Moose|Mason::Component::Moose> |
982
|
|
|
|
|
|
|
|
983
|
|
|
|
|
|
|
=item base_component_class_meta_class |
984
|
|
|
|
|
|
|
|
985
|
|
|
|
|
|
|
Specify alternate to L<Mason::Component::ClassMeta|Mason::Component::ClassMeta> |
986
|
|
|
|
|
|
|
|
987
|
|
|
|
|
|
|
=item base_component_import_class |
988
|
|
|
|
|
|
|
|
989
|
|
|
|
|
|
|
Specify alternate to L<Mason::Component::Import|Mason::Component::Import> |
990
|
|
|
|
|
|
|
|
991
|
|
|
|
|
|
|
=item base_request_class |
992
|
|
|
|
|
|
|
|
993
|
|
|
|
|
|
|
Specify alternate to L<Mason::Request|Mason::Request> |
994
|
|
|
|
|
|
|
|
995
|
|
|
|
|
|
|
=item base_result_class |
996
|
|
|
|
|
|
|
|
997
|
|
|
|
|
|
|
Specify alternate to L<Mason::Result|Mason::Result> |
998
|
|
|
|
|
|
|
|
999
|
|
|
|
|
|
|
=back |
1000
|
|
|
|
|
|
|
|
1001
|
|
|
|
|
|
|
=head1 PUBLIC METHODS |
1002
|
|
|
|
|
|
|
|
1003
|
|
|
|
|
|
|
=over |
1004
|
|
|
|
|
|
|
|
1005
|
|
|
|
|
|
|
=item all_paths ([dir_path]) |
1006
|
|
|
|
|
|
|
|
1007
|
|
|
|
|
|
|
Returns a list of distinct component paths under I<dir_path>, which defaults to |
1008
|
|
|
|
|
|
|
'/' if not provided. For example, |
1009
|
|
|
|
|
|
|
|
1010
|
|
|
|
|
|
|
$interp->all_paths('/foo/bar') |
1011
|
|
|
|
|
|
|
=> ('/foo/bar/baz.mc', '/foo/bar/blargh.mc') |
1012
|
|
|
|
|
|
|
|
1013
|
|
|
|
|
|
|
Note that these are all component paths, not filenames, and all component roots |
1014
|
|
|
|
|
|
|
are searched if there are multiple ones. |
1015
|
|
|
|
|
|
|
|
1016
|
|
|
|
|
|
|
=item comp_exists (path) |
1017
|
|
|
|
|
|
|
|
1018
|
|
|
|
|
|
|
Returns a boolean indicating whether a component exists for the absolute |
1019
|
|
|
|
|
|
|
component I<path>. |
1020
|
|
|
|
|
|
|
|
1021
|
|
|
|
|
|
|
=item count |
1022
|
|
|
|
|
|
|
|
1023
|
|
|
|
|
|
|
Returns the number of this interpreter, a monotonically increasing integer for |
1024
|
|
|
|
|
|
|
the process starting at 0. |
1025
|
|
|
|
|
|
|
|
1026
|
|
|
|
|
|
|
=item flush_code_cache |
1027
|
|
|
|
|
|
|
|
1028
|
|
|
|
|
|
|
Empties the component cache and removes all component classes. |
1029
|
|
|
|
|
|
|
|
1030
|
|
|
|
|
|
|
=item glob_paths (pattern) |
1031
|
|
|
|
|
|
|
|
1032
|
|
|
|
|
|
|
Returns a list of all component paths matching the glob I<pattern>. e.g. |
1033
|
|
|
|
|
|
|
|
1034
|
|
|
|
|
|
|
$interp->glob_paths('/foo/b*.mc') |
1035
|
|
|
|
|
|
|
=> ('/foo/bar.mc', '/foo/baz.mc') |
1036
|
|
|
|
|
|
|
|
1037
|
|
|
|
|
|
|
Note that these are all component paths, not filenames, and all component roots |
1038
|
|
|
|
|
|
|
are searched if there are multiple ones. |
1039
|
|
|
|
|
|
|
|
1040
|
|
|
|
|
|
|
=item load (path) |
1041
|
|
|
|
|
|
|
|
1042
|
|
|
|
|
|
|
Returns the component object corresponding to an absolute component I<path>, or |
1043
|
|
|
|
|
|
|
undef if none exists. Dies with an error if the component fails to load because |
1044
|
|
|
|
|
|
|
of a syntax error. |
1045
|
|
|
|
|
|
|
|
1046
|
|
|
|
|
|
|
=item object_dir |
1047
|
|
|
|
|
|
|
|
1048
|
|
|
|
|
|
|
Returns the directory containing component object files. |
1049
|
|
|
|
|
|
|
|
1050
|
|
|
|
|
|
|
=item run ([request params], path, args...) |
1051
|
|
|
|
|
|
|
|
1052
|
|
|
|
|
|
|
Creates a new L<Mason::Request|Mason::Request> object for the given I<path> and |
1053
|
|
|
|
|
|
|
I<args>, and executes it. Returns a L<Mason::Result|Mason::Result> object, |
1054
|
|
|
|
|
|
|
which is generally accessed to get the output. e.g. |
1055
|
|
|
|
|
|
|
|
1056
|
|
|
|
|
|
|
my $output = $interp->run('/foo/bar', baz => 5)->output; |
1057
|
|
|
|
|
|
|
|
1058
|
|
|
|
|
|
|
The first argument may optionally be a hashref of request parameters, which are |
1059
|
|
|
|
|
|
|
passed to the Mason::Request constructor. e.g. this tells the request to output |
1060
|
|
|
|
|
|
|
to standard output: |
1061
|
|
|
|
|
|
|
|
1062
|
|
|
|
|
|
|
$interp->run({out_method => sub { print $_[0] }}, '/foo/bar', baz => 5); |
1063
|
|
|
|
|
|
|
|
1064
|
|
|
|
|
|
|
=item set_global (varname, value) |
1065
|
|
|
|
|
|
|
|
1066
|
|
|
|
|
|
|
Set the global I<varname> to I<value>. This will be visible in all components |
1067
|
|
|
|
|
|
|
loaded by this interpreter. The variables must be on the |
1068
|
|
|
|
|
|
|
L<allow_globals|/allow_globals> list. |
1069
|
|
|
|
|
|
|
|
1070
|
|
|
|
|
|
|
$interp->set_global('$scalar', 5); |
1071
|
|
|
|
|
|
|
$interp->set_global('$scalar2', $some_object); |
1072
|
|
|
|
|
|
|
|
1073
|
|
|
|
|
|
|
See also L<set_global|Mason::Request/set_global>. |
1074
|
|
|
|
|
|
|
|
1075
|
|
|
|
|
|
|
=back |
1076
|
|
|
|
|
|
|
|
1077
|
|
|
|
|
|
|
=head1 MODIFIABLE METHODS |
1078
|
|
|
|
|
|
|
|
1079
|
|
|
|
|
|
|
These methods are not intended to be called externally, but may be useful to |
1080
|
|
|
|
|
|
|
modify with method modifiers in L<plugins|Mason::Manual::Plugins> and |
1081
|
|
|
|
|
|
|
L<subclasses|Mason::Manual::Subclasses>. Their APIs will be kept as stable as |
1082
|
|
|
|
|
|
|
possible. |
1083
|
|
|
|
|
|
|
|
1084
|
|
|
|
|
|
|
=over |
1085
|
|
|
|
|
|
|
|
1086
|
|
|
|
|
|
|
=item is_pure_perl_comp_path ($path) |
1087
|
|
|
|
|
|
|
|
1088
|
|
|
|
|
|
|
Determines whether I<$path> is a pure Perl component - by default, uses |
1089
|
|
|
|
|
|
|
L<pure_perl_extensions|/pure_perl_extensions>. |
1090
|
|
|
|
|
|
|
|
1091
|
|
|
|
|
|
|
=item is_top_level_comp_path ($path) |
1092
|
|
|
|
|
|
|
|
1093
|
|
|
|
|
|
|
Determines whether I<$path> is a valid top-level component - by default, uses |
1094
|
|
|
|
|
|
|
L<top_level_extensions|/top_level_extensions>. |
1095
|
|
|
|
|
|
|
|
1096
|
|
|
|
|
|
|
=item modify_loaded_class ( $compc ) |
1097
|
|
|
|
|
|
|
|
1098
|
|
|
|
|
|
|
An opportunity to modify loaded component class I<$compc> (e.g. add additional |
1099
|
|
|
|
|
|
|
methods or apply roles) before it is made immutable. |
1100
|
|
|
|
|
|
|
|
1101
|
|
|
|
|
|
|
=item write_object_file ($object_file, $object_contents) |
1102
|
|
|
|
|
|
|
|
1103
|
|
|
|
|
|
|
Write compiled component I<$object_contents> to I<$object_file>. This is an |
1104
|
|
|
|
|
|
|
opportunity to modify I<$object_contents> before it is written, or |
1105
|
|
|
|
|
|
|
I<$object_file> after it is written. |
1106
|
|
|
|
|
|
|
|
1107
|
|
|
|
|
|
|
=back |
1108
|
|
|
|
|
|
|
|
1109
|
|
|
|
|
|
|
=head1 SEE ALSO |
1110
|
|
|
|
|
|
|
|
1111
|
|
|
|
|
|
|
L<Mason|Mason> |
1112
|
|
|
|
|
|
|
|
1113
|
|
|
|
|
|
|
=head1 AUTHOR |
1114
|
|
|
|
|
|
|
|
1115
|
|
|
|
|
|
|
Jonathan Swartz <swartz@pobox.com> |
1116
|
|
|
|
|
|
|
|
1117
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
1118
|
|
|
|
|
|
|
|
1119
|
|
|
|
|
|
|
This software is copyright (c) 2012 by Jonathan Swartz. |
1120
|
|
|
|
|
|
|
|
1121
|
|
|
|
|
|
|
This is free software; you can redistribute it and/or modify it under |
1122
|
|
|
|
|
|
|
the same terms as the Perl 5 programming language system itself. |
1123
|
|
|
|
|
|
|
|
1124
|
|
|
|
|
|
|
=cut |