make the namespace cache lazy and weak, in case the stash is deleted
Jesse Luehrs [Fri, 4 Mar 2011 17:59:06 +0000 (11:59 -0600)]
lib/Package/Stash/PP.pm
t/07-edge-cases.t

index d6ca34b..653eeaf 100644 (file)
@@ -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};
 }
 
index 4f61ca2..acd92e8 100755 (executable)
@@ -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;