From: gfx Date: Sun, 7 Mar 2010 10:57:27 +0000 (+0900) Subject: Fix a possible panic, caused by triggers (reported by Nobuo Danjou) X-Git-Tag: 0.50_07~1 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=8ab2c6ab8d7a229539e3464298c59a8823a18cec;p=gitmo%2FMouse.git Fix a possible panic, caused by triggers (reported by Nobuo Danjou) --- diff --git a/t/001_mouse/007-attributes.t b/t/001_mouse/007-attributes.t index 4dba52a..39667c1 100644 --- a/t/001_mouse/007-attributes.t +++ b/t/001_mouse/007-attributes.t @@ -1,7 +1,7 @@ #!/usr/bin/env perl use strict; use warnings; -use Test::More tests => 21; +use Test::More; use Test::Exception; use Test::Mouse; @@ -63,6 +63,9 @@ $object->rw_attr(100); is $object->rw_attr, 100; is $object->read_attr, 100; +is $object->write_attr("piyo"), "piyo"; +is $object->rw_attr("yopi"), "yopi"; + dies_ok { Class->rw_attr(); }; @@ -72,3 +75,5 @@ dies_ok { dies_ok { Class->write_attr(42); }; + +done_testing; diff --git a/t/001_mouse/011-lazy.t b/t/001_mouse/011-lazy.t index 2d87867..df584b1 100644 --- a/t/001_mouse/011-lazy.t +++ b/t/001_mouse/011-lazy.t @@ -1,7 +1,7 @@ #!/usr/bin/env perl use strict; use warnings; -use Test::More tests => 16; +use Test::More; use Test::Exception; my $lazy_run = 0; @@ -48,6 +48,9 @@ is($lazy_run, 1, "lazy coderef invoked once"); is($object->lazy_value, "newp", "got new value"); is($lazy_run, 1, "lazy coderef invoked once"); +is($object->lazy(42), 42); +is($object->lazy_value(3.14), 3.14); + my $object2 = Class->new(lazy => 'very', lazy_value => "heh"); is($lazy_run, 1, "lazy attribute not initialized when an argument is passed to the constructor"); @@ -55,3 +58,4 @@ is($object2->lazy, 'very', 'value from the constructor'); is($object2->lazy_value, 'heh', 'value from the constructor'); is($lazy_run, 1, "lazy coderef not invoked, we already have a value"); +done_testing; diff --git a/t/001_mouse/016-trigger.t b/t/001_mouse/016-trigger.t index 2f3a666..edac65e 100644 --- a/t/001_mouse/016-trigger.t +++ b/t/001_mouse/016-trigger.t @@ -1,7 +1,7 @@ #!/usr/bin/env perl use strict; use warnings; -use Test::More tests => 11; +use Test::More; use Test::Exception; my @trigger; @@ -19,6 +19,22 @@ do { }, ); + has foobar => ( # from Net::Google::DataAPI + is => 'rw', + isa => 'Str', + + lazy => 1, + trigger => sub{ $_[0]->update }, + default => sub{ 'piyo' }, + + clearer => 'clear_foobar', + ); + + sub update { + my($self) = @_; + $self->clear_foobar; + } + ::lives_ok { has not_error => ( is => 'ro', @@ -46,7 +62,12 @@ is($object->attr(50), 50, "setting the value"); is(@trigger, 1, "trigger was called on read"); is_deeply([splice @trigger], [[$object, 50, undef]], "correct arguments to trigger in the accessor"); +is($object->foobar, 'piyo'); +is($object->foobar('baz'), 'baz'); +is($object->foobar, 'piyo', "call clearer in triggers"); + my $object2 = Class->new(attr => 100); is(@trigger, 1, "trigger was called on new with the attribute specified"); is_deeply([splice @trigger], [[$object2, 100, undef]], "correct arguments to trigger in the constructor"); +done_testing; diff --git a/xs-src/MouseAccessor.xs b/xs-src/MouseAccessor.xs index fd4cf68..a16b2ae 100644 --- a/xs-src/MouseAccessor.xs +++ b/xs-src/MouseAccessor.xs @@ -144,6 +144,12 @@ mouse_attr_set(pTHX_ SV* const self, MAGIC* const mg, SV* value){ SV* const trigger = mcall0s(MOUSE_mg_attribute(mg), "trigger"); dSP; + /* NOTE: triggers can remove value, so + value must be copied here, + revealed by Net::Google::DataAPI (DANJOU). + */ + value = sv_mortalcopy(value); + PUSHMARK(SP); EXTEND(SP, 2); PUSHs(self); @@ -152,6 +158,8 @@ mouse_attr_set(pTHX_ SV* const self, MAGIC* const mg, SV* value){ PUTBACK; call_sv(trigger, G_VOID | G_DISCARD); /* need not SPAGAIN */ + + assert(SvTYPE(value) != SVTYPEMASK); } PUSH_VALUE(value, flags);