From 7ece130cfc351e31e273d14a72ccd8442c0df549 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Fri, 31 May 2013 03:06:56 -0500 Subject: work around a lexical::persistence bug --- lib/Reply/Plugin/LexicalPersistence.pm | 38 ++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/lib/Reply/Plugin/LexicalPersistence.pm b/lib/Reply/Plugin/LexicalPersistence.pm index 0540f96..deb8d94 100644 --- a/lib/Reply/Plugin/LexicalPersistence.pm +++ b/lib/Reply/Plugin/LexicalPersistence.pm @@ -25,7 +25,45 @@ sub compile { (map { $_ => ref($c{$_}) ? $c{$_} : \$c{$_} } keys %c), }; my ($code) = $next->($line, %args); + $code = $self->_fixup_code($code, \%c); return $self->{env}->wrap($code); } +# XXX this is maybe a bug in Lexical::Persistence - it clears variables that +# aren't in its context, regardless of if they may have been set elsewhere +sub _fixup_code { + my $self = shift; + my ($code, $context) = @_; + + require PadWalker; + require Devel::LexAlias; + + my $pad = PadWalker::peek_sub($code); + my %restore; + for my $var (keys %$pad) { + next unless $var =~ /^\$\@\%./; + next if exists $context->{$var}; + $restore{$var} = $pad->{$var}; + } + + $self->{code} = $code; + + return sub { + my $code = shift; + for my $var (keys %restore) { + Devel::LexAlias::lexalias($code, $var, $restore{$var}); + } + $code->(@_); + }; +} + +# XXX can't just close over $code, because it will also be cleared by the same +# bug! we have to pass it as a parameter instead +sub execute { + my $self = shift; + my ($next, @args) = @_; + + $next->(delete $self->{code}, @args); +} + 1; -- cgit v1.2.3-54-g00ecf