Filename | /Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Mojo/Base.pm |
Statements | Executed 8454515 statements in 8.25s |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1651801 | 4 | 4 | 1.40s | 1.40s | new | Mojo::Base::
1268270 | 26 | 11 | 1.02s | 1.02s | fragment | Mojo::URL::
599695 | 4 | 1 | 536ms | 536ms | scheme | Mojo::URL::
496644 | 2 | 1 | 465ms | 465ms | charset | Mojo::Path::
515470 | 4 | 1 | 392ms | 392ms | host | Mojo::URL::
329583 | 1 | 1 | 385ms | 385ms | charset | Mojo::Parameters::
378040 | 2 | 1 | 228ms | 228ms | port | Mojo::URL::
146708 | 3 | 1 | 79.1ms | 79.1ms | CORE:subst (opcode) | Mojo::JSON::Pointer::
33963 | 1 | 1 | 65.8ms | 65.8ms | base | Mojo::URL::
70252 | 2 | 1 | 60.3ms | 60.3ms | userinfo | Mojo::URL::
1 | 1 | 1 | 4.17ms | 4.46ms | BEGIN@17 | Mojo::Base::
211 | 1 | 1 | 877µs | 877µs | CORE:match (opcode) | Mojo::JSON::Pointer::
1 | 1 | 1 | 752µs | 833µs | BEGIN@5 | Mojo::Base::
12 | 12 | 8 | 426µs | 1.43ms | import | Mojo::Base::
5 | 1 | 1 | 137µs | 296µs | attr | Mojo::Base::
1 | 1 | 1 | 108µs | 140µs | BEGIN@20 | Mojo::Base::
15 | 2 | 1 | 47µs | 47µs | CORE:match (opcode) | Mojo::Base::
1 | 1 | 1 | 26µs | 31µs | BEGIN@3 | Mojo::Base::
2 | 2 | 1 | 12µs | 156µs | has | Mojo::URL::
1 | 1 | 1 | 11µs | 18µs | BEGIN@133 | Mojo::Base::
1 | 1 | 1 | 10µs | 17µs | BEGIN@45 | Mojo::Base::
1 | 1 | 1 | 10µs | 12µs | BEGIN@7 | Mojo::Base::
1 | 1 | 1 | 9µs | 103µs | BEGIN@6 | Mojo::Base::
1 | 1 | 1 | 8µs | 67µs | has | Mojo::Parameters::
1 | 1 | 1 | 6µs | 44µs | BEGIN@4 | Mojo::Base::
1 | 1 | 1 | 6µs | 66µs | has | Mojo::Path::
1 | 1 | 1 | 5µs | 38µs | has | Mojo::JSON::Pointer::
1 | 1 | 1 | 3µs | 3µs | BEGIN@10 | Mojo::Base::
1 | 1 | 1 | 2µs | 2µs | BEGIN@11 | Mojo::Base::
0 | 0 | 0 | 0s | 0s | DESTROY | Mojo::Base::
0 | 0 | 0 | 0s | 0s | __ANON__[:113] | Mojo::Base::
0 | 0 | 0 | 0s | 0s | __ANON__[:136] | Mojo::Base::
0 | 0 | 0 | 0s | 0s | __ANON__[:43] | Mojo::Base::
0 | 0 | 0 | 0s | 0s | __ANON__[:66] | Mojo::Base::
0 | 0 | 0 | 0s | 0s | __ANON__[:73] | Mojo::Base::
0 | 0 | 0 | 0s | 0s | __ANON__[:81] | Mojo::Base::
0 | 0 | 0 | 0s | 0s | __ANON__[:88] | Mojo::Base::
0 | 0 | 0 | 0s | 0s | __ANON__[:91] | Mojo::Base::
0 | 0 | 0 | 0s | 0s | tap | Mojo::Base::
0 | 0 | 0 | 0s | 0s | with_roles | Mojo::Base::
0 | 0 | 0 | 0s | 0s | data | Mojo::JSON::Pointer::
0 | 0 | 0 | 0s | 0s | has | Mojo::Util::_Guard::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | package Mojo::Base; | ||||
2 | |||||
3 | 2 | 35µs | 2 | 36µs | # spent 31µs (26+5) within Mojo::Base::BEGIN@3 which was called:
# once (26µs+5µs) by Mojo::URL::BEGIN@2 at line 3 # spent 31µs making 1 call to Mojo::Base::BEGIN@3
# spent 5µs making 1 call to strict::import |
4 | 2 | 20µs | 2 | 82µs | # spent 44µs (6+38) within Mojo::Base::BEGIN@4 which was called:
# once (6µs+38µs) by Mojo::URL::BEGIN@2 at line 4 # spent 44µs making 1 call to Mojo::Base::BEGIN@4
# spent 38µs making 1 call to warnings::import |
5 | 2 | 983µs | 2 | 835µs | # spent 833µs (752+81) within Mojo::Base::BEGIN@5 which was called:
# once (752µs+81µs) by Mojo::URL::BEGIN@2 at line 5 # spent 833µs making 1 call to Mojo::Base::BEGIN@5
# spent 2µs making 1 call to utf8::import |
6 | 2 | 31µs | 2 | 197µs | # spent 103µs (9+94) within Mojo::Base::BEGIN@6 which was called:
# once (9µs+94µs) by Mojo::URL::BEGIN@2 at line 6 # spent 103µs making 1 call to Mojo::Base::BEGIN@6
# spent 94µs making 1 call to feature::import |
7 | 2 | 23µs | 2 | 14µs | # spent 12µs (10+2) within Mojo::Base::BEGIN@7 which was called:
# once (10µs+2µs) by Mojo::URL::BEGIN@2 at line 7 # spent 12µs making 1 call to Mojo::Base::BEGIN@7
# spent 2µs making 1 call to mro::import |
8 | |||||
9 | # No imports because we get subclassed, a lot! | ||||
10 | 2 | 15µs | 1 | 3µs | # spent 3µs within Mojo::Base::BEGIN@10 which was called:
# once (3µs+0s) by Mojo::URL::BEGIN@2 at line 10 # spent 3µs making 1 call to Mojo::Base::BEGIN@10 |
11 | 2 | 72µs | 1 | 2µs | # spent 2µs within Mojo::Base::BEGIN@11 which was called:
# once (2µs+0s) by Mojo::URL::BEGIN@2 at line 11 # spent 2µs making 1 call to Mojo::Base::BEGIN@11 |
12 | |||||
13 | # Defer to runtime so Mojo::Util can use "-strict" | ||||
14 | 1 | 696µs | require Mojo::Util; | ||
15 | |||||
16 | # Role support requires Role::Tiny 2.000001+ | ||||
17 | 5 | 972µs | 3 | 4.53ms | # spent 4.46ms (4.17+285µs) within Mojo::Base::BEGIN@17 which was called:
# once (4.17ms+285µs) by Mojo::URL::BEGIN@2 at line 17 # spent 4.46ms making 1 call to Mojo::Base::BEGIN@17
# spent 61µs making 1 call to constant::import
# spent 8µs making 1 call to UNIVERSAL::VERSION |
18 | |||||
19 | # async/await support requires Future::AsyncAwait 0.52+ | ||||
20 | # spent 140µs (108+32) within Mojo::Base::BEGIN@20 which was called:
# once (108µs+32µs) by Mojo::URL::BEGIN@2 at line 22 | ||||
21 | ? 0 | ||||
22 | 3 | 333µs | 2 | 172µs | : !!(eval { require Future::AsyncAwait; Future::AsyncAwait->VERSION('0.52'); 1 }); # spent 140µs making 1 call to Mojo::Base::BEGIN@20
# spent 32µs making 1 call to constant::import |
23 | |||||
24 | # Protect subclasses using AUTOLOAD | ||||
25 | sub DESTROY { } | ||||
26 | |||||
27 | # spent 296µs (137+159) within Mojo::Base::attr which was called 5 times, avg 59µs/call:
# 5 times (137µs+159µs) by Mojo::JSON::Pointer::has or Mojo::Parameters::has or Mojo::Path::has or Mojo::URL::has at line 136, avg 59µs/call | ||||
28 | 5 | 7µs | my ($self, $attrs, $value, %kv) = @_; | ||
29 | 5 | 6µs | return unless (my $class = ref $self || $self) && $attrs; | ||
30 | |||||
31 | 5 | 4µs | Carp::croak 'Default has to be a code reference or constant value' if ref $value && ref $value ne 'CODE'; | ||
32 | 5 | 5µs | Carp::croak 'Unsupported attribute option' if grep { $_ ne 'weak' } keys %kv; | ||
33 | |||||
34 | # Weaken | ||||
35 | 5 | 4µs | if ($kv{weak}) { | ||
36 | state %weak_names; | ||||
37 | unless ($weak_names{$class}) { | ||||
38 | my $names = $weak_names{$class} = []; | ||||
39 | my $sub = sub { | ||||
40 | my $self = shift->next::method(@_); | ||||
41 | ref $self->{$_} and Scalar::Util::weaken $self->{$_} for @$names; | ||||
42 | return $self; | ||||
43 | }; | ||||
44 | Mojo::Util::monkey_patch(my $base = $class . '::_Base', 'new', $sub); | ||||
45 | 2 | 1.11ms | 2 | 24µs | # spent 17µs (10+7) within Mojo::Base::BEGIN@45 which was called:
# once (10µs+7µs) by Mojo::URL::BEGIN@2 at line 45 # spent 17µs making 1 call to Mojo::Base::BEGIN@45
# spent 7µs making 1 call to strict::unimport |
46 | unshift @{"${class}::ISA"}, $base; | ||||
47 | } | ||||
48 | push @{$weak_names{$class}}, ref $attrs eq 'ARRAY' ? @$attrs : $attrs; | ||||
49 | } | ||||
50 | |||||
51 | 5 | 28µs | for my $attr (@{ref $attrs eq 'ARRAY' ? $attrs : [$attrs]}) { | ||
52 | 9 | 62µs | 9 | 33µs | Carp::croak qq{Attribute "$attr" invalid} unless $attr =~ /^[a-zA-Z_]\w*$/; # spent 33µs making 9 calls to Mojo::Base::CORE:match, avg 4µs/call |
53 | |||||
54 | # Very performance-sensitive code with lots of micro-optimizations | ||||
55 | 9 | 1µs | my $sub; | ||
56 | 9 | 8µs | if ($kv{weak}) { | ||
57 | if (ref $value) { | ||||
58 | $sub = sub { | ||||
59 | return | ||||
60 | exists $_[0]{$attr} | ||||
61 | ? $_[0]{$attr} | ||||
62 | : (ref($_[0]{$attr} = $value->($_[0])) && Scalar::Util::weaken($_[0]{$attr}), $_[0]{$attr}) | ||||
63 | if @_ == 1; | ||||
64 | ref($_[0]{$attr} = $_[1]) and Scalar::Util::weaken($_[0]{$attr}); | ||||
65 | $_[0]; | ||||
66 | }; | ||||
67 | } | ||||
68 | else { | ||||
69 | $sub = sub { | ||||
70 | return $_[0]{$attr} if @_ == 1; | ||||
71 | ref($_[0]{$attr} = $_[1]) and Scalar::Util::weaken($_[0]{$attr}); | ||||
72 | $_[0]; | ||||
73 | }; | ||||
74 | } | ||||
75 | } | ||||
76 | elsif (ref $value) { | ||||
77 | # spent 65.8ms within Mojo::URL::base which was called 33963 times, avg 2µs/call:
# 33963 times (65.8ms+0s) by Mojo::URL::to_abs at line 128 of Mojo/URL.pm, avg 2µs/call | ||||
78 | 33963 | 14.3ms | return exists $_[0]{$attr} ? $_[0]{$attr} : ($_[0]{$attr} = $value->($_[0])) if @_ == 1; | ||
79 | 33963 | 25.4ms | $_[0]{$attr} = $_[1]; | ||
80 | 33963 | 44.2ms | $_[0]; | ||
81 | 1 | 3µs | }; | ||
82 | } | ||||
83 | elsif (defined $value) { | ||||
84 | # spent 385ms within Mojo::Parameters::charset which was called 329583 times, avg 1µs/call:
# 329583 times (385ms+0s) by Mojo::Parameters::to_string at line 150 of Mojo/Parameters.pm, avg 1µs/call
# spent 465ms within Mojo::Path::charset which was called 496644 times, avg 937ns/call:
# 368028 times (308ms+0s) by Mojo::Path::to_string at line 84 of Mojo/Path.pm, avg 838ns/call
# 128616 times (157ms+0s) by Mojo::Path::_parse at line 106 of Mojo/Path.pm, avg 1µs/call | ||||
85 | 826227 | 1.42s | return exists $_[0]{$attr} ? $_[0]{$attr} : ($_[0]{$attr} = $value) if @_ == 1; | ||
86 | $_[0]{$attr} = $_[1]; | ||||
87 | $_[0]; | ||||
88 | 2 | 13µs | }; | ||
89 | } | ||||
90 | else { | ||||
91 | 4222627 | 4.18s | # spent 228ms within Mojo::URL::port which was called 378040 times, avg 603ns/call:
# 310114 times (163ms+0s) by Mojo::URL::host_port at line 30 of Mojo/URL.pm, avg 527ns/call
# 67926 times (64.5ms+0s) by Mojo::URL::to_abs at line 132 of Mojo/URL.pm, avg 949ns/call
# spent 392ms within Mojo::URL::host which was called 515470 times, avg 761ns/call:
# 313722 times (215ms+0s) by Mojo::URL::ihost at line 41 of Mojo/URL.pm, avg 686ns/call
# 99859 times (93.4ms+0s) by Mojo::URL::host_port at line 26 of Mojo/URL.pm, avg 936ns/call
# 67926 times (64.0ms+0s) by Mojo::URL::to_abs at line 132 of Mojo/URL.pm, avg 942ns/call
# 33963 times (19.7ms+0s) by Mojo::URL::to_abs at line 131 of Mojo/URL.pm, avg 580ns/call
# spent 60.3ms within Mojo::URL::userinfo which was called 70252 times, avg 858ns/call:
# 67926 times (59.1ms+0s) by Mojo::URL::to_abs at line 132 of Mojo/URL.pm, avg 870ns/call
# 2326 times (1.23ms+0s) by Mojo::URL::_string at line 171 of Mojo/URL.pm, avg 528ns/call
# spent 1.02s within Mojo::URL::fragment which was called 1268270 times, avg 800ns/call:
# 337182 times (343ms+0s) by JSON::Schema::Modern::Utilities::canonical_uri at line 189 of JSON/Schema/Modern/Utilities.pm, avg 1µs/call
# 313722 times (215ms+0s) by Mojo::URL::_string at line 181 of Mojo/URL.pm, avg 684ns/call
# 194464 times (98.4ms+0s) by JSON::Schema::Modern::Utilities::canonical_uri at line 190 of JSON/Schema/Modern/Utilities.pm, avg 506ns/call
# 89213 times (55.8ms+0s) by JSON::Schema::Modern::_fetch_from_uri at line 835 of JSON/Schema/Modern.pm, avg 625ns/call
# 72037 times (41.7ms+0s) by JSON::Schema::Modern::Utilities::A at line 247 of JSON/Schema/Modern/Utilities.pm, avg 579ns/call
# 64986 times (39.7ms+0s) by JSON::Schema::Modern::_fetch_from_uri at line 840 of JSON/Schema/Modern.pm, avg 611ns/call
# 58673 times (65.2ms+0s) by Mojo::URL::parse at line 60 of Mojo/URL.pm, avg 1µs/call
# 46881 times (36.7ms+0s) by JSON::Schema::Modern::_fetch_from_uri at line 823 of JSON/Schema/Modern.pm, avg 783ns/call
# 39123 times (67.7ms+0s) by JSON::Schema::Modern::_fetch_from_uri at line 839 of JSON/Schema/Modern.pm, avg 2µs/call
# 39123 times (43.2ms+0s) by JSON::Schema::Modern::_fetch_from_uri at line 826 of JSON/Schema/Modern.pm, avg 1µs/call
# 5172 times (3.57ms+0s) by JSON::Schema::Modern::Vocabulary::Core::_eval_keyword_dynamicRef at line 228 of JSON/Schema/Modern/Vocabulary/Core.pm, avg 690ns/call
# 4217 times (2.35ms+0s) by JSON::Schema::Modern::Utilities::E at line 213 of JSON/Schema/Modern/Utilities.pm, avg 557ns/call
# 2586 times (2.62ms+0s) by JSON::Schema::Modern::Vocabulary::Core::_eval_keyword_dynamicRef at line 234 of JSON/Schema/Modern/Vocabulary/Core.pm, avg 1µs/call
# 758 times (389µs+0s) by JSON::Schema::Modern::traverse at line 258 of JSON/Schema/Modern.pm, avg 513ns/call
# 36 times (21µs+0s) by JSON::Schema::Modern::Document::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/JSON/Schema/Modern/Document.pm:135] at line 131 of JSON/Schema/Modern/Document.pm, avg 583ns/call
# 18 times (19µs+0s) by JSON::Schema::Modern::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/JSON/Schema/Modern.pm:646] at line 637 of JSON/Schema/Modern.pm, avg 1µs/call
# 15 times (20µs+0s) by JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_anchor at line 162 of JSON/Schema/Modern/Vocabulary/Core.pm, avg 1µs/call
# 14 times (16µs+0s) by JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_id at line 66 of JSON/Schema/Modern/Vocabulary/Core.pm, avg 1µs/call
# 14 times (8µs+0s) by JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_id at line 62 of JSON/Schema/Modern/Vocabulary/Core.pm, avg 571ns/call
# 10 times (6µs+0s) by JSON::Schema::Modern::Document::_set_canonical_uri at line 39 of (eval 264)[Sub/Quote.pm:3], avg 600ns/call
# 9 times (9µs+0s) by JSON::Schema::Modern::add_schema at line 143 of JSON/Schema/Modern.pm, avg 1µs/call
# 8 times (12µs+0s) by JSON::Schema::Modern::Document::canonical_uri at line 44 of (eval 263)[Sub/Quote.pm:3], avg 2µs/call
# 6 times (6µs+0s) by JSON::Schema::Modern::Document::new at line 74 of (eval 424)[Sub/Quote.pm:3], avg 1µs/call
# once (3µs+0s) by JSON::Schema::Modern::Document::OpenAPI::new at line 77 of (eval 417)[Sub/Quote.pm:3]
# once (1µs+0s) by JSON::Schema::Modern::Document::OpenAPI::traverse at line 115 of JSON/Schema/Modern/Document/OpenAPI.pm
# once (1µs+0s) by Type::Tiny::__ANON__[(eval 421)[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Sub/Quote.pm:3]:16] at line 16 of (eval 421)[Sub/Quote.pm:3]
# spent 536ms within Mojo::URL::scheme which was called 599695 times, avg 894ns/call:
# 313722 times (244ms+0s) by Mojo::URL::protocol at line 96 of Mojo/URL.pm, avg 778ns/call
# 118188 times (99.1ms+0s) by Mojo::URL::is_abs at line 48 of Mojo/URL.pm, avg 839ns/call
# 99859 times (132ms+0s) by Mojo::URL::parse at line 57 of Mojo/URL.pm, avg 1µs/call
# 67926 times (61.0ms+0s) by Mojo::URL::to_abs at line 128 of Mojo/URL.pm, avg 898ns/call | ||
92 | } | ||||
93 | 9 | 15µs | 9 | 126µs | Mojo::Util::monkey_patch($class, $attr, $sub); # spent 126µs making 9 calls to Mojo::Util::monkey_patch, avg 14µs/call |
94 | } | ||||
95 | } | ||||
96 | |||||
97 | # spent 1.43ms (426µs+1.01) within Mojo::Base::import which was called 12 times, avg 119µs/call:
# once (102µs+335µs) by Mojo::Util::BEGIN@2 at line 2 of Mojo/Util.pm
# once (83µs+160µs) by Mojo::Parameters::BEGIN@2 at line 2 of Mojo/Parameters.pm
# once (64µs+155µs) by Mojo::Util::_Guard::BEGIN@538 at line 538 of Mojo/Util.pm
# once (45µs+142µs) by Mojo::Path::BEGIN@2 at line 2 of Mojo/Path.pm
# once (70µs+111µs) by Mojo::JSON::Pointer::BEGIN@2 at line 2 of Mojo/JSON/Pointer.pm
# once (35µs+105µs) by Mojo::URL::BEGIN@2 at line 2 of Mojo/URL.pm
# once (6µs+0s) by JSON::Schema::Modern::BEGIN@35 at line 35 of JSON/Schema/Modern.pm
# once (5µs+0s) by Mojo::URL::BEGIN@6 at line 6 of Mojo/URL.pm
# once (4µs+0s) by Mojo::URL::BEGIN@5 at line 5 of Mojo/URL.pm
# once (4µs+0s) by JSON::Schema::Modern::Document::BEGIN@17 at line 17 of JSON/Schema/Modern/Document.pm
# once (4µs+0s) by OpenAPI::Modern::BEGIN@28 at line 28 of OpenAPI/Modern.pm
# once (4µs+0s) by JSON::Schema::Modern::BEGIN@23 at line 23 of JSON/Schema/Modern.pm | ||||
98 | 12 | 33µs | my ($class, $caller) = (shift, caller); | ||
99 | 12 | 33µs | return unless my @flags = @_; | ||
100 | |||||
101 | # Mojo modules are strict! | ||||
102 | 6 | 176µs | 18 | 344µs | $_->import for qw(strict warnings utf8); # spent 311µs making 6 calls to warnings::import, avg 52µs/call
# spent 21µs making 6 calls to strict::import, avg 4µs/call
# spent 12µs making 6 calls to utf8::import, avg 2µs/call |
103 | 6 | 18µs | 6 | 560µs | feature->import(':5.16'); # spent 560µs making 6 calls to feature::import, avg 93µs/call |
104 | |||||
105 | 6 | 44µs | while (my $flag = shift @flags) { | ||
106 | |||||
107 | # Base | ||||
108 | 11 | 52µs | 6 | 14µs | if ($flag eq '-base') { push @flags, $class } # spent 14µs making 6 calls to Mojo::Base::CORE:match, avg 2µs/call |
109 | |||||
110 | # Role | ||||
111 | elsif ($flag eq '-role') { | ||||
112 | Carp::croak 'Role::Tiny 2.000001+ is required for roles' unless ROLES; | ||||
113 | Mojo::Util::monkey_patch($caller, 'has', sub { attr($caller, @_) }); | ||||
114 | eval "package $caller; use Role::Tiny; 1" or die $@; | ||||
115 | } | ||||
116 | |||||
117 | # async/await | ||||
118 | elsif ($flag eq '-async_await') { | ||||
119 | Carp::croak 'Future::AsyncAwait 0.52+ is required for async/await' unless ASYNC; | ||||
120 | require Mojo::Promise; | ||||
121 | Future::AsyncAwait->import_into($caller, future_class => 'Mojo::Promise'); | ||||
122 | } | ||||
123 | |||||
124 | # Signatures (Perl 5.20+) | ||||
125 | elsif ($flag eq '-signatures') { | ||||
126 | Carp::croak 'Subroutine signatures require Perl 5.20+' if $] < 5.020; | ||||
127 | require experimental; | ||||
128 | experimental->import($_) for qw(signatures postderef); | ||||
129 | } | ||||
130 | |||||
131 | # Module | ||||
132 | elsif ($flag !~ /^-/) { | ||||
133 | 2 | 873µs | 2 | 25µs | # spent 18µs (11+7) within Mojo::Base::BEGIN@133 which was called:
# once (11µs+7µs) by Mojo::URL::BEGIN@2 at line 133 # spent 18µs making 1 call to Mojo::Base::BEGIN@133
# spent 7µs making 1 call to strict::unimport |
134 | 5 | 35µs | 5 | 11µs | require(Mojo::Util::class_to_path($flag)) unless $flag->can('new'); # spent 11µs making 5 calls to UNIVERSAL::can, avg 2µs/call |
135 | 5 | 31µs | push @{"${caller}::ISA"}, $flag; | ||
136 | 10 | 46µs | 10 | 375µs | # spent 156µs (12+144) within Mojo::URL::has which was called 2 times, avg 78µs/call:
# once (3µs+86µs) by JSON::Schema::Modern::BEGIN@23 at line 10 of Mojo/URL.pm
# once (9µs+58µs) by JSON::Schema::Modern::BEGIN@23 at line 9 of Mojo/URL.pm
# spent 67µs (8+59) within Mojo::Parameters::has which was called:
# once (8µs+59µs) by Mojo::URL::BEGIN@5 at line 7 of Mojo/Parameters.pm
# spent 38µs (5+33) within Mojo::JSON::Pointer::has which was called:
# once (5µs+33µs) by Moo::_Utils::_require at line 4 of Mojo/JSON/Pointer.pm
# spent 66µs (6+60) within Mojo::Path::has which was called:
# once (6µs+60µs) by Mojo::URL::BEGIN@6 at line 7 of Mojo/Path.pm # spent 296µs making 5 calls to Mojo::Base::attr, avg 59µs/call
# spent 79µs making 5 calls to Mojo::Util::monkey_patch, avg 16µs/call |
137 | } | ||||
138 | |||||
139 | elsif ($flag ne '-strict') { Carp::croak "Unsupported flag: $flag" } | ||||
140 | } | ||||
141 | } | ||||
142 | |||||
143 | # spent 1.40s within Mojo::Base::new which was called 1651801 times, avg 846ns/call:
# 658284 times (481ms+0s) by Mojo::Path::new at line 53 of Mojo/Path.pm, avg 731ns/call
# 567983 times (584ms+0s) by Mojo::URL::new at line 50 of Mojo/URL.pm, avg 1µs/call
# 425519 times (331ms+0s) by Mojo::Parameters::new at line 63 of Mojo/Parameters.pm, avg 779ns/call
# 15 times (38µs+0s) by Mojo::JSON::Pointer::new at line 9 of Mojo/JSON/Pointer.pm, avg 3µs/call | ||||
144 | 1651801 | 205ms | my $class = shift; | ||
145 | 1651801 | 2.35s | bless @_ ? @_ > 1 ? {@_} : {%{$_[0]}} : {}, ref $class || $class; | ||
146 | } | ||||
147 | |||||
148 | sub tap { | ||||
149 | my ($self, $cb) = (shift, shift); | ||||
150 | $_->$cb(@_) for $self; | ||||
151 | return $self; | ||||
152 | } | ||||
153 | |||||
154 | sub with_roles { | ||||
155 | Carp::croak 'Role::Tiny 2.000001+ is required for roles' unless ROLES; | ||||
156 | my ($self, @roles) = @_; | ||||
157 | return $self unless @roles; | ||||
158 | |||||
159 | return Role::Tiny->create_class_with_roles($self, map { /^\+(.+)$/ ? "${self}::Role::$1" : $_ } @roles) | ||||
160 | unless my $class = Scalar::Util::blessed $self; | ||||
161 | |||||
162 | return Role::Tiny->apply_roles_to_object($self, map { /^\+(.+)$/ ? "${class}::Role::$1" : $_ } @roles); | ||||
163 | } | ||||
164 | |||||
165 | 1 | 3µs | 1; | ||
166 | |||||
167 | =encoding utf8 | ||||
168 | |||||
169 | =head1 NAME | ||||
170 | |||||
171 | Mojo::Base - Minimal base class for Mojo projects | ||||
172 | |||||
173 | =head1 SYNOPSIS | ||||
174 | |||||
175 | package Cat; | ||||
176 | use Mojo::Base -base; | ||||
177 | |||||
178 | has name => 'Nyan'; | ||||
179 | has ['age', 'weight'] => 4; | ||||
180 | |||||
181 | package Tiger; | ||||
182 | use Mojo::Base 'Cat'; | ||||
183 | |||||
184 | has friend => sub { Cat->new }; | ||||
185 | has stripes => 42; | ||||
186 | |||||
187 | package main; | ||||
188 | use Mojo::Base -strict; | ||||
189 | |||||
190 | my $mew = Cat->new(name => 'Longcat'); | ||||
191 | say $mew->age; | ||||
192 | say $mew->age(3)->weight(5)->age; | ||||
193 | |||||
194 | my $rawr = Tiger->new(stripes => 38, weight => 250); | ||||
195 | say $rawr->tap(sub { $_->friend->name('Tacgnol') })->weight; | ||||
196 | |||||
197 | =head1 DESCRIPTION | ||||
198 | |||||
199 | L<Mojo::Base> is a simple base class for L<Mojo> projects with fluent interfaces. | ||||
200 | |||||
201 | # Automatically enables "strict", "warnings", "utf8" and Perl 5.16 features | ||||
202 | use Mojo::Base -strict; | ||||
203 | use Mojo::Base -base; | ||||
204 | use Mojo::Base 'SomeBaseClass'; | ||||
205 | use Mojo::Base -role; | ||||
206 | |||||
207 | All four forms save a lot of typing. Note that role support depends on L<Role::Tiny> (2.000001+). | ||||
208 | |||||
209 | # use Mojo::Base -strict; | ||||
210 | use strict; | ||||
211 | use warnings; | ||||
212 | use utf8; | ||||
213 | use feature ':5.16'; | ||||
214 | use mro; | ||||
215 | |||||
216 | # use Mojo::Base -base; | ||||
217 | use strict; | ||||
218 | use warnings; | ||||
219 | use utf8; | ||||
220 | use feature ':5.16'; | ||||
221 | use mro; | ||||
222 | push @ISA, 'Mojo::Base'; | ||||
223 | sub has { Mojo::Base::attr(__PACKAGE__, @_) } | ||||
224 | |||||
225 | # use Mojo::Base 'SomeBaseClass'; | ||||
226 | use strict; | ||||
227 | use warnings; | ||||
228 | use utf8; | ||||
229 | use feature ':5.16'; | ||||
230 | use mro; | ||||
231 | require SomeBaseClass; | ||||
232 | push @ISA, 'SomeBaseClass'; | ||||
233 | sub has { Mojo::Base::attr(__PACKAGE__, @_) } | ||||
234 | |||||
235 | # use Mojo::Base -role; | ||||
236 | use strict; | ||||
237 | use warnings; | ||||
238 | use utf8; | ||||
239 | use feature ':5.16'; | ||||
240 | use mro; | ||||
241 | use Role::Tiny; | ||||
242 | sub has { Mojo::Base::attr(__PACKAGE__, @_) } | ||||
243 | |||||
244 | On Perl 5.20+ you can also use the C<-signatures> flag with all four forms and enable support for L<subroutine | ||||
245 | signatures|perlsub/"Signatures">. | ||||
246 | |||||
247 | # Also enable signatures | ||||
248 | use Mojo::Base -strict, -signatures; | ||||
249 | use Mojo::Base -base, -signatures; | ||||
250 | use Mojo::Base 'SomeBaseClass', -signatures; | ||||
251 | use Mojo::Base -role, -signatures; | ||||
252 | |||||
253 | If you have L<Future::AsyncAwait> 0.52+ installed you can also use the C<-async_await> flag to activate the C<async> | ||||
254 | and C<await> keywords to deal much more efficiently with promises. Note that this feature is B<EXPERIMENTAL> and might | ||||
255 | change without warning! | ||||
256 | |||||
257 | # Also enable async/await | ||||
258 | use Mojo::Base -strict, -async_await; | ||||
259 | use Mojo::Base -base, -signatures, -async_await; | ||||
260 | |||||
261 | This will also disable experimental warnings on versions of Perl where this feature was still experimental. | ||||
262 | |||||
263 | =head1 FLUENT INTERFACES | ||||
264 | |||||
265 | Fluent interfaces are a way to design object-oriented APIs around method chaining to create domain-specific languages, | ||||
266 | with the goal of making the readability of the source code close to written prose. | ||||
267 | |||||
268 | package Duck; | ||||
269 | use Mojo::Base -base, -signatures; | ||||
270 | |||||
271 | has 'name'; | ||||
272 | |||||
273 | sub quack ($self) { | ||||
274 | my $name = $self->name; | ||||
275 | say "$name: Quack!" | ||||
276 | } | ||||
277 | |||||
278 | L<Mojo::Base> will help you with this by having all attribute accessors created with L</"has"> (or L</"attr">) return | ||||
279 | their invocant (C<$self>) whenever they are used to assign a new attribute value. | ||||
280 | |||||
281 | Duck->new->name('Donald')->quack; | ||||
282 | |||||
283 | In this case the C<name> attribute accessor is called on the object created by C<Duck-E<gt>new>. It assigns a new | ||||
284 | attribute value and then returns the C<Duck> object, so the C<quack> method can be called on it afterwards. These | ||||
285 | method chains can continue until one of the methods called does not return the C<Duck> object. | ||||
286 | |||||
287 | =head1 FUNCTIONS | ||||
288 | |||||
289 | L<Mojo::Base> implements the following functions, which can be imported with the C<-base> flag or by setting a base | ||||
290 | class. | ||||
291 | |||||
292 | =head2 has | ||||
293 | |||||
294 | has 'name'; | ||||
295 | has ['name1', 'name2', 'name3']; | ||||
296 | has name => 'foo'; | ||||
297 | has name => sub {...}; | ||||
298 | has ['name1', 'name2', 'name3'] => 'foo'; | ||||
299 | has ['name1', 'name2', 'name3'] => sub {...}; | ||||
300 | has name => sub {...}, weak => 1; | ||||
301 | has name => undef, weak => 1; | ||||
302 | has ['name1', 'name2', 'name3'] => sub {...}, weak => 1; | ||||
303 | |||||
304 | Create attributes for hash-based objects, just like the L</"attr"> method. | ||||
305 | |||||
306 | =head1 METHODS | ||||
307 | |||||
308 | L<Mojo::Base> implements the following methods. | ||||
309 | |||||
310 | =head2 attr | ||||
311 | |||||
312 | $object->attr('name'); | ||||
313 | SubClass->attr('name'); | ||||
314 | SubClass->attr(['name1', 'name2', 'name3']); | ||||
315 | SubClass->attr(name => 'foo'); | ||||
316 | SubClass->attr(name => sub {...}); | ||||
317 | SubClass->attr(['name1', 'name2', 'name3'] => 'foo'); | ||||
318 | SubClass->attr(['name1', 'name2', 'name3'] => sub {...}); | ||||
319 | SubClass->attr(name => sub {...}, weak => 1); | ||||
320 | SubClass->attr(name => undef, weak => 1); | ||||
321 | SubClass->attr(['name1', 'name2', 'name3'] => sub {...}, weak => 1); | ||||
322 | |||||
323 | Create attribute accessors for hash-based objects, an array reference can be used to create more than one at a time. | ||||
324 | Pass an optional second argument to set a default value, it should be a constant or a callback. The callback will be | ||||
325 | executed at accessor read time if there's no set value, and gets passed the current instance of the object as first | ||||
326 | argument. Accessors can be chained, that means they return their invocant when they are called with an argument. | ||||
327 | |||||
328 | These options are currently available: | ||||
329 | |||||
330 | =over 2 | ||||
331 | |||||
332 | =item weak | ||||
333 | |||||
334 | weak => $bool | ||||
335 | |||||
336 | Weaken attribute reference to avoid L<circular references|perlref/"Circular-References"> and memory leaks. | ||||
337 | |||||
338 | =back | ||||
339 | |||||
340 | =head2 new | ||||
341 | |||||
342 | my $object = SubClass->new; | ||||
343 | my $object = SubClass->new(name => 'value'); | ||||
344 | my $object = SubClass->new({name => 'value'}); | ||||
345 | |||||
346 | This base class provides a basic constructor for hash-based objects. You can pass it either a hash or a hash reference | ||||
347 | with attribute values. | ||||
348 | |||||
349 | =head2 tap | ||||
350 | |||||
351 | $object = $object->tap(sub {...}); | ||||
352 | $object = $object->tap('some_method'); | ||||
353 | $object = $object->tap('some_method', @args); | ||||
354 | |||||
355 | Tap into a method chain to perform operations on an object within the chain (also known as a K combinator or Kestrel). | ||||
356 | The object will be the first argument passed to the callback, and is also available as C<$_>. The callback's return | ||||
357 | value will be ignored; instead, the object (the callback's first argument) will be the return value. In this way, | ||||
358 | arbitrary code can be used within (i.e., spliced or tapped into) a chained set of object method calls. | ||||
359 | |||||
360 | # Longer version | ||||
361 | $object = $object->tap(sub { $_->some_method(@args) }); | ||||
362 | |||||
363 | # Inject side effects into a method chain | ||||
364 | $object->foo('A')->tap(sub { say $_->foo })->foo('B'); | ||||
365 | |||||
366 | =head2 with_roles | ||||
367 | |||||
368 | my $new_class = SubClass->with_roles('SubClass::Role::One'); | ||||
369 | my $new_class = SubClass->with_roles('+One', '+Two'); | ||||
370 | $object = $object->with_roles('+One', '+Two'); | ||||
371 | |||||
372 | Create a new class with one or more L<Role::Tiny> roles. If called on a class returns the new class, or if called on an | ||||
373 | object reblesses the object into the new class. For roles following the naming scheme C<MyClass::Role::RoleName> you | ||||
374 | can use the shorthand C<+RoleName>. Note that role support depends on L<Role::Tiny> (2.000001+). | ||||
375 | |||||
376 | # Create a new class with the role "SubClass::Role::Foo" and instantiate it | ||||
377 | my $new_class = SubClass->with_roles('+Foo'); | ||||
378 | my $object = $new_class->new; | ||||
379 | |||||
380 | =head1 SEE ALSO | ||||
381 | |||||
382 | L<Mojolicious>, L<Mojolicious::Guides>, L<https://mojolicious.org>. | ||||
383 | |||||
384 | =cut | ||||
sub Mojo::Base::CORE:match; # opcode | |||||
# spent 877µs within Mojo::JSON::Pointer::CORE:match which was called 211 times, avg 4µs/call:
# 211 times (877µs+0s) by Mojo::JSON::Pointer::_pointer at line 21 of Mojo/JSON/Pointer.pm, avg 4µs/call | |||||
# spent 79.1ms within Mojo::JSON::Pointer::CORE:subst which was called 146708 times, avg 539ns/call:
# 49431 times (18.1ms+0s) by Mojo::JSON::Pointer::_pointer at line 17 of Mojo/JSON/Pointer.pm, avg 365ns/call
# 49431 times (11.3ms+0s) by Mojo::JSON::Pointer::_pointer at line 18 of Mojo/JSON/Pointer.pm, avg 229ns/call
# 47846 times (49.7ms+0s) by Mojo::JSON::Pointer::_pointer at line 15 of Mojo/JSON/Pointer.pm, avg 1µs/call |