Skip to content

Commit

Permalink
Revert "we can catch this earlier now that we optimize out unused att…
Browse files Browse the repository at this point in the history
…ributes"

This reverts commit 50d8ed5.

this actually doesn't work, because a method might look like

    method wrap ($app, @Args) {
        if (ref $self) {
            $!app = $app;
        } else {
            $self = $self->new({ app => $app, @Args });
        }
        return $self->to_app;
    }
  • Loading branch information
doy committed Nov 18, 2013
1 parent c2040cb commit 45dcb56
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 6 deletions.
48 changes: 43 additions & 5 deletions mop.xs
Expand Up @@ -333,6 +333,28 @@ mg_attr_set(pTHX_ SV *sv, MAGIC *mg)
return 0;
}

static int
mg_err_get(pTHX_ SV *sv, MAGIC *mg)
{
PERL_UNUSED_ARG(sv);

assert(mg->mg_obj && SvPOK(mg->mg_obj));

croak("Cannot access the attribute:(%"SVf") in a method "
"without a blessed invocant", SVfARG(mg->mg_obj));
}

static int
mg_err_set(pTHX_ SV *sv, MAGIC *mg)
{
PERL_UNUSED_ARG(sv);

assert(mg->mg_obj && SvPOK(mg->mg_obj));

croak("Cannot assign to the attribute:(%"SVf") in a method "
"without a blessed invocant", SVfARG(mg->mg_obj));
}

static MGVTBL attr_vtbl = {
mg_attr_get, /* get */
mg_attr_set, /* set */
Expand All @@ -343,6 +365,16 @@ static MGVTBL attr_vtbl = {
0, /* dup */
0, /* local */
};
static MGVTBL err_vtbl = {
mg_err_get, /* get */
mg_err_set, /* set */
0, /* len */
0, /* clear */
0, /* free */
0, /* copy */
0, /* dup */
0, /* local */
};

#define set_attr_magic(var, name, meta, self) THX_set_attr_magic(aTHX_ var, name, meta, self)
static void
Expand All @@ -357,6 +389,13 @@ THX_set_attr_magic(pTHX_ SV *var, SV *name, SV *meta, SV *self)
sv_magicext(var, (SV *)data, PERL_MAGIC_ext, &attr_vtbl, "attr", 0);
}

#define set_err_magic(var, name) THX_set_err_magic(aTHX_ var, name)
static void
THX_set_err_magic(pTHX_ SV *var, SV *name)
{
sv_magicext(var, name, PERL_MAGIC_ext, &err_vtbl, "err", 0);
}

/* }}} */
/* version helpers {{{ */

Expand Down Expand Up @@ -1332,11 +1371,10 @@ pp_init_attr(pTHX)
attr_name = POPs;
meta_class = get_meta(meta_class_name);

if (!sv_isobject(invocant))
croak("Cannot access the attribute:(%"SVf") in a method "
"without a blessed invocant", SVfARG(attr_name));

set_attr_magic(TARG, attr_name, meta_class, invocant);
if (sv_isobject(invocant))
set_attr_magic(TARG, attr_name, meta_class, invocant);
else
set_err_magic(TARG, attr_name);

RETURN;
}
Expand Down
2 changes: 1 addition & 1 deletion t/010-basics/007-class-methods.t
Expand Up @@ -19,7 +19,7 @@ class Foo {
eval { Foo->bar(10) };
like(
$@,
qr/^Cannot access the attribute\:\(\$!bar\) in a method without a blessed invocant/,
qr/^Cannot assign to the attribute\:\(\$!bar\) in a method without a blessed invocant/,
'... got the error we expected'
);

Expand Down
28 changes: 28 additions & 0 deletions t/010-basics/028-attributes-in-class-methods.t
@@ -0,0 +1,28 @@
#!/usr/bin/env perl
use strict;
use warnings;
use Test::More;

use mop;

# this comes up in, for instance, Plack::Middleware::wrap

class Foo {
has $!bar is ro;

method baz ($bar) {
if (ref($self)) {
$!bar = $bar;
}
else {
$self = __CLASS__->new(bar => $bar);
}

return $self->bar;
}
}

is(Foo->baz('BAR-class'), 'BAR-class');
is(Foo->new->baz('BAR-instance'), 'BAR-instance');

done_testing;

0 comments on commit 45dcb56

Please sign in to comment.