diff options
author | Graham Knop <haarg@haarg.org> | 2022-03-01 08:31:03 +0100 |
---|---|---|
committer | Yves Orton <demerphq@gmail.com> | 2022-03-01 16:20:36 +0100 |
commit | f0ef35deb0072805b68cef82ebe28739f67ca79a (patch) | |
tree | dae12b8e86de697f54752069dc7fe8fa6b11e8d9 /dist/Attribute-Handlers | |
parent | 5fd455724334701f8b57422da66c641df3c87963 (diff) | |
download | perl-f0ef35deb0072805b68cef82ebe28739f67ca79a.tar.gz |
wrap any existing import in Attribute::Handlers' injected import
Some modules using Attribute::Handlers autotie feature have their own
import method. When injecting an import method, attempt to wrap anything
that exists, either in the class directly or in a parent class.
We can't detect parent classes at injection time, because @ISA may
change, and this is actually common since users of Exporter will add it
as a parent class at module runtime, while Attribute::Handlers injection
would happen first during compilation.
A better approach could involve using next::can from mro, but that also
requires Sub::Util::set_subname, and Attribute::Handlers is dual life
and currently supports 5.6.
Diffstat (limited to 'dist/Attribute-Handlers')
-rw-r--r-- | dist/Attribute-Handlers/lib/Attribute/Handlers.pm | 27 |
1 files changed, 20 insertions, 7 deletions
diff --git a/dist/Attribute-Handlers/lib/Attribute/Handlers.pm b/dist/Attribute-Handlers/lib/Attribute/Handlers.pm index 6de6ae987c..21f657dcb9 100644 --- a/dist/Attribute-Handlers/lib/Attribute/Handlers.pm +++ b/dist/Attribute-Handlers/lib/Attribute/Handlers.pm @@ -88,13 +88,26 @@ sub import { if ($attr =~ /\A__CALLER__::/) { no strict 'refs'; - *{ caller . '::import' } = sub { - my $caller = caller; - my $full_attr = $attr; - $full_attr =~ s/__CALLER__/$caller/; - eval qq{ sub $full_attr $code 1; } - or die "Internal error: $@"; - + my $add_import = caller; + my $next = defined &{ $add_import . '::import' } && \&{ $add_import . '::import' }; + *{ $add_import . '::import' } = sub { + my $caller = caller; + my $full_attr = $attr; + $full_attr =~ s/__CALLER__/$caller/; + eval qq{ sub $full_attr $code 1; } + or die "Internal error: $@"; + + goto &$next + if $next; + my $uni = defined &UNIVERSAL::import && \&UNIVERSAL::import; + for my $isa (@{ $add_import . '::ISA' }) { + if (my $import = $isa->can('import')) { + goto &$import + if $import != $uni; + } + } + goto &$uni + if $uni; }; } else { |