From 93f6f9654a81b66c47c07ca982e4c00558bd4159 Mon Sep 17 00:00:00 2001 From: Yves Orton Date: Mon, 19 Dec 2022 19:32:03 +0100 Subject: pp_ctl.c - add support for hooking require. This defines a new magic hash C<%{^HOOK}> which is intended to be used for hooking keywords. It is similar to %SIG in that the values it contains are validated on set, and it is not allowed to store something in C<%{^HOOK}> that isn't supposed to be there. Hooks are expected to be coderefs (people can use currying if they really want to put an object in there, the API is deliberately simple.) The C<%{^HOOK}> hash is documented to have keys of the form "${keyword}__${phase}" where $phase is either "before" or "after" and in this initial release two hooks are supported, "require__before" and "require__after": The C hook is called before require is executed, including any @INC hooks that might be fired. It is called with the path of the file being required, just as would be stored in %INC. The hook may alter the filename by writing to $_[0] and it may return a coderef to be executed *after* the require has completed, otherwise the return is ignored. This coderef is also called with the path of the file which was required, and it will be called regardless as to whether the require (or its dependencies) die during execution. This mechanism makes it trivial and safe to share state between the initial hook and the coderef it returns. The C hook is similar to the C hook however except that it is called after the require completes (successfully or not), and its return is ignored always. --- pod/perlvar.pod | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) (limited to 'pod/perlvar.pod') 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 or CORE::GLOBAL::die override instead. See L, L, L, and L 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, 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 B 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 +hook may return a "post-action" coderef which will in turn be executed when +the C 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 hook will be silently ignored. + +C 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 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 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 for an example implementation. + +=item require__after + +The routine indicated by C<${^HOOK}{require__after}> is called by +C B 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 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 hook is called for each required file in FILO +order. In other words if A requires B requires C, then C +will be called first for C, then B and then A. + +=back + =item $BASETIME =item $^T -- cgit v1.2.1