summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2011-03-04 12:33:39 -0600
committerJesse Luehrs <doy@tozt.net>2011-03-04 12:33:39 -0600
commit3126316894b74934d9192c69ec580be1abd1c589 (patch)
tree2f510ef0f80d1d7f26d5e7fea01efe60eaac8922
parentbe41f2111b3fa566459f4ecacfa111c95c037cb1 (diff)
downloadpackage-stash-xs-3126316894b74934d9192c69ec580be1abd1c589.tar.gz
package-stash-xs-3126316894b74934d9192c69ec580be1abd1c589.zip
make the namespace cache lazy and weak, in case the stash is deleted
-rw-r--r--XS.xs28
-rwxr-xr-xt/07-edge-cases.t15
2 files changed, 33 insertions, 10 deletions
diff --git a/XS.xs b/XS.xs
index 159aa5a..73ca16f 100644
--- a/XS.xs
+++ b/XS.xs
@@ -351,8 +351,6 @@ new(class, package_name)
SV *package_name
PREINIT:
HV *instance;
- HV *namespace;
- SV *nsref;
CODE:
if (!SvPOK(package_name))
croak("The constructor argument must be the name of a package");
@@ -364,13 +362,6 @@ new(class, package_name)
SvREFCNT_dec(instance);
croak("Couldn't initialize the 'name' key, hv_store failed");
}
- namespace = gv_stashpv(SvPV_nolen(package_name), GV_ADD);
- nsref = newRV_inc((SV*)namespace);
- if (!hv_store(instance, "namespace", 9, nsref, 0)) {
- SvREFCNT_dec(nsref);
- SvREFCNT_dec(instance);
- croak("Couldn't initialize the 'namespace' key, hv_store failed");
- }
RETVAL = sv_bless(newRV_noinc((SV*)instance), gv_stashsv(class, 0));
OUTPUT:
@@ -398,7 +389,24 @@ namespace(self)
if (!sv_isobject(self))
croak("Can't call namespace as a class method");
slot = hv_fetch_ent((HV*)SvRV(self), namespace_key, 0, namespace_hash);
- RETVAL = slot ? SvREFCNT_inc_simple_NN(HeVAL(slot)) : &PL_sv_undef;
+ if (slot) {
+ RETVAL = SvREFCNT_inc_simple_NN(HeVAL(slot));
+ }
+ else {
+ HV *namespace;
+ SV *nsref, *package_name;
+
+ package_name = _get_name(self);
+ namespace = gv_stashpv(SvPV_nolen(package_name), GV_ADD);
+ nsref = newRV_inc((SV*)namespace);
+ sv_rvweaken(nsref);
+ if (!hv_store((HV*)SvRV(self), "namespace", 9, nsref, 0)) {
+ SvREFCNT_dec(nsref);
+ SvREFCNT_dec(self);
+ croak("Couldn't initialize the 'namespace' key, hv_store failed");
+ }
+ RETVAL = SvREFCNT_inc_simple_NN(nsref);
+ }
OUTPUT:
RETVAL
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;