$is_removable{$name} = 1;
}
+ $class->_make_prototyped_sub($sub);
+
$export_recorder->{$sub} = 1;
$exports{$name} = sub {$sub};
};
}
-sub _make_wrapper {
+sub _make_prototyped_sub {
shift;
+ my $sub = shift;
+
+ # If I use Scalar::Util::set_prototype, this will forever be bound to XS.
+ # And it's hard to use anyway (it requires a BLOCK or a sub{} declaration
+ # as its first argument)
+ if (my $proto = prototype $sub) {
+ $sub = eval "sub ($proto) { \$sub->(\@_) }";
+ Carp::confess if $@;
+ }
+ return $sub;
+}
+
+sub _make_wrapper {
+ my $class = shift;
my $caller = shift;
my $sub = shift;
my $fq_name = shift;
- return sub { $sub->($caller, @_) };
+ # XXX optimization: since we're building a new sub anyways, we
+ # unroll _make_prototyped_sub here
+ my $wrapper;
+ if (my $proto = prototype $sub) {
+ $wrapper = eval "sub ($proto) { \$sub->(\$caller, \@_) }";
+ Carp::confess if $@;
+ } else {
+ $wrapper = sub { $sub->($caller, @_) };
+ }
+ return $wrapper;
}
sub _make_import_sub {
--- /dev/null
+use lib "t/lib";
+package MyExporter::User;
+use MyExporter;
+
+use Test::More (tests => 4);
+use Test::Exception;
+
+lives_and {
+ with_prototype {
+ my $caller = caller(0);
+ is($caller, 'MyExporter', "With_caller prototype code gets called from MyMooseX");
+ };
+} "check function with prototype";
+
+lives_and {
+ as_is_prototype {
+ my $caller = caller(0);
+ is($caller, 'MyExporter', "As-is prototype code gets called from MyMooseX");
+ };
+} "check function with prototype";
--- /dev/null
+
+
+package MyExporter;
+use Moose::Exporter;
+use Test::More;
+
+Moose::Exporter->setup_import_methods(
+ with_caller => [ qw(with_prototype) ],
+ as_is => [ qw(as_is_prototype) ],
+);
+
+sub with_prototype (&) {
+ my ($class, $code) = @_;
+ isa_ok($code, 'CODE', 'with_prototype received a coderef');
+ $code->();
+}
+
+sub as_is_prototype (&) {
+ my ($code) = @_;
+ isa_ok($code, 'CODE', 'as_is_prototype received a coderef');
+ $code->();
+}
+
+1;
\ No newline at end of file