summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2012-09-14 14:20:07 -0700
committerFather Chrysostomos <sprout@cpan.org>2012-09-14 22:29:47 -0700
commit37b0b3b2e3fecf62fbb5a9c784ad24707e8d3581 (patch)
tree9d0f11f2160440fe168a5c0a62a2c8f1de04b691
parent0308a534a635b8c34297657046d32a3f05818821 (diff)
downloadperl-37b0b3b2e3fecf62fbb5a9c784ad24707e8d3581.tar.gz
Make SUPER::method respect method changes in moved pkg
->SUPER::method calls inside the Foo package cache the method for reuse inside the stash Foo::SUPER. Before the call, @Foo::SUPER::ISA is set to "Foo", so that those caches will be invalidated properly. (@ISA has the magic to make that work.) The actual value in @Foo::SUPER::ISA unused. Now we have two types of package names. If you alias the Foo package and then clobber the original entry: *Bar:: = *Foo::; undef *Foo::; __PACKAGE__ and HvNAME will return Foo still, but HvENAME (the effec- tive name) will return Bar, because that is where the package is to be found. As of the previous commit, the package used for ISA is based on the effective name, Bar::SUPER in this case. But @Bar::SUPER::ISA is still set to Foo. So even if we make changes to methods inherited by what is now the Bar package, a previous method cached in *Bar::SUPER::method will be reused. BEGIN { *Bar:: = *Foo::; undef *Foo::; } package Bar; @ISA = 'Baz'; *Baz::m = sub { "method 1" }; anthying->SUPER::m; undef *Baz::m; *Baz::m = sub { "method 2" }; warn anything->SUPER::m; __END__ method 1 at - line 11.
-rw-r--r--gv.c2
-rw-r--r--t/op/method.t6
2 files changed, 6 insertions, 2 deletions
diff --git a/gv.c b/gv.c
index 6b6e49340d..e64c8f29f6 100644
--- a/gv.c
+++ b/gv.c
@@ -921,7 +921,7 @@ S_gv_get_super_pkg(pTHX_ const char* name, I32 namelen, U32 flags)
GvMULTI_on(gv);
sv_magic(MUTABLE_SV(superisa), MUTABLE_SV(gv), PERL_MAGIC_isa, NULL, 0);
av_push(superisa, newSVhek(CopSTASH(PL_curcop)
- ? HvNAME_HEK(CopSTASH(PL_curcop)) : NULL));
+ ? HvENAME_HEK(CopSTASH(PL_curcop)) : NULL));
return stash;
}
diff --git a/t/op/method.t b/t/op/method.t
index aaa70be6af..584ffd99f1 100644
--- a/t/op/method.t
+++ b/t/op/method.t
@@ -13,7 +13,7 @@ BEGIN {
use strict;
no warnings 'once';
-plan(tests => 109);
+plan(tests => 110);
@A::ISA = 'B';
@B::ISA = 'C';
@@ -262,6 +262,10 @@ sub OtherSouper::method { "Isidore Ropen, Draft Manager" }
sub door::dohtem { 'dohtem' }
::is eval { Mover->SUPER::dohtem; }, 'dohtem',
'SUPER inside moved package';
+ undef *door::dohtem;
+ *door::dohtem = sub { 'method' };
+ ::is eval { Mover->SUPER::dohtem; }, 'method',
+ 'SUPER inside moved package respects method changes';
}
# failed method call or UNIVERSAL::can() should not autovivify packages