diff options
Diffstat (limited to 'pod')
-rw-r--r-- | pod/perldiag.pod | 24 | ||||
-rw-r--r-- | pod/perlfunc.pod | 64 | ||||
-rw-r--r-- | pod/perlguts.pod | 4 | ||||
-rw-r--r-- | pod/perlvar.pod | 65 |
4 files changed, 153 insertions, 4 deletions
diff --git a/pod/perldiag.pod b/pod/perldiag.pod index fbeac66515..acd30568a9 100644 --- a/pod/perldiag.pod +++ b/pod/perldiag.pod @@ -2263,6 +2263,18 @@ the C<encoding> pragma, is no longer supported as of Perl 5.26.0. Setting it to anything other than C<undef> is a fatal error as of Perl 5.28. +=item ${^HOOK}{%s} may only be a CODE reference or undef + +(F) You attempted to assign something other than undef or a CODE ref to +C<%{^HOOK}>. Hooks may only be CODE refs. See L<perlvar/%{^HOOK}> for +details. + +=item Attempt to set unknown hook '%s' in %{^HOOK} + +(F) You attempted to assign something other than undef or a CODE ref to +C<%{^HOOK}>. Hooks may only be CODE refs. See L<perlvar/%{^HOOK}> for +details. + =item entering effective %s failed (F) While under the C<use filetest> pragma, switching the real and @@ -3961,11 +3973,17 @@ can vary from one line to the next. =item Missing or undefined argument to %s -(F) You tried to call require or do with no argument or with an undefined -value as an argument. Require expects either a package name or a -file-specification as an argument; do expects a filename. See +(F) You tried to call C<require> or C<do> with no argument or with an +undefined value as an argument. Require expects either a package name or +a file-specification as an argument; do expects a filename. See L<perlfunc/require EXPR> and L<perlfunc/do EXPR>. +=item Missing or undefined argument to %s via %{^HOOK}{require__before} + +(F) A C<%{^HOOK}{require__before}> hook rewrote the name of the file being +compiled with C<require> or C<do> with an empty string an undefined value +which is forbidden. See L<perlvar/%{^HOOK}> and L<perlfunc/require EXPR>. + =item Missing right brace on \%c{} in regex; marked by S<<-- HERE> in m/%s/ (F) Missing right brace in C<\x{...}>, C<\p{...}>, C<\P{...}>, or C<\N{...}>. diff --git a/pod/perlfunc.pod b/pod/perlfunc.pod index 90f07afbe8..5a26941e75 100644 --- a/pod/perlfunc.pod +++ b/pod/perlfunc.pod @@ -7064,7 +7064,69 @@ require executes at all. As of 5.37.7 C<@INC> values of undef will be silently ignored. -For a yet-more-powerful import facility, see +The function C<require()> is difficult to wrap properly. Many modules +consult the stack to find information about their caller, and injecting +a new stack frame by wrapping C<require()> often breaks things. +Nevertheless it can be very helpful to have the ability to perform +actions before and after a C<require>, for instance for trace utilities +like C<Devel::TraceUse> or to measure time to load and the memory +consumption of the require graph. Because of the difficulties in safely +creating a C<require()> wrapper in 5.37.10 we introduced a new mechanism. + +As of 5.37.10, prior to any other actions it performs, C<require> will +check if C<${^HOOK}{require__before}> contains a coderef, and if it does +it will be called with the filename form of the item being loaded. The hook +may modify C<$_[0]> to load a different filename, or it may throw a fatal +exception to cause the require to fail, which will be treated as though the +required code itself had thrown an exception. + +The C<${^HOOK}{require__before}> hook may return a code reference, in +which case the code reference will be executed (in an eval with the +filname as a parameter) after the require completes. It will be executed +regardless of how the compilation completed, and even if the require +throws a fatal exception. The function may consult C<%INC> to determine +if the require failed or not. For instance the following code will print +some diagnostics before and after every C<require> statement. The +example also includes logic to chain the signal, so that multiple +signals can cooperate. Well behaved C<${^HOOK}{require__before}> +handlers should always take this into account. + + { + use Scalar::Util qw(reftype); + my $old_hook = ${^HOOK}{require__before}; + local ${^HOOK}{require__before} = sub { + my ($name) = @_; + my $old_hook_ret; + $old_hook_ret = $old_hook->($name) if $old_hook; + warn "Requiring: $name\n"; + return sub { + $old_hook_ret->() if ref($old_hook_ret) + && reftype($old_hook_ret) eq "CODE"; + warn sprintf "Finished requiring %s: %s\n", + $name, $INC{$name} ? "loaded" :"failed"; + }; + }; + require Whatever; + } + +This hook executes for ALL C<require> statements, unlike C<INC> and +C<INCDIR> hooks, which are only executed for relative file names, and it +executes first before any other special behaviour inside of require. +Note that the initial hook in C<${^HOOK}{require__before}> is *not* +executed inside of an eval, and throwing an exception will stop further +processing, but the after hook it may return is executed inside of an +eval, and any exceptions it throws will be silently ignored. This is +because it executes inside of the scope cleanup logic that is triggered +after the require completes, and an exception at this time would not +stop the module from being loaded, etc. + +There is a similar hook that fires after require completes, +C<${^HOOK}{require__after}>, which will be called after each require statement +completes, either via an exception or successfully. It will be called with +the filename of the most recently executed require statement. It is executed +in an eval, and will not in any way affect execution. + +For a yet-more-powerful import facility built around C<require>, see L<C<use>|/use Module VERSION LIST> and L<perlmod>. =item reset EXPR diff --git a/pod/perlguts.pod b/pod/perlguts.pod index 9f35597d7a..e0101d33ad 100644 --- a/pod/perlguts.pod +++ b/pod/perlguts.pod @@ -1555,6 +1555,8 @@ will be lost. y PERL_MAGIC_defelem vtbl_defelem Shadow "foreach" iterator variable / smart parameter vivification + Z PERL_MAGIC_hook vtbl_hook %{^HOOK} hash + z PERL_MAGIC_hookelem vtbl_hookelem %{^HOOK} hash element \ PERL_MAGIC_lvref vtbl_lvref Lvalue reference constructor ] PERL_MAGIC_checkcall vtbl_checkcall Inlining/mutation of call @@ -1584,6 +1586,8 @@ will be lost. =for apidoc_item ||PERL_MAGIC_fm =for apidoc_item ||PERL_MAGIC_hints =for apidoc_item ||PERL_MAGIC_hintselem +=for apidoc_item ||PERL_MAGIC_hook +=for apidoc_item ||PERL_MAGIC_hookelem =for apidoc_item ||PERL_MAGIC_isa =for apidoc_item ||PERL_MAGIC_isaelem =for apidoc_item ||PERL_MAGIC_lvref diff --git a/pod/perlvar.pod b/pod/perlvar.pod index aebd6a45bd..25dbd05a9b 100644 --- a/pod/perlvar.pod +++ b/pod/perlvar.pod @@ -779,6 +779,71 @@ and use an C<END{}> or CORE::GLOBAL::die override instead. See L<perlfunc/die>, L<perlfunc/warn>, L<perlfunc/eval>, and L<warnings> for additional information. +=item %{^HOOK} +X<%{^HOOK}> + +This hash contains coderefs which are called when various perl keywords +which are hard or impossible to wrap are called. The keys of this hash +are named after the keyword that is being hooked, followed by two +underbars and then a phase term; either "before" or "after". + +Perl will throw an error if you attempt modify a key which is not +documented to exist, or if you attempt to store anything other than a +code reference or undef in the hash. If you wish to use an object to +implement a hook you can use currying to embed the object into an +anonymous code reference. + +Currently there is only one keyword which can be hooked, C<require>, but +it is expected that in future releases there will be additional keywords +with hook support. + +=over 4 + +=item require__before + +The routine indicated by C<${^HOOK}{require__before}> is called by +C<require> B<before> it checks C<%INC>, looks up C<@INC>, calls INC +hooks, or compiles any code. It is called with a single argument, the +filename for the item being required (package names are converted to +paths). It may alter this filename to change what file is loaded. If +the hook dies during execution then it will block the require from executing. + +In order to make it easy to perform an action with shared state both +before and after the require keyword was executed the C<require__before> +hook may return a "post-action" coderef which will in turn be executed when +the C<require> completes. This coderef will be executed regardless as to +whether the require completed succesfully or threw an exception. It will +be called with the filename that was required. You can check %INC to +determine if the require was successful. Any other return from the +C<require__before> hook will be silently ignored. + +C<require__before> hooks are called in FIFO order, and if the hook +returns a code reference those code references will be called in FILO +order. In other words if A requires B requires C, then +C<require__before> will be called first for A, then B and then C, and +the post-action code reference will executed first for C, then B and +then finally A. + +Well behaved code should ensure that when setting up a +C<require__before> hook that any prior installed hook will be called, +and that their return value, if a code reference, will be called as +well. See L<perlfunc/require> for an example implementation. + +=item require__after + +The routine indicated by C<${^HOOK}{require__after}> is called by +C<require> B<after> the require completes. It is called with a single +argument, the filename for the item being required (package names are +converted to paths). It is executed when the C<require> completes, +either via exception or via completion of the require statement, and you +can check C<%INC> to determine if the require was successful. + +The C<require__after> hook is called for each required file in FILO +order. In other words if A requires B requires C, then C<require__after> +will be called first for C, then B and then A. + +=back + =item $BASETIME =item $^T |