From: Jesse Luehrs Date: Thu, 23 Sep 2010 07:31:52 +0000 (-0500) Subject: give CMOP::Object a real meta method, and simplify some things X-Git-Tag: 1.09~17 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=28a82ddae9835be042c809198885582ba32b9583;p=gitmo%2FClass-MOP.git give CMOP::Object a real meta method, and simplify some things --- diff --git a/lib/Class/MOP.pm b/lib/Class/MOP.pm index 3cbe4c4..fabda7d 100644 --- a/lib/Class/MOP.pm +++ b/lib/Class/MOP.pm @@ -664,6 +664,12 @@ Class::MOP::Instance->meta->add_attribute( ), ); +## -------------------------------------------------------- +## Class::MOP::Object + +# need to replace the meta method there with a real meta method object +Class::MOP::Object->meta->_add_meta_method; + require Class::MOP::Deprecated unless our $no_deprecated; # we need the meta instance of the meta instance to be created now, in order diff --git a/lib/Class/MOP/Class.pm b/lib/Class/MOP/Class.pm index a1fc198..334c57f 100644 --- a/lib/Class/MOP/Class.pm +++ b/lib/Class/MOP/Class.pm @@ -127,6 +127,9 @@ sub _real_ref_name { sub _add_meta_method { my $self = shift; + my $existing_method = $self->find_method_by_name('meta'); + return if $existing_method + && $existing_method->isa('Class::MOP::Method::Meta'); $self->add_method( 'meta' => Class::MOP::Method::Meta->wrap( name => 'meta', diff --git a/lib/Class/MOP/Method/Meta.pm b/lib/Class/MOP/Method/Meta.pm index 1a14fe4..e339832 100644 --- a/lib/Class/MOP/Method/Meta.pm +++ b/lib/Class/MOP/Method/Meta.pm @@ -15,24 +15,25 @@ use constant DEBUG_NO_META => $ENV{DEBUG_NO_META}; use base 'Class::MOP::Method'; +sub _is_caller_mop_internal { + my $self = shift; + my ($caller) = @_; + return $caller =~ /^(?:Class::MOP|metaclass)(?:::|$)/; +} + sub _generate_meta_method { my $method_self = shift; my $metaclass = shift; sub { # this will be compiled out if the env var wasn't set if (DEBUG_NO_META) { - my ($self) = @_; - # it's okay if we installed a meta method in a subclass of a class - # with a legitimate meta method (we'll still die if we install a - # meta method in a subclass of a class we installed a meta method - # in, since this function is itself defined in Class::MOP) - #if (my $meta = try { $self->SUPER::meta }) { - #return $meta if $meta->isa('Class::MOP::Class'); - #} - # it's okay if the test itself calls ->meta, we only care about if - # the mop internals call ->meta confess "'meta' method called by MOP internals" - if caller =~ /^(?:Class::MOP|metaclass)(?:::|$)/; + # it's okay to call meta methods on metaclasses, since we + # explicitly ask for them + if !$_[0]->isa('Class::MOP::Object') + # it's okay if the test itself calls ->meta, we only care about + # if the mop internals call ->meta + && $method_self->_is_caller_mop_internal(scalar caller); } # we must re-initialize so that it # works as expected in subclasses, diff --git a/t/303_RT_39001_fix.t b/t/303_RT_39001_fix.t index 51e355e..210d715 100644 --- a/t/303_RT_39001_fix.t +++ b/t/303_RT_39001_fix.t @@ -25,6 +25,10 @@ throws_ok { use metaclass; } +# reset @ISA, so that calling methods like ->isa won't die (->meta does this +# if DEBUG_NO_META is set) +@Foo::ISA = (); + lives_ok { Foo->meta->superclasses('Bar'); } "regular subclass";