make weak_ref+lazy match behavior of moose
Graham Knop [Thu, 18 Apr 2013 04:34:47 +0000 (00:34 -0400)]
lib/Method/Generate/Accessor.pm
t/accessor-weaken.t

index e5ca31d..ad9f683 100644 (file)
@@ -489,11 +489,11 @@ sub _generate_core_set {
 sub _generate_simple_set {
   my ($self, $me, $name, $spec, $value) = @_;
   my $name_str = perlstring $name;
+  my $simple = $self->_generate_core_set($me, $name, $spec, $value);
 
   if ($spec->{weak_ref}) {
-    $value = '$preserve = '.$value;
-    my $simple = $self->_generate_core_set($me, $name, $spec, $value);
     require Scalar::Util;
+    my $get = $self->_generate_simple_get($me, $name, $spec);
 
     # Perl < 5.8.3 can't weaken refs to readonly vars
     # (e.g. string constants). This *can* be solved by:
@@ -504,12 +504,10 @@ sub _generate_simple_set {
     #
     # but requires XS and is just too damn crazy
     # so simply throw a better exception
-    my $weak_simple = "my \$preserve; Scalar::Util::weaken(${simple}); no warnings 'void'; \$preserve";
+    my $weak_simple = "do { Scalar::Util::weaken(${simple}); no warnings 'void'; $get }";
     Moo::_Utils::lt_5_8_3() ? <<"EOC" : $weak_simple;
-
-      my \$preserve;
       eval { Scalar::Util::weaken($simple); 1 }
-        ? do { no warnings 'void'; \$preserve; }
+        ? do { no warnings 'void'; $get }
         : do {
           if( \$@ =~ /Modification of a read-only value attempted/) {
             require Carp;
@@ -523,7 +521,7 @@ sub _generate_simple_set {
         }
 EOC
   } else {
-    $self->_generate_core_set($me, $name, $spec, $value);
+    $simple;
   }
 }
 
index 89f49fa..5da1435 100644 (file)
@@ -12,24 +12,33 @@ use Test::More;
 
   use Moo;
 
-  has one => (is => 'rw', lazy => 1, weak_ref => 1, default => sub { {} });
+  our $preexist = {};
+  has one => (is => 'rw', lazy => 1, weak_ref => 1, default => sub { $preexist });
+  has two => (is => 'rw', lazy => 1, weak_ref => 1, default => sub { {} });
 }
 
 my $ref = {};
 my $foo = Foo->new(one => $ref);
 is($foo->one, $ref, 'value present');
 ok(Scalar::Util::isweak($foo->{one}), 'value weakened');
-is($foo->one($ref), $ref, 'value returned from setter');
 undef $ref;
 ok(!defined $foo->{one}, 'weak value gone');
 
 my $foo2 = Foo2->new;
-ok(my $ref2 = $foo2->one, 'value returned');
+ok(my $ref2 = $foo2->one, 'external value returned');
+is($foo2->one, $ref2, 'value maintained');
 ok(Scalar::Util::isweak($foo2->{one}), 'value weakened');
 is($foo2->one($ref2), $ref2, 'value returned from setter');
 undef $ref2;
 ok(!defined $foo->{one}, 'weak value gone');
 
+is($foo2->two, undef, 'weak+lazy ref not returned');
+is($foo2->{two}, undef, 'internal value not set');
+my $ref3 = {};
+is($foo2->two($ref3), $ref3, 'value returned from setter');
+undef $ref3;
+ok(!defined $foo->{two}, 'weak value gone');
+
 
 # test readonly SVs
 sub mk_ref { \ 'yay' };