Skip Menu |

Preferred bug tracker

Please visit the preferred bug tracker to report your issue.

This queue is for tickets about the Mouse CPAN distribution.

Report information
The Basics
Id: 56837
Status: resolved
Priority: 0/
Queue: Mouse

People
Owner: Nobody in particular
Requestors: sanko [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: 0.55
Fixed in: (no value)



Subject: Role application to instance with init_arg'd attributes
The attached .patch covers a (perhaps over the) edge case where a role is applied at runtime to an instance which has attributes which in turn have user-defined init_arg names. With Moose, this works as I expect it to; the role is applied cleanly and all attributes are in their correct slots. With Mouse, after the instance is reblessed in Mouse::Meta::Role::apply(), its contents are used (as a simple hashref) to re- initialize the object. For attributes with init_arg names different from their actual name, the keys in this hashref are incorrect for initialization. ...an example is probably a lot easier to understand than that was, so here's one where the attribute is also required so the problem is slightly more evident: package User; use Mouse; has 'name' => (isa => 'Str', is => 'ro', required => 1, init_arg => 'Name'); package Admin; use Mouse::Role; package main; my $tim = User->new(Name => 'Tim'); Admin->meta->apply($tim); Be aware that it's allergy season so this 'fix' may not be the best solution (seeing as I had to patch both the XS and PurePerl versions of _initialize_object(), it's most likely the wrong place for such changes) and should be triple checked before being accepted. -- Sanko Robinson sanko@cpan.org
Subject: patch1.patch
diff --git a/lib/Mouse/PurePerl.pm b/lib/Mouse/PurePerl.pm index d1b2c27..92532c6 100644 --- a/lib/Mouse/PurePerl.pm +++ b/lib/Mouse/PurePerl.pm @@ -288,6 +288,10 @@ sub _initialize_object{ my $init_arg = $attribute->init_arg; my $slot = $attribute->name; + if (defined($init_arg) && exists($args->{$slot}) + && ! exists($args->{$init_arg})) { + $args->{$init_arg} = delete $args->{$slot}; + } if (defined($init_arg) && exists($args->{$init_arg})) { $object->{$slot} = $attribute->_coerce_and_verify($args->{$init_arg}, $object); diff --git a/t/100_bugs/028_runtime_roles_with_require_and_init_arg_attr.t b/t/100_bugs/028_runtime_roles_with_require_and_init_arg_attr.t new file mode 100644 index 0000000..4946bd7 --- /dev/null +++ b/t/100_bugs/028_runtime_roles_with_require_and_init_arg_attr.t @@ -0,0 +1,23 @@ +use Test::More tests => 2; + +{ + package Admin; + use Mouse::Role; + sub shutdown {1} +} +{ + package User; + use Mouse; + has 'name' => + (isa => 'Str', is => 'ro', init_arg => 'Name', required => 1); +} + +package main; +my $tim = User->new(Name => 'Tim'); + +Admin->meta->apply($tim); + +ok($tim->can('shutdown'), + 'The role was successfully composed at the object level'); +is($tim->name, 'Tim', + '... attribute with init_arg was re-initialized correctly'); diff --git a/xs-src/Mouse.xs b/xs-src/Mouse.xs index 5c7e623..fc43932 100644 --- a/xs-src/Mouse.xs +++ b/xs-src/Mouse.xs @@ -317,6 +317,15 @@ mouse_class_initialize_object(pTHX_ SV* const meta, SV* const object, HV* const SV* const init_arg = MOUSE_xa_init_arg(xa); HE* he; + if(SvOK(init_arg) && hv_exists_ent(args, slot, 0U) + && !hv_exists_ent(args, init_arg, 0U)) { + SV * _current = hv_delete_ent(args, slot, 0, 0U); + he = hv_fetch_ent(args, init_arg, TRUE, 0U); + SV * value = HeVAL(he); + sv_setsv(value, _current); + SvSETMAGIC(value); + } + if(SvOK(init_arg) && ( he = hv_fetch_ent(args, init_arg, FALSE, 0U) ) ){ SV* value = HeVAL(he); if(flags & MOUSEf_ATTR_HAS_TC){
Hi, Thank you for your report. I have released 0.56 with your tests. It was lucky that I fixed a similar problem (fixed in 0.53), so I made this fix with that change, rather than using your patch directly. Regards, -- Goro Fuji (gfx) GFUJI at CPAN.org