← Index
NYTProf Performance Profile   « line view »
For ../prof.pl
  Run on Wed Dec 14 16:10:05 2022
Reported on Wed Dec 14 16:12:57 2022

Filename/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Mojo/Base.pm
StatementsExecuted 6750365 statements in 7.68s
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
1303813441.35s1.35sMojo::Base::::new Mojo::Base::new
8427342511783ms783msMojo::URL::::fragment Mojo::URL::fragment
45377941481ms481msMojo::URL::::scheme Mojo::URL::scheme
42031921466ms466msMojo::Path::::charset Mojo::Path::charset
44174241370ms370msMojo::URL::::host Mojo::URL::host
25601211350ms350msMojo::Parameters::::charset Mojo::Parameters::charset
30584621192ms192msMojo::URL::::port Mojo::URL::port
339631185.9ms85.9msMojo::URL::::base Mojo::URL::base
687182153.3ms53.3msMojo::URL::::userinfo Mojo::URL::userinfo
1114.39ms4.72msMojo::Base::::BEGIN@17 Mojo::Base::BEGIN@17
111370µs439µsMojo::Base::::BEGIN@5 Mojo::Base::BEGIN@5
12128308µs1.11msMojo::Base::::import Mojo::Base::import
511131µs254µsMojo::Base::::attr Mojo::Base::attr
111109µs144µsMojo::Base::::BEGIN@20 Mojo::Base::BEGIN@20
152137µs37µsMojo::Base::::CORE:match Mojo::Base::CORE:match (opcode)
11128µs33µsMojo::Base::::BEGIN@3 Mojo::Base::BEGIN@3
11110µs18µsMojo::Base::::BEGIN@133 Mojo::Base::BEGIN@133
1118µs17µsMojo::Base::::BEGIN@45 Mojo::Base::BEGIN@45
1118µs10µsMojo::Base::::BEGIN@7 Mojo::Base::BEGIN@7
2218µs87µsMojo::URL::::has Mojo::URL::has
1117µs105µsMojo::Base::::BEGIN@6 Mojo::Base::BEGIN@6
1117µs67µsMojo::Path::::has Mojo::Path::has
1116µs61µsMojo::Parameters::::has Mojo::Parameters::has
1115µs48µsMojo::Base::::BEGIN@4 Mojo::Base::BEGIN@4
1115µs65µ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
3234µs238µs
# spent 33µs (28+5) within Mojo::Base::BEGIN@3 which was called: # once (28µs+5µs) by Mojo::URL::BEGIN@2 at line 3
use strict;
# spent 33µs making 1 call to Mojo::Base::BEGIN@3 # spent 5µs making 1 call to strict::import
4219µs291µs
# spent 48µs (5+43) within Mojo::Base::BEGIN@4 which was called: # once (5µs+43µs) by Mojo::URL::BEGIN@2 at line 4
use warnings;
# spent 48µs making 1 call to Mojo::Base::BEGIN@4 # spent 43µs making 1 call to warnings::import
52233µs2442µs
# spent 439µs (370+69) within Mojo::Base::BEGIN@5 which was called: # once (370µs+69µs) by Mojo::URL::BEGIN@2 at line 5
use utf8;
# spent 439µs making 1 call to Mojo::Base::BEGIN@5 # spent 3µs making 1 call to utf8::import
6223µs2203µs
# spent 105µs (7+98) within Mojo::Base::BEGIN@6 which was called: # once (7µs+98µs) by Mojo::URL::BEGIN@2 at line 6
use feature ':5.16';
# spent 105µs making 1 call to Mojo::Base::BEGIN@6 # spent 98µs making 1 call to feature::import
7225µs212µs
# spent 10µs (8+2) within Mojo::Base::BEGIN@7 which was called: # once (8µs+2µs) by Mojo::URL::BEGIN@2 at line 7
use mro;
# spent 10µ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!
10216µ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
11263µ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"
141551µsrequire Mojo::Util;
15
16# Role support requires Role::Tiny 2.000001+
175526µs34.79ms
# spent 4.72ms (4.39+339µs) within Mojo::Base::BEGIN@17 which was called: # once (4.39ms+339µs) by Mojo::URL::BEGIN@2 at line 17
use constant ROLES => !!(eval { require Role::Tiny; Role::Tiny->VERSION('2.000001'); 1 });
# spent 4.72ms making 1 call to Mojo::Base::BEGIN@17 # spent 59µs making 1 call to constant::import # spent 10µs making 1 call to UNIVERSAL::VERSION
18
19# async/await support requires Future::AsyncAwait 0.52+
20
# spent 144µs (109+35) within Mojo::Base::BEGIN@20 which was called: # once (109µs+35µs) by Mojo::URL::BEGIN@2 at line 22
use constant ASYNC => $ENV{MOJO_NO_ASYNC}
21 ? 0
223332µs2179µs : !!(eval { require Future::AsyncAwait; Future::AsyncAwait->VERSION('0.52'); 1 });
# spent 144µs making 1 call to Mojo::Base::BEGIN@20 # spent 35µs making 1 call to constant::import
23
24# Protect subclasses using AUTOLOAD
25sub DESTROY { }
26
27
# spent 254µs (131+123) within Mojo::Base::attr which was called 5 times, avg 51µs/call: # 5 times (131µs+123µs) by Mojo::JSON::Pointer::has or Mojo::Parameters::has or Mojo::Path::has or Mojo::URL::has at line 136, avg 51µs/call
sub attr {
2857µs my ($self, $attrs, $value, %kv) = @_;
2953µs return unless (my $class = ref $self || $self) && $attrs;
30
3153µs Carp::croak 'Default has to be a code reference or constant value' if ref $value && ref $value ne 'CODE';
3254µs Carp::croak 'Unsupported attribute option' if grep { $_ ne 'weak' } keys %kv;
33
34 # Weaken
3553µ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);
452856µs226µs
# spent 17µs (8+9) within Mojo::Base::BEGIN@45 which was called: # once (8µs+9µs) by Mojo::URL::BEGIN@2 at line 45
no strict 'refs';
# spent 17µs making 1 call to Mojo::Base::BEGIN@45 # spent 9µ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
51523µs for my $attr (@{ref $attrs eq 'ARRAY' ? $attrs : [$attrs]}) {
52951µs931µs Carp::croak qq{Attribute "$attr" invalid} unless $attr =~ /^[a-zA-Z_]\w*$/;
# spent 31µs making 9 calls to Mojo::Base::CORE:match, avg 3µs/call
53
54 # Very performance-sensitive code with lots of micro-optimizations
5591µs my $sub;
5699µ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 85.9ms within Mojo::URL::base which was called 33963 times, avg 3µs/call: # 33963 times (85.9ms+0s) by Mojo::URL::to_abs at line 128 of Mojo/URL.pm, avg 3µs/call
$sub = sub {
783396315.7ms return exists $_[0]{$attr} ? $_[0]{$attr} : ($_[0]{$attr} = $value->($_[0])) if @_ == 1;
793396335.1ms $_[0]{$attr} = $_[1];
803396360.5ms $_[0];
8112µs };
82 }
83 elsif (defined $value) {
84
# spent 350ms within Mojo::Parameters::charset which was called 256012 times, avg 1µs/call: # 256012 times (350ms+0s) by Mojo::Parameters::to_string at line 150 of Mojo/Parameters.pm, avg 1µs/call # spent 466ms within Mojo::Path::charset which was called 420319 times, avg 1µs/call: # 294457 times (298ms+0s) by Mojo::Path::to_string at line 84 of Mojo/Path.pm, avg 1µs/call # 125862 times (168ms+0s) by Mojo::Path::_parse at line 106 of Mojo/Path.pm, avg 1µs/call
$sub = sub {
856763311.38s return exists $_[0]{$attr} ? $_[0]{$attr} : ($_[0]{$attr} = $value) if @_ == 1;
86 $_[0]{$attr} = $_[1];
87 $_[0];
8827µs };
89 }
90 else {
9133643493.72s
# spent 192ms within Mojo::URL::port which was called 305846 times, avg 627ns/call: # 237920 times (140ms+0s) by Mojo::URL::host_port at line 30 of Mojo/URL.pm, avg 588ns/call # 67926 times (52.0ms+0s) by Mojo::URL::to_abs at line 132 of Mojo/URL.pm, avg 765ns/call # spent 783ms within Mojo::URL::fragment which was called 842734 times, avg 929ns/call: # 240151 times (211ms+0s) by Mojo::URL::_string at line 181 of Mojo/URL.pm, avg 878ns/call # 126625 times (123ms+0s) by JSON::Schema::Modern::Utilities::canonical_uri at line 193 of JSON/Schema/Modern/Utilities.pm, avg 970ns/call # 126625 times (118ms+0s) by JSON::Schema::Modern::Utilities::canonical_uri at line 195 of JSON/Schema/Modern/Utilities.pm, avg 929ns/call # 89213 times (59.7ms+0s) by JSON::Schema::Modern::_fetch_from_uri at line 865 of JSON/Schema/Modern.pm, avg 669ns/call # 64986 times (41.7ms+0s) by JSON::Schema::Modern::_fetch_from_uri at line 870 of JSON/Schema/Modern.pm, avg 641ns/call # 57141 times (65.5ms+0s) by Mojo::URL::parse at line 60 of Mojo/URL.pm, avg 1µs/call # 46881 times (39.6ms+0s) by JSON::Schema::Modern::_fetch_from_uri at line 853 of JSON/Schema/Modern.pm, avg 845ns/call # 39123 times (74.0ms+0s) by JSON::Schema::Modern::_fetch_from_uri at line 869 of JSON/Schema/Modern.pm, avg 2µs/call # 39123 times (40.9ms+0s) by JSON::Schema::Modern::_fetch_from_uri at line 856 of JSON/Schema/Modern.pm, avg 1µs/call # 5172 times (4.22ms+0s) by JSON::Schema::Modern::Vocabulary::Core::_eval_keyword_dynamicRef at line 237 of JSON/Schema/Modern/Vocabulary/Core.pm, avg 816ns/call # 4217 times (2.84ms+0s) by JSON::Schema::Modern::Utilities::E at line 218 of JSON/Schema/Modern/Utilities.pm, avg 675ns/call # 2586 times (2.49ms+0s) by JSON::Schema::Modern::Vocabulary::Core::_eval_keyword_dynamicRef at line 243 of JSON/Schema/Modern/Vocabulary/Core.pm, avg 962ns/call # 758 times (420µs+0s) by JSON::Schema::Modern::traverse at line 259 of JSON/Schema/Modern.pm, avg 554ns/call # 36 times (19µ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 528ns/call # 18 times (19µs+0s) by JSON::Schema::Modern::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/JSON/Schema/Modern.pm:676] at line 667 of JSON/Schema/Modern.pm, avg 1µs/call # 15 times (19µs+0s) by JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_anchor at line 171 of JSON/Schema/Modern/Vocabulary/Core.pm, avg 1µs/call # 14 times (10µs+0s) by JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_id at line 66 of JSON/Schema/Modern/Vocabulary/Core.pm, avg 714ns/call # 14 times (9µs+0s) by JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_id at line 62 of JSON/Schema/Modern/Vocabulary/Core.pm, avg 643ns/call # 10 times (7µs+0s) by JSON::Schema::Modern::Document::_set_canonical_uri at line 39 of (eval 268)[Sub/Quote.pm:3], avg 700ns/call # 9 times (10µs+0s) by JSON::Schema::Modern::add_schema at line 143 of JSON/Schema/Modern.pm, avg 1µs/call # 8 times (40µs+0s) by JSON::Schema::Modern::Document::canonical_uri at line 44 of (eval 267)[Sub/Quote.pm:3], avg 5µs/call # 6 times (4µs+0s) by JSON::Schema::Modern::Document::new at line 74 of (eval 428)[Sub/Quote.pm:3], avg 667ns/call # once (2µs+0s) by JSON::Schema::Modern::Document::OpenAPI::new at line 77 of (eval 421)[Sub/Quote.pm:3] # once (2µ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 425)[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Sub/Quote.pm:3]:16] at line 16 of (eval 425)[Sub/Quote.pm:3] # spent 481ms within Mojo::URL::scheme which was called 453779 times, avg 1µs/call: # 240151 times (228ms+0s) by Mojo::URL::protocol at line 96 of Mojo/URL.pm, avg 950ns/call # 99702 times (152ms+0s) by Mojo::URL::parse at line 57 of Mojo/URL.pm, avg 2µs/call # 67926 times (63.3ms+0s) by Mojo::URL::to_abs at line 128 of Mojo/URL.pm, avg 932ns/call # 46000 times (37.6ms+0s) by Mojo::URL::is_abs at line 48 of Mojo/URL.pm, avg 818ns/call # spent 53.3ms within Mojo::URL::userinfo which was called 68718 times, avg 775ns/call: # 67926 times (52.8ms+0s) by Mojo::URL::to_abs at line 132 of Mojo/URL.pm, avg 777ns/call # 792 times (500µs+0s) by Mojo::URL::_string at line 171 of Mojo/URL.pm, avg 631ns/call # spent 370ms within Mojo::URL::host which was called 441742 times, avg 838ns/call: # 240151 times (182ms+0s) by Mojo::URL::ihost at line 41 of Mojo/URL.pm, avg 759ns/call # 99702 times (99.7ms+0s) by Mojo::URL::host_port at line 26 of Mojo/URL.pm, avg 1000ns/call # 67926 times (67.6ms+0s) by Mojo::URL::to_abs at line 132 of Mojo/URL.pm, avg 996ns/call # 33963 times (20.5ms+0s) by Mojo::URL::to_abs at line 131 of Mojo/URL.pm, avg 603ns/call
$sub = sub { return $_[0]{$attr} if @_ == 1; $_[0]{$attr} = $_[1]; $_[0] };
92 }
9398µs992µs Mojo::Util::monkey_patch($class, $attr, $sub);
# spent 92µs making 9 calls to Mojo::Util::monkey_patch, avg 10µs/call
94 }
95}
96
97
# spent 1.11ms (308µs+801µs) within Mojo::Base::import which was called 12 times, avg 92µs/call: # once (80µs+152µs) by Mojo::URL::BEGIN@2 at line 2 of Mojo/URL.pm # once (54µs+134µs) by Mojo::Util::_Guard::BEGIN@538 at line 538 of Mojo/Util.pm # once (40µs+134µs) by Mojo::Parameters::BEGIN@2 at line 2 of Mojo/Parameters.pm # once (35µs+136µs) by Mojo::Util::BEGIN@2 at line 2 of Mojo/Util.pm # once (36µs+132µs) by Mojo::Path::BEGIN@2 at line 2 of Mojo/Path.pm # once (43µs+113µs) by Mojo::JSON::Pointer::BEGIN@2 at line 2 of Mojo/JSON/Pointer.pm # once (5µs+0s) by JSON::Schema::Modern::Document::BEGIN@17 at line 17 of JSON/Schema/Modern/Document.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::BEGIN@35 at line 35 of JSON/Schema/Modern.pm # once (3µs+0s) by Mojo::URL::BEGIN@6 at line 6 of Mojo/URL.pm # once (2µs+0s) by JSON::Schema::Modern::BEGIN@23 at line 23 of JSON/Schema/Modern.pm # once (2µs+0s) by OpenAPI::Modern::BEGIN@28 at line 28 of OpenAPI/Modern.pm
sub import {
981227µs my ($class, $caller) = (shift, caller);
991259µs return unless my @flags = @_;
100
101 # Mojo modules are strict!
102688µs18247µs $_->import for qw(strict warnings utf8);
# spent 221µs making 6 calls to warnings::import, avg 37µs/call # spent 16µs making 6 calls to strict::import, avg 3µs/call # spent 10µs making 6 calls to utf8::import, avg 2µs/call
103618µs6466µs feature->import(':5.16');
# spent 466µs making 6 calls to feature::import, avg 78µs/call
104
105634µs while (my $flag = shift @flags) {
106
107 # Base
1081131µs66µs if ($flag eq '-base') { push @flags, $class }
# spent 6µs making 6 calls to Mojo::Base::CORE:match, avg 1µ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 !~ /^-/) {
1332855µs226µs
# spent 18µs (10+8) within Mojo::Base::BEGIN@133 which was called: # once (10µs+8µs) by Mojo::URL::BEGIN@2 at line 133
no strict 'refs';
# spent 18µs making 1 call to Mojo::Base::BEGIN@133 # spent 8µs making 1 call to strict::unimport
134536µs512µs require(Mojo::Util::class_to_path($flag)) unless $flag->can('new');
# spent 12µs making 5 calls to UNIVERSAL::can, avg 2µs/call
135530µs push @{"${caller}::ISA"}, $flag;
1361043µs10324µs
# spent 87µs (8+79) within Mojo::URL::has which was called 2 times, avg 44µs/call: # once (7µs+37µs) by JSON::Schema::Modern::BEGIN@23 at line 9 of Mojo/URL.pm # once (1µs+42µs) by JSON::Schema::Modern::BEGIN@23 at line 10 of Mojo/URL.pm # spent 61µs (6+55) within Mojo::Parameters::has which was called: # once (6µs+55µs) by Mojo::URL::BEGIN@5 at line 7 of Mojo/Parameters.pm # spent 65µs (5+60) within Mojo::JSON::Pointer::has which was called: # once (5µs+60µs) by Moo::_Utils::_require at line 4 of Mojo/JSON/Pointer.pm # spent 67µs (7+60) within Mojo::Path::has which was called: # once (7µ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 254µs making 5 calls to Mojo::Base::attr, avg 51µs/call # spent 70µs making 5 calls to Mojo::Util::monkey_patch, avg 14µs/call
137 }
138
139 elsif ($flag ne '-strict') { Carp::croak "Unsupported flag: $flag" }
140 }
141}
142
143
# spent 1.35s within Mojo::Base::new which was called 1303813 times, avg 1µs/call: # 541370 times (510ms+0s) by Mojo::Path::new at line 53 of Mojo/Path.pm, avg 941ns/call # 452446 times (546ms+0s) by Mojo::URL::new at line 50 of Mojo/URL.pm, avg 1µs/call # 309982 times (300ms+0s) by Mojo::Parameters::new at line 63 of Mojo/Parameters.pm, avg 967ns/call # 15 times (29µs+0s) by Mojo::JSON::Pointer::new at line 9 of Mojo/JSON/Pointer.pm, avg 2µs/call
sub new {
1441303813207ms my $class = shift;
14513038132.26s 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
16514µ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 37µs within Mojo::Base::CORE:match which was called 15 times, avg 2µs/call: # 9 times (31µs+0s) by Mojo::Base::attr at line 52, avg 3µs/call # 6 times (6µs+0s) by Mojo::Base::import at line 108, avg 1µs/call
sub Mojo::Base::CORE:match; # opcode