}
sub _initialize_object{
- my($self, $object, $args, $ignore_triggers) = @_;
+ my($self, $object, $args, $is_cloning) = @_;
my @triggers_queue;
push @triggers_queue, [ $attribute->trigger, $object->{$slot} ];
}
}
- else { # no init arg
+ elsif(!$is_cloning) { # no init arg, noop while cloning
if ($attribute->has_default || $attribute->has_builder) {
if (!$attribute->is_lazy) {
my $default = $attribute->default;
}
}
- if(!$ignore_triggers){
+ if(@triggers_queue){
foreach my $trigger_and_value(@triggers_queue){
my($trigger, $value) = @{$trigger_and_value};
$trigger->($object, $value);
#!/usr/bin/env perl
use strict;
use warnings;
-use Test::More tests => 12;
+use Test::More;
use Test::Exception;
my %triggered;
-do {
+{
package Foo;
use Mouse;
my ($self, @args) = @_;
$self->meta->clone_object($self, @args);
}
-};
+}
+
+{
+ package Bar;
+ use Mouse;
+
+ has id => (
+ is => 'ro',
+ isa => 'Str',
+
+ required => 1,
+ );
+
+ sub clone {
+ my ($self, @args) = @_;
+ $self->meta->clone_object($self, @args);
+ }
+}
my $foo = Foo->new(bar => [ 1, 2, 3 ], quuux => "indeed");
is($clone->baz, "foo", "init_arg=undef means the attr is ignored");
is($clone->quux, "yes", "clone uses init_arg and not attribute name");
+lives_and {
+ my $bar = Bar->new(id => 'xyz');
+ my $c = $bar->clone;
+
+ is_deeply $bar, $c, "clone() with required attributes";
+};
+
throws_ok {
Foo->meta->clone_object("constant");
} qr/You must pass an instance of the metaclass \(Foo\), not \(constant\)/;
Foo->meta->clone_object(Foo->meta)
} qr/You must pass an instance of the metaclass \(Foo\), not \(Mouse::Meta::Class=HASH\(\w+\)\)/;
-
+done_testing;
static void
-mouse_class_initialize_object(pTHX_ SV* const meta, SV* const object, HV* const args, bool const ignore_triggers) {
+mouse_class_initialize_object(pTHX_ SV* const meta, SV* const object, HV* const args, bool const is_cloning) {
AV* const xc = mouse_get_xc(aTHX_ meta);
AV* const attrs = MOUSE_xc_attrall(xc);
I32 len = AvFILLp(attrs) + 1;
croak("You cannot use tied HASH reference as initializing arguments");
}
- if(!ignore_triggers){
- triggers_queue = newAV_mortal();
- }
-
/* for each attribute */
for(i = 0; i < len; i++){
SV* const attr = MOUSE_av_at(attrs, i);
if(SvROK(value) && flags & MOUSEf_ATTR_IS_WEAK_REF){
weaken_slot(object, slot);
}
- if(flags & MOUSEf_ATTR_HAS_TRIGGER && triggers_queue){
+ if(flags & MOUSEf_ATTR_HAS_TRIGGER){
AV* const pair = newAV();
av_push(pair, newSVsv( mcall0s(attr, "trigger") ));
av_push(pair, newSVsv(value));
+ if(!triggers_queue) {
+ triggers_queue = newAV_mortal();
+ }
av_push(triggers_queue, (SV*)pair);
}
used++;
}
- else { /* no init arg */
+ else if(!is_cloning){ /* no init arg, noop while cloning */
if(flags & (MOUSEf_ATTR_HAS_DEFAULT | MOUSEf_ATTR_HAS_BUILDER)){
if(!(flags & MOUSEf_ATTR_IS_LAZY)){
mouse_xa_set_default(aTHX_ xa, object);
RETVAL
void
-_initialize_object(SV* meta, SV* object, HV* args, bool ignore_triggers = FALSE)
+_initialize_object(SV* meta, SV* object, HV* args, bool is_cloning = FALSE)
CODE:
{
- mouse_class_initialize_object(aTHX_ meta, object, args, ignore_triggers);
+ mouse_class_initialize_object(aTHX_ meta, object, args, is_cloning);
}
MODULE = Mouse PACKAGE = Mouse::Meta::Role