← Index
NYTProf Performance Profile   « line view »
For ../prof.pl
  Run on Wed Dec 14 15:33:55 2022
Reported on Wed Dec 14 15:40:02 2022

Filename/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Mojo/Base.pm
StatementsExecuted 8454515 statements in 8.25s
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
1651801441.40s1.40sMojo::Base::::new Mojo::Base::new
126827026111.02s1.02sMojo::URL::::fragment Mojo::URL::fragment
59969541536ms536msMojo::URL::::scheme Mojo::URL::scheme
49664421465ms465msMojo::Path::::charset Mojo::Path::charset
51547041392ms392msMojo::URL::::host Mojo::URL::host
32958311385ms385msMojo::Parameters::::charset Mojo::Parameters::charset
37804021228ms228msMojo::URL::::port Mojo::URL::port
1467083179.1ms79.1msMojo::JSON::Pointer::::CORE:substMojo::JSON::Pointer::CORE:subst (opcode)
339631165.8ms65.8msMojo::URL::::base Mojo::URL::base
702522160.3ms60.3msMojo::URL::::userinfo Mojo::URL::userinfo
1114.17ms4.46msMojo::Base::::BEGIN@17 Mojo::Base::BEGIN@17
21111877µs877µsMojo::JSON::Pointer::::CORE:matchMojo::JSON::Pointer::CORE:match (opcode)
111752µs833µsMojo::Base::::BEGIN@5 Mojo::Base::BEGIN@5
12128426µs1.43msMojo::Base::::import Mojo::Base::import
511137µs296µsMojo::Base::::attr Mojo::Base::attr
111108µs140µsMojo::Base::::BEGIN@20 Mojo::Base::BEGIN@20
152147µs47µsMojo::Base::::CORE:match Mojo::Base::CORE:match (opcode)
11126µs31µsMojo::Base::::BEGIN@3 Mojo::Base::BEGIN@3
22112µs156µsMojo::URL::::has Mojo::URL::has
11111µs18µsMojo::Base::::BEGIN@133 Mojo::Base::BEGIN@133
11110µs17µsMojo::Base::::BEGIN@45 Mojo::Base::BEGIN@45
11110µs12µsMojo::Base::::BEGIN@7 Mojo::Base::BEGIN@7
1119µs103µsMojo::Base::::BEGIN@6 Mojo::Base::BEGIN@6
1118µs67µsMojo::Parameters::::has Mojo::Parameters::has
1116µs44µsMojo::Base::::BEGIN@4 Mojo::Base::BEGIN@4
1116µs66µsMojo::Path::::has Mojo::Path::has
1115µs38µsMojo::JSON::Pointer::::hasMojo::JSON::Pointer::has
1113µs3µsMojo::Base::::BEGIN@10 Mojo::Base::BEGIN@10
1112µs2µsMojo::Base::::BEGIN@11 Mojo::Base::BEGIN@11
0000s0sMojo::Base::::DESTROY Mojo::Base::DESTROY
0000s0sMojo::Base::::__ANON__[:113] Mojo::Base::__ANON__[:113]
0000s0sMojo::Base::::__ANON__[:136] Mojo::Base::__ANON__[:136]
0000s0sMojo::Base::::__ANON__[:43] Mojo::Base::__ANON__[:43]
0000s0sMojo::Base::::__ANON__[:66] Mojo::Base::__ANON__[:66]
0000s0sMojo::Base::::__ANON__[:73] Mojo::Base::__ANON__[:73]
0000s0sMojo::Base::::__ANON__[:81] Mojo::Base::__ANON__[:81]
0000s0sMojo::Base::::__ANON__[:88] Mojo::Base::__ANON__[:88]
0000s0sMojo::Base::::__ANON__[:91] Mojo::Base::__ANON__[:91]
0000s0sMojo::Base::::tap Mojo::Base::tap
0000s0sMojo::Base::::with_roles Mojo::Base::with_roles
0000s0sMojo::JSON::Pointer::::dataMojo::JSON::Pointer::data
0000s0sMojo::Util::_Guard::::has Mojo::Util::_Guard::has
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1package Mojo::Base;
2
3235µs236µ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
use strict;
# spent 31µs making 1 call to Mojo::Base::BEGIN@3 # spent 5µs making 1 call to strict::import
4220µs282µ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
use warnings;
# spent 44µs making 1 call to Mojo::Base::BEGIN@4 # spent 38µs making 1 call to warnings::import
52983µs2835µ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
use utf8;
# spent 833µs making 1 call to Mojo::Base::BEGIN@5 # spent 2µs making 1 call to utf8::import
6231µs2197µ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
use feature ':5.16';
# spent 103µs making 1 call to Mojo::Base::BEGIN@6 # spent 94µs making 1 call to feature::import
7223µs214µ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
use mro;
# 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!
10215µs13µs
# spent 3µs within Mojo::Base::BEGIN@10 which was called: # once (3µs+0s) by Mojo::URL::BEGIN@2 at line 10
use Carp ();
# spent 3µs making 1 call to Mojo::Base::BEGIN@10
11272µs12µs
# spent 2µs within Mojo::Base::BEGIN@11 which was called: # once (2µs+0s) by Mojo::URL::BEGIN@2 at line 11
use Scalar::Util ();
# spent 2µs making 1 call to Mojo::Base::BEGIN@11
12
13# Defer to runtime so Mojo::Util can use "-strict"
141696µsrequire Mojo::Util;
15
16# Role support requires Role::Tiny 2.000001+
175972µs34.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
use constant ROLES => !!(eval { require Role::Tiny; Role::Tiny->VERSION('2.000001'); 1 });
# 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
use constant ASYNC => $ENV{MOJO_NO_ASYNC}
21 ? 0
223333µs2172µ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
25sub 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
sub attr {
2857µs my ($self, $attrs, $value, %kv) = @_;
2956µs return unless (my $class = ref $self || $self) && $attrs;
30
3154µs Carp::croak 'Default has to be a code reference or constant value' if ref $value && ref $value ne 'CODE';
3255µs Carp::croak 'Unsupported attribute option' if grep { $_ ne 'weak' } keys %kv;
33
34 # Weaken
3554µ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);
4521.11ms224µ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
no strict 'refs';
# 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
51528µs for my $attr (@{ref $attrs eq 'ARRAY' ? $attrs : [$attrs]}) {
52962µs933µ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
5591µs my $sub;
5698µ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
$sub = sub {
783396314.3ms return exists $_[0]{$attr} ? $_[0]{$attr} : ($_[0]{$attr} = $value->($_[0])) if @_ == 1;
793396325.4ms $_[0]{$attr} = $_[1];
803396344.2ms $_[0];
8113µ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
$sub = sub {
858262271.42s return exists $_[0]{$attr} ? $_[0]{$attr} : ($_[0]{$attr} = $value) if @_ == 1;
86 $_[0]{$attr} = $_[1];
87 $_[0];
88213µs };
89 }
90 else {
9142226274.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
$sub = sub { return $_[0]{$attr} if @_ == 1; $_[0]{$attr} = $_[1]; $_[0] };
92 }
93915µs9126µ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
sub import {
981233µs my ($class, $caller) = (shift, caller);
991233µs return unless my @flags = @_;
100
101 # Mojo modules are strict!
1026176µs18344µ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
103618µs6560µs feature->import(':5.16');
# spent 560µs making 6 calls to feature::import, avg 93µs/call
104
105644µs while (my $flag = shift @flags) {
106
107 # Base
1081152µs614µ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 !~ /^-/) {
1332873µs225µ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
no strict 'refs';
# spent 18µs making 1 call to Mojo::Base::BEGIN@133 # spent 7µs making 1 call to strict::unimport
134535µs511µ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
135531µs push @{"${caller}::ISA"}, $flag;
1361046µs10375µ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
Mojo::Util::monkey_patch($caller, 'has', sub { attr($caller, @_) });
# 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
sub new {
1441651801205ms my $class = shift;
14516518012.35s bless @_ ? @_ > 1 ? {@_} : {%{$_[0]}} : {}, ref $class || $class;
146}
147
148sub tap {
149 my ($self, $cb) = (shift, shift);
150 $_->$cb(@_) for $self;
151 return $self;
152}
153
154sub 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
16513µs1;
166
167=encoding utf8
168
169=head1 NAME
170
171Mojo::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
199L<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
207All 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
244On Perl 5.20+ you can also use the C<-signatures> flag with all four forms and enable support for L<subroutine
245signatures|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
253If you have L<Future::AsyncAwait> 0.52+ installed you can also use the C<-async_await> flag to activate the C<async>
254and C<await> keywords to deal much more efficiently with promises. Note that this feature is B<EXPERIMENTAL> and might
255change without warning!
256
257 # Also enable async/await
258 use Mojo::Base -strict, -async_await;
259 use Mojo::Base -base, -signatures, -async_await;
260
261This will also disable experimental warnings on versions of Perl where this feature was still experimental.
262
263=head1 FLUENT INTERFACES
264
265Fluent interfaces are a way to design object-oriented APIs around method chaining to create domain-specific languages,
266with 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
278L<Mojo::Base> will help you with this by having all attribute accessors created with L</"has"> (or L</"attr">) return
279their invocant (C<$self>) whenever they are used to assign a new attribute value.
280
281 Duck->new->name('Donald')->quack;
282
283In this case the C<name> attribute accessor is called on the object created by C<Duck-E<gt>new>. It assigns a new
284attribute value and then returns the C<Duck> object, so the C<quack> method can be called on it afterwards. These
285method chains can continue until one of the methods called does not return the C<Duck> object.
286
287=head1 FUNCTIONS
288
289L<Mojo::Base> implements the following functions, which can be imported with the C<-base> flag or by setting a base
290class.
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
304Create attributes for hash-based objects, just like the L</"attr"> method.
305
306=head1 METHODS
307
308L<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
323Create attribute accessors for hash-based objects, an array reference can be used to create more than one at a time.
324Pass an optional second argument to set a default value, it should be a constant or a callback. The callback will be
325executed at accessor read time if there's no set value, and gets passed the current instance of the object as first
326argument. Accessors can be chained, that means they return their invocant when they are called with an argument.
327
328These options are currently available:
329
330=over 2
331
332=item weak
333
334 weak => $bool
335
336Weaken 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
346This base class provides a basic constructor for hash-based objects. You can pass it either a hash or a hash reference
347with 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
355Tap into a method chain to perform operations on an object within the chain (also known as a K combinator or Kestrel).
356The object will be the first argument passed to the callback, and is also available as C<$_>. The callback's return
357value will be ignored; instead, the object (the callback's first argument) will be the return value. In this way,
358arbitrary 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
372Create 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
373object reblesses the object into the new class. For roles following the naming scheme C<MyClass::Role::RoleName> you
374can 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
382L<Mojolicious>, L<Mojolicious::Guides>, L<https://mojolicious.org>.
383
384=cut
 
# spent 47µs within Mojo::Base::CORE:match which was called 15 times, avg 3µs/call: # 9 times (33µs+0s) by Mojo::Base::attr at line 52, avg 4µs/call # 6 times (14µs+0s) by Mojo::Base::import at line 108, avg 2µs/call
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
sub Mojo::JSON::Pointer::CORE:match; # opcode
# 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
sub Mojo::JSON::Pointer::CORE:subst; # opcode