Attached patch should fix it.
--
Paul Evans
=== modified file 'lib/IO/Async/Notifier.pm'
--- lib/IO/Async/Notifier.pm 2011-02-10 23:30:56 +0000
+++ lib/IO/Async/Notifier.pm 2011-02-16 20:05:19 +0000
@@ -458,6 +458,10 @@
The C<$code> argument may also be a plain string, which will be used as a
method name; the returned CODE ref will then invoke that method on the object.
+In this case the method name is stored symbolically in the returned CODE
+reference, and dynamically dispatched each time the reference is invoked. This
+allows it to follow code reloading, dynamic replacement of class methods, or
+other similar techniques.
If the C<$mref> CODE reference is being stored in some object other than the
one it refers to, remember that since the Notifier is only weakly captured, it
@@ -480,21 +484,24 @@
if( !ref $code ) {
my $class = ref $self;
- my $coderef = $self->can( $code ) or
+ # Don't save this coderef, or it will break dynamic method dispatch,
+ # which means code reloading, dynamic replacement, or other funky
+ # techniques stop working
+ $self->can( $code ) or
croak qq(Can't locate object method "$code" via package "$class");
-
- $code = $coderef;
}
weaken $self;
return sub {
+ my $cv = ref( $code ) ? $code : $self->can( $code );
+
if( HAS_BROKEN_TRAMPOLINES ) {
- return $code->( $self, @_ );
+ return $cv->( $self, @_ );
}
else {
unshift @_, $self;
- goto &$code;
+ goto &$cv;
}
};
}
@@ -521,6 +528,7 @@
The C<$code> argument may also be a plain string, which will be used as a
method name; the returned CODE ref will then invoke that method on the object.
+As with C<_capture_weakself> this is stored symbolically.
As with C<_capture_weakself>, care should be taken against Notifier
destruction if the C<$mref> CODE reference is stored in some other object.
@@ -533,24 +541,25 @@
my ( $code ) = @_; # actually bare method names work too
if( !ref $code ) {
+ # Don't save this coderef, see _capture_weakself for why
my $class = ref $self;
- my $coderef = $self->can( $code ) or
+ $self->can( $code ) or
croak qq(Can't locate object method "$code" via package "$class");
-
- $code = $coderef;
}
weaken $self;
return sub {
+ my $cv = ref( $code ) ? $code : $self->can( $code );
+
if( HAS_BROKEN_TRAMPOLINES ) {
- return $code->( $self, @_[1..$#_] );
+ return $cv->( $self, @_[1..$#_] );
}
else {
# Don't assign to $_[0] directly or we will change caller's first argument
shift @_;
unshift @_, $self;
- goto &$code;
+ goto &$cv;
}
};
}
=== modified file 't/04notifier.t'
--- t/04notifier.t 2011-02-09 09:45:12 +0000
+++ t/04notifier.t 2011-02-16 20:05:19 +0000
@@ -2,7 +2,7 @@
use strict;
-use Test::More tests => 36;
+use Test::More tests => 38;
use Test::Fatal;
use Test::Refcount;
@@ -105,6 +105,19 @@
$mref->( 456 );
is_deeply( \@subargs, [ $notifier, 456 ], '@subargs after invoking $mref on named method' );
+{
+ undef @subargs;
+ my @newargs;
+
+ no warnings 'redefine';
+ local *TestNotifier::frobnicate = sub { @newargs = @_; };
+
+ $mref->( 321 );
+
+ is_deeply( \@subargs, [], '@subargs empty after TestNotifier::frobnicate replacement' );
+ is_deeply( \@newargs, [ $notifier, 321 ], '@newargs after TestNotifier::frobnicate replacement' );
+}
+
undef @subargs;
ok( exception { $notifier->_capture_weakself( 'cannotdo' ) },