From: Jesse Luehrs Date: Fri, 4 Mar 2011 17:59:06 +0000 (-0600) Subject: make the namespace cache lazy and weak, in case the stash is deleted X-Git-Tag: 0.26~4 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=eb53b1bd771d2bed902655654014680ea64cf8d4;p=gitmo%2FPackage-Stash.git make the namespace cache lazy and weak, in case the stash is deleted --- diff --git a/lib/Package/Stash/PP.pm b/lib/Package/Stash/PP.pm index d6ca34b..653eeaf 100644 --- a/lib/Package/Stash/PP.pm +++ b/lib/Package/Stash/PP.pm @@ -4,7 +4,7 @@ use warnings; # ABSTRACT: pure perl implementation of the Package::Stash API use Carp qw(confess); -use Scalar::Util qw(blessed reftype); +use Scalar::Util qw(blessed reftype weaken); use Symbol; # before 5.12, assigning to the ISA glob would make it lose its magical ->isa # powers @@ -24,15 +24,8 @@ sub new { my $class = shift; my ($package) = @_; my $namespace; - { - no strict 'refs'; - # supposedly this caused a bug in earlier perls, but I can't reproduce - # it, so re-enabling the caching - $namespace = \%{$package . '::'}; - } return bless { - 'package' => $package, - 'namespace' => $namespace, + 'package' => $package, }, $class; } @@ -45,6 +38,17 @@ sub name { sub namespace { confess "Can't call namespace as a class method" unless blessed($_[0]); + return $_[0]->{namespace} if defined $_[0]->{namespace}; + + { + no strict 'refs'; + # supposedly this caused a bug in earlier perls, but I can't reproduce + # it, so re-enabling the caching + $_[0]->{namespace} = \%{$_[0]->name . '::'}; + } + + weaken($_[0]->{namespace}); + return $_[0]->{namespace}; } diff --git a/t/07-edge-cases.t b/t/07-edge-cases.t index 4f61ca2..acd92e8 100755 --- a/t/07-edge-cases.t +++ b/t/07-edge-cases.t @@ -66,4 +66,19 @@ is(exception { $Bar->add_symbol('$bar', \$bar) }, undef, use_ok('CompileTime'); +{ + package Gets::Deleted; + sub bar { } +} + +{ + my $delete = Package::Stash->new('Gets::Deleted'); + ok($delete->has_symbol('&bar'), "sees the method"); + { + no strict 'refs'; + delete ${'main::Gets::'}{'Deleted::'}; + } + ok(!$delete->has_symbol('&bar'), "method goes away when stash is deleted"); +} + done_testing;