From: Jesse Luehrs Date: Fri, 4 Mar 2011 18:33:39 +0000 (-0600) Subject: make the namespace cache lazy and weak, in case the stash is deleted X-Git-Tag: 0.22~3 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=gitmo%2FPackage-Stash-XS.git;a=commitdiff_plain;h=3126316894b74934d9192c69ec580be1abd1c589 make the namespace cache lazy and weak, in case the stash is deleted --- 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;