Merge branch 'master' into renames-and-deprecations
Dave Rolsky [Thu, 26 Mar 2009 21:33:35 +0000 (16:33 -0500)]
Conflicts:

t/010_self_introspection.t
t/073_make_mutable.t

24 files changed:
Changes
Makefile.PL
README
lib/Class/MOP.pm
lib/Class/MOP/Attribute.pm
lib/Class/MOP/Class.pm
lib/Class/MOP/Immutable.pm
lib/Class/MOP/Instance.pm
lib/Class/MOP/Method.pm
lib/Class/MOP/Method/Accessor.pm
lib/Class/MOP/Method/Constructor.pm
lib/Class/MOP/Method/Generated.pm
lib/Class/MOP/Method/Wrapped.pm
lib/Class/MOP/Module.pm
lib/Class/MOP/Object.pm
lib/Class/MOP/Package.pm
lib/metaclass.pm
mop.h
t/010_self_introspection.t
t/070_immutable_metaclass.t
t/071_immutable_w_custom_metaclass.t
t/073_make_mutable.t
t/086_rebless_instance_away.t [new file with mode: 0644]
xt/pod_coverage.t

diff --git a/Changes b/Changes
index bb68d73..37bd252 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,8 +1,27 @@
 Revision history for Perl extension Class-MOP.
 
+0.78_02 Thu, March 26, 2009
+    * Class::MOP::Class
+    * Class::MOP::Immutable
+      - A big backwards-incompatible refactoring of the Immutable API,
+        and the make_immutable/make_mutable pieces of the Class
+        API. The core __PACKAGE__->meta->make_immutable API remains
+        the same, however, so this should only affect the most
+        guts-digging code.
+
+    * XS code
+      - The XS code used a macro, XSPROTO, that's only in 5.10.x. This
+        has been fixed to be backwards compatible with 5.8.x.
+
+    * Class::MOP::Class
+      - Add a hook for rebless_instance_away (Sartak)
+      - Use blessed instead of ref to get an instance's class name
+        in rebless_instance. (Sartak)
+
 0.78_01 Wed, March 18, 2009
     * Class::MOP::*
-      - Revised and reorganized all of the API documentation.
+      - Revised and reorganized all of the API documentation. All
+        classes now have (more or less) complete API documentation.
 
     * Class::MOP::Class
     * Class::MOP::Instance
index 9f3a285..6cc4507 100644 (file)
@@ -62,7 +62,7 @@ WriteAll();
 # before a release.
 sub check_conflicts {
     my %conflicts = (
-        'Moose' => '0.71',
+        'Moose' => '0.72',
     );
 
     my $found = 0;
diff --git a/README b/README
index be902b8..a27f42d 100644 (file)
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-Class::MOP version 0.78_01
+Class::MOP version 0.78_02
 ===========================
 
 See the individual module documentation for more information
index 8b0bd26..3385712 100644 (file)
@@ -32,7 +32,7 @@ BEGIN {
     *check_package_cache_flag = \&mro::get_pkg_gen;
 }
 
-our $VERSION   = '0.78_01';
+our $VERSION   = '0.78_02';
 our $XS_VERSION = $VERSION;
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';    
@@ -329,6 +329,17 @@ Class::MOP::Class->meta->add_attribute(
     ))
 );
 
+Class::MOP::Class->meta->add_attribute(
+    Class::MOP::Attribute->new('immutable_transformer' => (
+        reader   => {
+            'immutable_transformer' => \&Class::MOP::Class::immutable_transformer
+        },
+        writer   => {
+            '_set_immutable_transformer' => \&Class::MOP::Class::_set_immutable_transformer
+        },
+    ))
+);
+
 # NOTE:
 # we don't actually need to tie the knot with
 # Class::MOP::Class here, it is actually handled
index 7375bb9..9340f35 100644 (file)
@@ -9,7 +9,7 @@ use Class::MOP::Method::Accessor;
 use Carp         'confess';
 use Scalar::Util 'blessed', 'weaken';
 
-our $VERSION   = '0.78_01';
+our $VERSION   = '0.78_02';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index 97f7517..ef1d1a1 100644 (file)
@@ -11,7 +11,7 @@ use Class::MOP::Method::Wrapped;
 use Carp         'confess';
 use Scalar::Util 'blessed', 'weaken';
 
-our $VERSION   = '0.78_01';
+our $VERSION   = '0.78_02';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
@@ -79,8 +79,7 @@ sub _construct_class_instance {
     # now create the metaclass
     my $meta;
     if ($class eq 'Class::MOP::Class') {
-        no strict 'refs';
-        $meta = $class->_new($options)
+        $meta = $class->_new($options);
     }
     else {
         # NOTE:
@@ -437,9 +436,11 @@ sub rebless_instance {
         $old_metaclass = $instance->meta;
     }
     else {
-        $old_metaclass = $self->initialize(ref($instance));
+        $old_metaclass = $self->initialize(blessed($instance));
     }
 
+    $old_metaclass->rebless_instance_away($instance, $self, %params);
+
     my $meta_instance = $self->get_meta_instance();
 
     $self->name->isa($old_metaclass->name)
@@ -468,6 +469,10 @@ sub rebless_instance {
     $instance;
 }
 
+sub rebless_instance_away {
+    # this intentionally does nothing, it is just a hook
+}
+
 # Inheritance
 
 sub superclasses {
@@ -1000,108 +1005,56 @@ sub is_pristine {
 sub is_mutable   { 1 }
 sub is_immutable { 0 }
 
-# NOTE:
-# Why I changed this (groditi)
-#  - One Metaclass may have many Classes through many Metaclass instances
-#  - One Metaclass should only have one Immutable Transformer instance
-#  - Each Class may have different Immutabilizing options
-#  - Therefore each Metaclass instance may have different Immutabilizing options
-#  - We need to store one Immutable Transformer instance per Metaclass
-#  - We need to store one set of Immutable Transformer options per Class
-#  - Upon make_mutable we may delete the Immutabilizing options
-#  - We could clean the immutable Transformer instance when there is no more
-#      immutable Classes of that type, but we can also keep it in case
-#      another class with this same Metaclass becomes immutable. It is a case
-#      of trading of storing an instance to avoid unnecessary instantiations of
-#      Immutable Transformers. You may view this as a memory leak, however
-#      Because we have few Metaclasses, in practice it seems acceptable
-#  - To allow Immutable Transformers instances to be cleaned up we could weaken
-#      the reference stored in  $IMMUTABLE_TRANSFORMERS{$class} and ||= should DWIM
-
-{
-
-    my %IMMUTABLE_TRANSFORMERS;
-    my %IMMUTABLE_OPTIONS;
-
-    sub get_immutable_options {
-        my $self = shift;
-        return if $self->is_mutable;
-        confess "unable to find immutabilizing options"
-            unless exists $IMMUTABLE_OPTIONS{$self->name};
-        my %options = %{$IMMUTABLE_OPTIONS{$self->name}};
-        delete $options{IMMUTABLE_TRANSFORMER};
-        return \%options;
-    }
-
-    sub get_immutable_transformer {
-        my $self = shift;
-        if( $self->is_mutable ){
-            return $IMMUTABLE_TRANSFORMERS{$self->name} ||= $self->create_immutable_transformer;
-        }
-        confess "unable to find transformer for immutable class"
-            unless exists $IMMUTABLE_OPTIONS{$self->name};
-        return $IMMUTABLE_OPTIONS{$self->name}->{IMMUTABLE_TRANSFORMER};
-    }
+sub immutable_transformer { $_[0]->{immutable_transformer} }
+sub _set_immutable_transformer { $_[0]->{immutable_transformer} = $_[1] }
 
-    sub make_immutable {
-        my $self = shift;
-        my %options = @_;
+sub make_immutable {
+    my $self = shift;
 
-        my $transformer = $self->get_immutable_transformer;
-        $transformer->make_metaclass_immutable($self, \%options);
-        $IMMUTABLE_OPTIONS{$self->name} =
-            { %options,  IMMUTABLE_TRANSFORMER => $transformer };
+    return if $self->is_immutable;
 
-        if( exists $options{debug} && $options{debug} ){
-            print STDERR "# of Metaclass options:      ", keys %IMMUTABLE_OPTIONS;
-            print STDERR "# of Immutable transformers: ", keys %IMMUTABLE_TRANSFORMERS;
-        }
+    my $transformer = $self->immutable_transformer
+        || $self->_make_immutable_transformer(@_);
 
-        1;
-    }
+    $self->_set_immutable_transformer($transformer);
 
-    sub make_mutable{
-        my $self = shift;
-        return if $self->is_mutable;
-        my $options = delete $IMMUTABLE_OPTIONS{$self->name};
-        confess "unable to find immutabilizing options" unless ref $options;
-        my $transformer = delete $options->{IMMUTABLE_TRANSFORMER};
-        $transformer->make_metaclass_mutable($self, $options);
-        1;
-    }
+    $transformer->make_metaclass_immutable;
 }
 
-sub create_immutable_transformer {
-    my $self = shift;
-    my $class = Class::MOP::Immutable->new($self, {
+{
+    my %Default_Immutable_Options = (
         read_only   => [qw/superclasses/],
-        cannot_call => [qw/
-           add_method
-           alias_method
-           remove_method
-           add_attribute
-           remove_attribute
-           remove_package_symbol
-        /],
-        memoize     => {
-           class_precedence_list             => 'ARRAY',
-           linearized_isa                    => 'ARRAY', # FIXME perl 5.10 memoizes this on its own, no need?
-           get_all_methods                   => 'ARRAY',
-           get_all_method_names              => 'ARRAY',
-           #get_all_attributes               => 'ARRAY', # it's an alias, no need, but maybe in the future
-           compute_all_applicable_attributes => 'ARRAY',
-           get_meta_instance                 => 'SCALAR',
-           get_method_map                    => 'SCALAR',
+        cannot_call => [
+            qw(
+                add_method
+                alias_method
+                remove_method
+                add_attribute
+                remove_attribute
+                remove_package_symbol
+                )
+        ],
+        memoize => {
+            class_precedence_list => 'ARRAY',
+            # FIXME perl 5.10 memoizes this on its own, no need?
+            linearized_isa                    => 'ARRAY',
+            get_all_methods                   => 'ARRAY',
+            get_all_method_names              => 'ARRAY',
+            compute_all_applicable_attributes => 'ARRAY',
+            get_meta_instance                 => 'SCALAR',
+            get_method_map                    => 'SCALAR',
         },
+
         # NOTE:
-        # this is ugly, but so are typeglobs, 
+        # this is ugly, but so are typeglobs,
         # so whattayahgonnadoboutit
         # - SL
-        wrapped => { 
+        wrapped => {
             add_package_symbol => sub {
                 my $original = shift;
-                confess "Cannot add package symbols to an immutable metaclass" 
-                    unless (caller(2))[3] eq 'Class::MOP::Package::get_package_symbol'; 
+                confess "Cannot add package symbols to an immutable metaclass"
+                    unless ( caller(2) )[3] eq
+                    'Class::MOP::Package::get_package_symbol';
 
                 # This is a workaround for a bug in 5.8.1 which thinks that
                 # goto $original->body
@@ -1110,8 +1063,29 @@ sub create_immutable_transformer {
                 goto $body;
             },
         },
-    });
-    return $class;
+    );
+
+    sub _default_immutable_transformer_options {
+        return %Default_Immutable_Options;
+    }
+}
+
+sub _make_immutable_transformer {
+    my $self = shift;
+
+    Class::MOP::Immutable->new(
+        $self,
+        $self->_default_immutable_transformer_options,
+        @_
+    );
+}
+
+sub make_mutable {
+    my $self = shift;
+
+    return if $self->is_mutable;
+
+    $self->immutable_transformer->make_metaclass_mutable;
 }
 
 1;
@@ -1292,6 +1266,12 @@ like constructor parameters and used to initialize the object's
 attributes. Any existing attributes that are already set will be
 overwritten.
 
+Before reblessing the instance, this method will call
+C<rebless_instance_away> on the instance's current metaclass. This method
+will be passed the instance, the new metaclass, and any parameters
+specified to C<rebless_instance>. By default, C<rebless_instance_away>
+does nothing; it is merely a hook.
+
 =item B<< $metaclass->new_object(%params) >>
 
 This method is used to create a new object of the metaclass's
@@ -1587,7 +1567,7 @@ documentation.
 
 Calling this method reverse the immutabilization transformation.
 
-=item B<< $metaclass->get_immutable_transformer >>
+=item B<< $metaclass->immutable_transformer >>
 
 If the class has been made immutable previously, this returns the
 L<Class::MOP::Immutable> object that was created to do the
index 076fbab..b050685 100644 (file)
@@ -9,7 +9,7 @@ use Class::MOP::Method::Constructor;
 use Carp         'confess';
 use Scalar::Util 'blessed';
 
-our $VERSION   = '0.78_01';
+our $VERSION   = '0.78_02';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
@@ -18,23 +18,21 @@ use base 'Class::MOP::Object';
 sub new {
     my ($class, @args) = @_;
 
-    my ( $metaclass, $options );
+    unshift @args, 'metaclass' if @args % 2 == 1;
 
-    if ( @args == 2 ) {
-        # compatibility args
-        ( $metaclass, $options ) = @args;
-    } else {
-        unshift @args, "metaclass" if @args % 2 == 1;
-
-        # default named args
-        my %options = @args;
-        $options = \%options;
-        $metaclass = $options{metaclass};
-    }
+    my %options = (
+        inline_accessors   => 1,
+        inline_constructor => 1,
+        inline_destructor  => 0,
+        constructor_name   => 'new',
+        constructor_class  => 'Class::MOP::Method::Constructor',
+        debug              => 0,
+        @args,
+    );
 
     my $self = $class->_new(
-        'metaclass'           => $metaclass,
-        'options'             => $options,
+        'metaclass'           => delete $options{metaclass},
+        'options'             => \%options,
         'immutable_metaclass' => undef,
         'inlined_constructor' => undef,
     );
@@ -52,188 +50,165 @@ sub _new {
 sub immutable_metaclass {
     my $self = shift;
 
-    $self->create_immutable_metaclass unless $self->{'immutable_metaclass'};
-
-    return $self->{'immutable_metaclass'};
+    return $self->{'immutable_metaclass'} ||= $self->_create_immutable_metaclass;
 }
 
 sub metaclass           { (shift)->{'metaclass'}           }
 sub options             { (shift)->{'options'}             }
 sub inlined_constructor { (shift)->{'inlined_constructor'} }
 
-sub create_immutable_metaclass {
+sub _create_immutable_metaclass {
     my $self = shift;
 
-    # NOTE:
-    # The immutable version of the
-    # metaclass is just a anon-class
-    # which shadows the methods
-    # appropriately
-    $self->{'immutable_metaclass'} = Class::MOP::Class->create_anon_class(
+    # NOTE: The immutable version of the metaclass is just a
+    # anon-class which shadows the methods appropriately
+    return Class::MOP::Class->create_anon_class(
         superclasses => [ blessed($self->metaclass) ],
-        methods      => $self->create_methods_for_immutable_metaclass,
+        methods      => $self->_create_methods_for_immutable_metaclass,
     );
 }
 
-
-my %DEFAULT_METHODS = (
-    # I don't really understand this, but removing it breaks tests (groditi)
-    meta => sub {
-        my $self = shift;
-        # if it is not blessed, then someone is asking
-        # for the meta of Class::MOP::Immutable
-        return Class::MOP::Class->initialize($self) unless blessed($self);
-        # otherwise, they are asking for the metaclass
-        # which has been made immutable, which is itself
-        # except in the cases where it is a metaclass itself
-        # that has been made immutable and for that we need 
-        # to dig a bit ...
-        if ($self->isa('Class::MOP::Class')) {
-            return $self->{'___original_class'}->meta;
-        }
-        else {
-            return $self;
-        }
-    },
-    is_mutable     => sub { 0  },
-    is_immutable   => sub { 1  },
-    make_immutable => sub { () },
-);
-
-# NOTE:
-# this will actually convert the
-# existing metaclass to an immutable
-# version of itself
 sub make_metaclass_immutable {
-    my ($self, $metaclass, $options) = @_;
-
-    my %options = (
-        inline_accessors   => 1,
-        inline_constructor => 1,
-        inline_destructor  => 0,
-        constructor_name   => 'new',
-        debug              => 0,
-        %$options,
-    );
+    my $self = shift;
 
-    %$options = %options; # FIXME who the hell is relying on this?!? tests fail =(
+    $self->_inline_accessors;
+    $self->_inline_constructor;
+    $self->_inline_destructor;
+    $self->_check_memoized_methods;
 
-    $self->_inline_accessors( $metaclass, \%options );
-    $self->_inline_constructor( $metaclass, \%options );
-    $self->_inline_destructor( $metaclass, \%options );
-    $self->_check_memoized_methods( $metaclass, \%options );
+    my $metaclass = $self->metaclass;
 
     $metaclass->{'___original_class'} = blessed($metaclass);
     bless $metaclass => $self->immutable_metaclass->name;
 }
 
 sub _inline_accessors {
-    my ( $self, $metaclass, $options ) = @_;
+    my $self = shift;
 
-    return unless $options->{inline_accessors};
+    return unless $self->options->{inline_accessors};
 
-    foreach my $attr_name ( $metaclass->get_attribute_list ) {
-        $metaclass->get_attribute($attr_name)->install_accessors(1);
+    foreach my $attr_name ( $self->metaclass->get_attribute_list ) {
+        $self->metaclass->get_attribute($attr_name)->install_accessors(1);
     }
 }
 
 sub _inline_constructor {
-    my ( $self, $metaclass, $options ) = @_;
+    my $self = shift;
 
-    return unless $options->{inline_constructor};
+    return unless $self->options->{inline_constructor};
 
     return
-        unless $options->{replace_constructor}
-            or !$metaclass->has_method( $options->{constructor_name} );
+        unless $self->options->{replace_constructor}
+            or !$self->metaclass->has_method(
+                $self->options->{constructor_name}
+            );
 
-    my $constructor_class = $options->{constructor_class}
-        || 'Class::MOP::Method::Constructor';
+    my $constructor_class = $self->options->{constructor_class};
 
     my $constructor = $constructor_class->new(
-        options      => $options,
-        metaclass    => $metaclass,
+        options      => $self->options,
+        metaclass    => $self->metaclass,
         is_inline    => 1,
-        package_name => $metaclass->name,
-        name         => $options->{constructor_name},
+        package_name => $self->metaclass->name,
+        name         => $self->options->{constructor_name},
     );
 
-    if ( $options->{replace_constructor} or $constructor->can_be_inlined ) {
-        $metaclass->add_method( $options->{constructor_name} => $constructor );
+    if (   $self->options->{replace_constructor}
+        or $constructor->can_be_inlined ) {
+        $self->metaclass->add_method(
+            $self->options->{constructor_name} => $constructor );
         $self->{inlined_constructor} = $constructor;
     }
 }
 
 sub _inline_destructor {
-    my ( $self, $metaclass, $options ) = @_;
+    my $self = shift;
 
-    return unless $options->{inline_destructor};
+    return unless $self->options->{inline_destructor};
 
-    ( exists $options->{destructor_class} )
+    ( exists $self->options->{destructor_class} )
         || confess "The 'inline_destructor' option is present, but "
         . "no destructor class was specified";
 
-    my $destructor_class = $options->{destructor_class};
+    my $destructor_class = $self->options->{destructor_class};
 
-    return unless $destructor_class->is_needed($metaclass);
+    return unless $destructor_class->is_needed( $self->metaclass );
 
     my $destructor = $destructor_class->new(
-        options      => $options,
-        metaclass    => $metaclass,
-        package_name => $metaclass->name,
+        options      => $self->options,
+        metaclass    => $self->metaclass,
+        package_name => $self->metaclass->name,
         name         => 'DESTROY'
     );
 
-    return unless $destructor->is_needed;
-
-    $metaclass->add_method( 'DESTROY' => $destructor )
+    $self->metaclass->add_method( 'DESTROY' => $destructor );
 }
 
 sub _check_memoized_methods {
-    my ( $self, $metaclass, $options ) = @_;
+    my $self = shift;
 
     my $memoized_methods = $self->options->{memoize};
     foreach my $method_name ( keys %{$memoized_methods} ) {
         my $type = $memoized_methods->{$method_name};
 
-        ( $metaclass->can($method_name) )
+        ( $self->metaclass->can($method_name) )
             || confess "Could not find the method '$method_name' in "
-            . $metaclass->name;
+            . $self->metaclass->name;
     }
 }
+my %DEFAULT_METHODS = (
+    # I don't really understand this, but removing it breaks tests (groditi)
+    meta => sub {
+        my $self = shift;
+        # if it is not blessed, then someone is asking
+        # for the meta of Class::MOP::Immutable
+        return Class::MOP::Class->initialize($self) unless blessed($self);
+        # otherwise, they are asking for the metaclass
+        # which has been made immutable, which is itself
+        # except in the cases where it is a metaclass itself
+        # that has been made immutable and for that we need 
+        # to dig a bit ...
+        if ($self->isa('Class::MOP::Class')) {
+            return $self->{'___original_class'}->meta;
+        }
+        else {
+            return $self;
+        }
+    },
+    is_mutable     => sub { 0  },
+    is_immutable   => sub { 1  },
+    make_immutable => sub { () },
+);
 
-sub create_methods_for_immutable_metaclass {
+sub _create_methods_for_immutable_metaclass {
     my $self = shift;
 
-    my %methods   = %DEFAULT_METHODS;
     my $metaclass = $self->metaclass;
     my $meta      = $metaclass->meta;
 
-    $methods{get_mutable_metaclass_name}
-        = sub { (shift)->{'___original_class'} };
-
-    $methods{immutable_transformer} = sub {$self};
-
     return {
         %DEFAULT_METHODS,
-        $self->_make_read_only_methods( $metaclass, $meta ),
-        $self->_make_uncallable_methods( $metaclass, $meta ),
-        $self->_make_memoized_methods( $metaclass, $meta ),
-        $self->_make_wrapped_methods( $metaclass, $meta ),
+        $self->_make_read_only_methods,
+        $self->_make_uncallable_methods,
+        $self->_make_memoized_methods,
+        $self->_make_wrapped_methods,
         get_mutable_metaclass_name => sub { (shift)->{'___original_class'} },
         immutable_transformer      => sub {$self},
     };
 }
 
 sub _make_read_only_methods {
-    my ( $self, $metaclass, $meta ) = @_;
+    my $self = shift;
+
+    my $metameta = $self->metaclass->meta;
 
     my %methods;
     foreach my $read_only_method ( @{ $self->options->{read_only} } ) {
-        my $method = $meta->find_method_by_name($read_only_method);
+        my $method = $metameta->find_method_by_name($read_only_method);
 
         ( defined $method )
             || confess "Could not find the method '$read_only_method' in "
-            . $metaclass->name;
+            . $self->metaclass->name;
 
         $methods{$read_only_method} = sub {
             confess "This method is read-only" if scalar @_ > 1;
@@ -245,7 +220,7 @@ sub _make_read_only_methods {
 }
 
 sub _make_uncallable_methods {
-    my ( $self, $metaclass, $meta ) = @_;
+    my $self = shift;
 
     my %methods;
     foreach my $cannot_call_method ( @{ $self->options->{cannot_call} } ) {
@@ -259,15 +234,17 @@ sub _make_uncallable_methods {
 }
 
 sub _make_memoized_methods {
-    my ( $self, $metaclass, $meta ) = @_;
+    my $self = shift;
 
     my %methods;
 
+    my $metameta = $self->metaclass->meta;
+
     my $memoized_methods = $self->options->{memoize};
     foreach my $method_name ( keys %{$memoized_methods} ) {
         my $type   = $memoized_methods->{$method_name};
         my $key    = '___' . $method_name;
-        my $method = $meta->find_method_by_name($method_name);
+        my $method = $metameta->find_method_by_name($method_name);
 
         if ( $type eq 'ARRAY' ) {
             $methods{$method_name} = sub {
@@ -296,18 +273,20 @@ sub _make_memoized_methods {
 }
 
 sub _make_wrapped_methods {
-    my ( $self, $metaclass, $meta ) = @_;
+    my $self = shift;
 
     my %methods;
 
     my $wrapped_methods = $self->options->{wrapped};
 
+    my $metameta = $self->metaclass->meta;
+
     foreach my $method_name ( keys %{$wrapped_methods} ) {
-        my $method = $meta->find_method_by_name($method_name);
+        my $method = $metameta->find_method_by_name($method_name);
 
         ( defined $method )
             || confess "Could not find the method '$method_name' in "
-            . $metaclass->name;
+            . $self->metaclass->name;
 
         my $wrapper = $wrapped_methods->{$method_name};
 
@@ -318,28 +297,31 @@ sub _make_wrapped_methods {
 }
 
 sub make_metaclass_mutable {
-    my ($self, $immutable, $options) = @_;
+    my $self = shift;
 
-    my %options = %$options;
+    my $metaclass = $self->metaclass;
 
-    my $original_class = $immutable->get_mutable_metaclass_name;
-    delete $immutable->{'___original_class'} ;
-    bless $immutable => $original_class;
+    my $original_class = $metaclass->get_mutable_metaclass_name;
+    delete $metaclass->{'___original_class'};
+    bless $metaclass => $original_class;
 
     my $memoized_methods = $self->options->{memoize};
-    foreach my $method_name (keys %{$memoized_methods}) {
+    foreach my $method_name ( keys %{$memoized_methods} ) {
         my $type = $memoized_methods->{$method_name};
 
-        ($immutable->can($method_name))
-          || confess "Could not find the method '$method_name' in " . $immutable->name;
-        if ($type eq 'SCALAR' || $type eq 'ARRAY' ||  $type eq 'HASH' ) {
-            delete $immutable->{'___' . $method_name};
+        ( $metaclass->can($method_name) )
+            || confess "Could not find the method '$method_name' in "
+            . $metaclass->name;
+        if ( $type eq 'SCALAR' || $type eq 'ARRAY' || $type eq 'HASH' ) {
+            delete $metaclass->{ '___' . $method_name };
         }
     }
 
-    if ($options{inline_destructor} && $immutable->has_method('DESTROY')) {
-        $immutable->remove_method('DESTROY')
-          if blessed($immutable->get_method('DESTROY')) eq $options{destructor_class};
+    if (   $self->options->{inline_destructor}
+        && $metaclass->has_method('DESTROY') ) {
+        $metaclass->remove_method('DESTROY')
+            if blessed( $metaclass->get_method('DESTROY') ) eq
+                $self->options->{destructor_class};
     }
 
     # NOTE:
@@ -359,11 +341,17 @@ sub make_metaclass_mutable {
     # 14:26 <@stevan> the only user of ::Method::Constructor is immutable
     # 14:27 <@stevan> if someone uses it outside of immutable,.. they are either: mst or groditi
     # 14:27 <@stevan> so I am not worried
-    if ($options{inline_constructor}  && $immutable->has_method($options{constructor_name})) {
-        my $constructor_class = $options{constructor_class} || 'Class::MOP::Method::Constructor';
-
-        if ( blessed($immutable->get_method($options{constructor_name})) eq $constructor_class ) {
-            $immutable->remove_method( $options{constructor_name}  );
+    if (   $self->options->{inline_constructor}
+        && $metaclass->has_method( $self->options->{constructor_name} ) ) {
+        my $constructor_class = $self->options->{constructor_class}
+            || 'Class::MOP::Method::Constructor';
+
+        if (
+            blessed(
+                $metaclass->get_method( $self->options->{constructor_name} )
+            ) eq $constructor_class
+            ) {
+            $metaclass->remove_method( $self->options->{constructor_name} );
             $self->{inlined_constructor} = undef;
         }
     }
@@ -402,7 +390,7 @@ Class::MOP::Immutable - A class to transform Class::MOP::Class metaclasses
         }
     });
 
-    $immutable_metaclass->make_metaclass_immutable(@_)
+    $immutable_metaclass->make_metaclass_immutable;
 
 =head1 DESCRIPTION
 
@@ -512,6 +500,14 @@ transformation process.
 If the constructor was inlined, this returns the constructor method
 object that was created to do this.
 
+=item B<< $transformer->make_metaclass_immutable >>
+
+Makes the transformer's metaclass immutable.
+
+=item B<< $transformer->make_metaclass_mutable >>
+
+Makes the transformer's metaclass mutable.
+
 =back
 
 =head1 AUTHORS
index ed4afa4..546ffbf 100644 (file)
@@ -6,7 +6,7 @@ use warnings;
 
 use Scalar::Util 'weaken', 'blessed';
 
-our $VERSION   = '0.78_01';
+our $VERSION   = '0.78_02';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index ad9bd52..836273b 100644 (file)
@@ -7,7 +7,7 @@ use warnings;
 use Carp         'confess';
 use Scalar::Util 'weaken';
 
-our $VERSION   = '0.78_01';
+our $VERSION   = '0.78_02';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index 4df2cf1..6e40217 100644 (file)
@@ -7,7 +7,7 @@ use warnings;
 use Carp         'confess';
 use Scalar::Util 'blessed', 'weaken';
 
-our $VERSION   = '0.78_01';
+our $VERSION   = '0.78_02';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index c4aadff..7f0fe51 100644 (file)
@@ -7,7 +7,7 @@ use warnings;
 use Carp         'confess';
 use Scalar::Util 'blessed', 'weaken', 'looks_like_number';
 
-our $VERSION   = '0.78_01';
+our $VERSION   = '0.78_02';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
@@ -264,11 +264,6 @@ inlined.
 
 This returns the L<Class::MOP::Class> object for the method.
 
-=item B<< $metamethod->is_inline >>
-
-Returns a boolean indicating whether or not the constructor is
-inlined.
-
 =item B<< $metamethod->can_be_inlined >>
 
 This method always returns true in this class. It exists so that
index 203de2d..9c00836 100644 (file)
@@ -6,7 +6,7 @@ use warnings;
 
 use Carp 'confess';
 
-our $VERSION   = '0.78_01';
+our $VERSION   = '0.78_02';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index 3a3780d..0568a01 100644 (file)
@@ -7,7 +7,7 @@ use warnings;
 use Carp         'confess';
 use Scalar::Util 'blessed';
 
-our $VERSION   = '0.78_01';
+our $VERSION   = '0.78_02';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index eef59d7..35294b1 100644 (file)
@@ -7,7 +7,7 @@ use warnings;
 use Carp         'confess';
 use Scalar::Util 'blessed';
 
-our $VERSION   = '0.78_01';
+our $VERSION   = '0.78_02';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index 2c837ba..b6b0445 100644 (file)
@@ -6,7 +6,7 @@ use warnings;
 
 use Scalar::Util 'blessed';
 
-our $VERSION   = '0.78_01';
+our $VERSION   = '0.78_02';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index 3c43210..4a70e89 100644 (file)
@@ -8,7 +8,7 @@ use B;
 use Scalar::Util 'blessed';
 use Carp         'confess';
 
-our $VERSION   = '0.78_01';
+our $VERSION   = '0.78_02';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index b289049..b3f66b8 100644 (file)
@@ -7,7 +7,7 @@ use warnings;
 use Carp         'confess';
 use Scalar::Util 'blessed';
 
-our $VERSION   = '0.78_01';
+our $VERSION   = '0.78_02';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
diff --git a/mop.h b/mop.h
index 7566652..288c8ad 100644 (file)
--- a/mop.h
+++ b/mop.h
 
 #define MOP_CALL_BOOT(name)  mop_call_xs(aTHX_ name, cv, mark);
 
+#ifndef XSPROTO
+#define XSPROTO(name) XS(name)
+#endif
+
 void mop_call_xs (pTHX_ XSPROTO(subaddr), CV *cv, SV **mark);
 
 typedef enum {
index 9b63ea6..6fc43ec 100644 (file)
@@ -1,7 +1,7 @@
 use strict;
 use warnings;
 
-use Test::More tests => 254;
+use Test::More tests => 260;
 use Test::Exception;
 
 use Class::MOP;
@@ -63,7 +63,7 @@ my @class_mop_class_methods = qw(
     construct_instance
     construct_class_instance _construct_class_instance
     clone_instance _clone_instance
-    rebless_instance
+    rebless_instance rebless_instance_away
     check_metaclass_compatibility _check_metaclass_compatibility
 
     add_meta_instance_dependencies remove_meta_instance_dependencies update_meta_instance_dependencies
@@ -83,8 +83,10 @@ my @class_mop_class_methods = qw(
     has_attribute get_attribute add_attribute remove_attribute
     get_attribute_list get_attribute_map get_all_attributes compute_all_applicable_attributes find_attribute_by_name
 
-    is_mutable is_immutable make_mutable make_immutable create_immutable_transformer
-    get_immutable_options get_immutable_transformer
+    is_mutable is_immutable make_mutable make_immutable
+    immutable_transformer _set_immutable_transformer
+    _make_immutable_transformer
+    _default_immutable_transformer_options
 
     DESTROY
 );
@@ -162,7 +164,8 @@ my @class_mop_class_attributes = (
     'attribute_metaclass',
     'method_metaclass',
     'wrapped_method_metaclass',
-    'instance_metaclass'
+    'instance_metaclass',
+    'immutable_transformer',
 );
 
 # check class
index 3814526..4ec34fc 100644 (file)
@@ -1,7 +1,7 @@
 use strict;
 use warnings;
 
-use Test::More tests => 86;
+use Test::More tests => 80;
 use Test::Exception;
 
 use Class::MOP;
@@ -37,223 +37,257 @@ use Class::MOP;
 }
 
 {
-  my $meta = Foo->meta;
-
-  my $transformer;
-  lives_ok{ $transformer = $meta->create_immutable_transformer }
-    "Created immutable transformer";
-  isa_ok($transformer, 'Class::MOP::Immutable', '... transformer isa Class::MOP::Immutable');
-  my $methods = $transformer->create_methods_for_immutable_metaclass;
-
-  my $immutable_metaclass = $transformer->immutable_metaclass;
-  is($transformer->metaclass, $meta,      '... transformer has correct metaclass');
-  ok(!$transformer->inlined_constructor,  '... transformer says it did not inline the constructor');
-  ok($immutable_metaclass->is_anon_class, '... immutable_metaclass is an anonymous class');
-
-  #I don't understand why i need to ->meta here...
-  my $obj = $immutable_metaclass->name;
-  ok(!$obj->is_mutable,     '... immutable_metaclass is not mutable');
-  ok($obj->is_immutable,    '... immutable_metaclass is immutable');
-  ok(!$obj->make_immutable, '... immutable_metaclass make_mutable is noop');
-  is($obj->meta, $immutable_metaclass, '... immutable_metaclass meta hack works');
-
-  is_deeply(
-            [ $immutable_metaclass->superclasses ],
-            [ Scalar::Util::blessed($meta) ],
-            '... immutable_metaclass superclasses are correct'
-           );
-  ok($immutable_metaclass->has_method('get_mutable_metaclass_name'),
-     'immutable metaclass has get_mutable_metaclass_name method');
+    my $meta = Foo->meta;
+    my $original_metaclass_name = ref $meta;
+
+    $meta->make_immutable;
+
+    my $transformer = $meta->immutable_transformer;
+    isa_ok( $transformer, 'Class::MOP::Immutable',
+        '... transformer isa Class::MOP::Immutable' );
+
+    my $immutable_metaclass = $transformer->immutable_metaclass;
+    is( $transformer->metaclass, $meta,
+        '... transformer has correct metaclass' );
+    ok( $transformer->inlined_constructor,
+        '... transformer says it did inline the constructor' );
+    ok( $immutable_metaclass->is_anon_class,
+        '... immutable_metaclass is an anonymous class' );
+
+    #I don't understand why i need to ->meta here...
+    my $obj = $immutable_metaclass->name;
+    ok( !$obj->is_mutable,  '... immutable_metaclass is not mutable' );
+    ok( $obj->is_immutable, '... immutable_metaclass is immutable' );
+    ok( !$obj->make_immutable,
+        '... immutable_metaclass make_mutable is noop' );
+    is( $obj->meta, $immutable_metaclass,
+        '... immutable_metaclass meta hack works' );
+
+    is_deeply(
+        [ $immutable_metaclass->superclasses ],
+        [ $original_metaclass_name ],
+        '... immutable_metaclass superclasses are correct'
+    );
+    ok(
+        $immutable_metaclass->has_method('get_mutable_metaclass_name'),
+        'immutable metaclass has get_mutable_metaclass_name method'
+    );
 
 }
 
 {
     my $meta = Foo->meta;
-    is($meta->name, 'Foo', '... checking the Foo metaclass');
+    is( $meta->name, 'Foo', '... checking the Foo metaclass' );
 
-    ok($meta->is_mutable, '... our class is mutable');
-    ok(!$meta->is_immutable, '... our class is not immutable');
+    ok( !$meta->is_mutable,    '... our class is not mutable' );
+    ok( $meta->is_immutable, '... our class is immutable' );
 
-    my $transformer = $meta->get_immutable_transformer;
+    my $transformer = $meta->immutable_transformer;
 
-    lives_ok {
-        $meta->make_immutable();
-    } '... changed Foo to be immutable';
+    is( $transformer, $meta->immutable_transformer,
+        '... immutable transformer cache works' );
 
-    ok($transformer->inlined_constructor,  '... transformer says it did inline the constructor');
-    is($transformer, $meta->get_immutable_transformer, '... immutable transformer cache works');
-    ok(!$meta->make_immutable, '... make immutable now returns nothing');
+    isa_ok( $meta, 'Class::MOP::Class' );
 
-    ok(!$meta->is_mutable, '... our class is no longer mutable');
-    ok($meta->is_immutable, '... our class is now immutable');
-
-    isa_ok($meta, 'Class::MOP::Class');
-
-    dies_ok { $meta->add_method()    } '... exception thrown as expected';
-    dies_ok { $meta->alias_method()  } '... exception thrown as expected';
+    dies_ok { $meta->add_method() } '... exception thrown as expected';
+    dies_ok { $meta->alias_method() } '... exception thrown as expected';
     dies_ok { $meta->remove_method() } '... exception thrown as expected';
 
-    dies_ok { $meta->add_attribute()    } '... exception thrown as expected';
+    dies_ok { $meta->add_attribute() } '... exception thrown as expected';
     dies_ok { $meta->remove_attribute() } '... exception thrown as expected';
 
-    dies_ok { $meta->add_package_symbol()    } '... exception thrown as expected';
-    dies_ok { $meta->remove_package_symbol() } '... exception thrown as expected';
+    dies_ok { $meta->add_package_symbol() }
+    '... exception thrown as expected';
+    dies_ok { $meta->remove_package_symbol() }
+    '... exception thrown as expected';
 
-    lives_ok { $meta->identifier() } '... no exception for get_package_symbol special case';
+    lives_ok { $meta->identifier() }
+    '... no exception for get_package_symbol special case';
 
     my @supers;
     lives_ok {
         @supers = $meta->superclasses;
-    } '... got the superclasses okay';
+    }
+    '... got the superclasses okay';
 
-    dies_ok { $meta->superclasses([ 'UNIVERSAL' ]) } '... but could not set the superclasses okay';
+    dies_ok { $meta->superclasses( ['UNIVERSAL'] ) }
+    '... but could not set the superclasses okay';
 
     my $meta_instance;
     lives_ok {
         $meta_instance = $meta->get_meta_instance;
-    } '... got the meta instance okay';
-    isa_ok($meta_instance, 'Class::MOP::Instance');
-    is($meta_instance, $meta->get_meta_instance, '... and we know it is cached');
+    }
+    '... got the meta instance okay';
+    isa_ok( $meta_instance, 'Class::MOP::Instance' );
+    is( $meta_instance, $meta->get_meta_instance,
+        '... and we know it is cached' );
 
     my @cpl;
     lives_ok {
         @cpl = $meta->class_precedence_list;
-    } '... got the class precedence list okay';
+    }
+    '... got the class precedence list okay';
     is_deeply(
-    \@cpl,
-    [ 'Foo' ],
-    '... we just have ourselves in the class precedence list');
+        \@cpl,
+        ['Foo'],
+        '... we just have ourselves in the class precedence list'
+    );
 
     my @attributes;
     lives_ok {
         @attributes = $meta->compute_all_applicable_attributes;
-    } '... got the attribute list okay';
+    }
+    '... got the attribute list okay';
     is_deeply(
-    \@attributes,
-    [ $meta->get_attribute('bar') ],
-    '... got the right list of attributes');
+        \@attributes,
+        [ $meta->get_attribute('bar') ],
+        '... got the right list of attributes'
+    );
 }
 
 {
     my $meta = Bar->meta;
-    is($meta->name, 'Bar', '... checking the Bar metaclass');
+    is( $meta->name, 'Bar', '... checking the Bar metaclass' );
 
-    ok($meta->is_mutable, '... our class is mutable');
-    ok(!$meta->is_immutable, '... our class is not immutable');
+    ok( $meta->is_mutable,    '... our class is mutable' );
+    ok( !$meta->is_immutable, '... our class is not immutable' );
 
     lives_ok {
         $meta->make_immutable();
-    } '... changed Bar to be immutable';
+    }
+    '... changed Bar to be immutable';
 
-    ok(!$meta->make_immutable, '... make immutable now returns nothing');
+    ok( !$meta->make_immutable, '... make immutable now returns nothing' );
 
-    ok(!$meta->is_mutable, '... our class is no longer mutable');
-    ok($meta->is_immutable, '... our class is now immutable');
+    ok( !$meta->is_mutable,  '... our class is no longer mutable' );
+    ok( $meta->is_immutable, '... our class is now immutable' );
 
-    isa_ok($meta, 'Class::MOP::Class');
+    isa_ok( $meta, 'Class::MOP::Class' );
 
-    dies_ok { $meta->add_method()    } '... exception thrown as expected';
-    dies_ok { $meta->alias_method()  } '... exception thrown as expected';
+    dies_ok { $meta->add_method() } '... exception thrown as expected';
+    dies_ok { $meta->alias_method() } '... exception thrown as expected';
     dies_ok { $meta->remove_method() } '... exception thrown as expected';
 
-    dies_ok { $meta->add_attribute()    } '... exception thrown as expected';
+    dies_ok { $meta->add_attribute() } '... exception thrown as expected';
     dies_ok { $meta->remove_attribute() } '... exception thrown as expected';
 
-    dies_ok { $meta->add_package_symbol()    } '... exception thrown as expected';
-    dies_ok { $meta->remove_package_symbol() } '... exception thrown as expected';
+    dies_ok { $meta->add_package_symbol() }
+    '... exception thrown as expected';
+    dies_ok { $meta->remove_package_symbol() }
+    '... exception thrown as expected';
 
     my @supers;
     lives_ok {
         @supers = $meta->superclasses;
-    } '... got the superclasses okay';
+    }
+    '... got the superclasses okay';
 
-    dies_ok { $meta->superclasses([ 'UNIVERSAL' ]) } '... but could not set the superclasses okay';
+    dies_ok { $meta->superclasses( ['UNIVERSAL'] ) }
+    '... but could not set the superclasses okay';
 
     my $meta_instance;
     lives_ok {
         $meta_instance = $meta->get_meta_instance;
-    } '... got the meta instance okay';
-    isa_ok($meta_instance, 'Class::MOP::Instance');
-    is($meta_instance, $meta->get_meta_instance, '... and we know it is cached');
+    }
+    '... got the meta instance okay';
+    isa_ok( $meta_instance, 'Class::MOP::Instance' );
+    is( $meta_instance, $meta->get_meta_instance,
+        '... and we know it is cached' );
 
     my @cpl;
     lives_ok {
         @cpl = $meta->class_precedence_list;
-    } '... got the class precedence list okay';
+    }
+    '... got the class precedence list okay';
     is_deeply(
-    \@cpl,
-    [ 'Bar', 'Foo'],
-    '... we just have ourselves in the class precedence list');
+        \@cpl,
+        [ 'Bar', 'Foo' ],
+        '... we just have ourselves in the class precedence list'
+    );
 
     my @attributes;
     lives_ok {
         @attributes = $meta->compute_all_applicable_attributes;
-    } '... got the attribute list okay';
+    }
+    '... got the attribute list okay';
     is_deeply(
-    [ sort { $a->name cmp $b->name } @attributes ],
-    [ Foo->meta->get_attribute('bar'), $meta->get_attribute('baz') ],
-    '... got the right list of attributes');
+        [ sort { $a->name cmp $b->name } @attributes ],
+        [ Foo->meta->get_attribute('bar'), $meta->get_attribute('baz') ],
+        '... got the right list of attributes'
+    );
 }
 
 {
     my $meta = Baz->meta;
-    is($meta->name, 'Baz', '... checking the Baz metaclass');
+    is( $meta->name, 'Baz', '... checking the Baz metaclass' );
 
-    ok($meta->is_mutable, '... our class is mutable');
-    ok(!$meta->is_immutable, '... our class is not immutable');
+    ok( $meta->is_mutable,    '... our class is mutable' );
+    ok( !$meta->is_immutable, '... our class is not immutable' );
 
     lives_ok {
         $meta->make_immutable();
-    } '... changed Baz to be immutable';
+    }
+    '... changed Baz to be immutable';
 
-    ok(!$meta->make_immutable, '... make immutable now returns nothing');
+    ok( !$meta->make_immutable, '... make immutable now returns nothing' );
 
-    ok(!$meta->is_mutable, '... our class is no longer mutable');
-    ok($meta->is_immutable, '... our class is now immutable');
+    ok( !$meta->is_mutable,  '... our class is no longer mutable' );
+    ok( $meta->is_immutable, '... our class is now immutable' );
 
-    isa_ok($meta, 'Class::MOP::Class');
+    isa_ok( $meta, 'Class::MOP::Class' );
 
-    dies_ok { $meta->add_method()    } '... exception thrown as expected';
-    dies_ok { $meta->alias_method()  } '... exception thrown as expected';
+    dies_ok { $meta->add_method() } '... exception thrown as expected';
+    dies_ok { $meta->alias_method() } '... exception thrown as expected';
     dies_ok { $meta->remove_method() } '... exception thrown as expected';
 
-    dies_ok { $meta->add_attribute()    } '... exception thrown as expected';
+    dies_ok { $meta->add_attribute() } '... exception thrown as expected';
     dies_ok { $meta->remove_attribute() } '... exception thrown as expected';
 
-    dies_ok { $meta->add_package_symbol()    } '... exception thrown as expected';
-    dies_ok { $meta->remove_package_symbol() } '... exception thrown as expected';
+    dies_ok { $meta->add_package_symbol() }
+    '... exception thrown as expected';
+    dies_ok { $meta->remove_package_symbol() }
+    '... exception thrown as expected';
 
     my @supers;
     lives_ok {
         @supers = $meta->superclasses;
-    } '... got the superclasses okay';
+    }
+    '... got the superclasses okay';
 
-    dies_ok { $meta->superclasses([ 'UNIVERSAL' ]) } '... but could not set the superclasses okay';
+    dies_ok { $meta->superclasses( ['UNIVERSAL'] ) }
+    '... but could not set the superclasses okay';
 
     my $meta_instance;
     lives_ok {
         $meta_instance = $meta->get_meta_instance;
-    } '... got the meta instance okay';
-    isa_ok($meta_instance, 'Class::MOP::Instance');
-    is($meta_instance, $meta->get_meta_instance, '... and we know it is cached');
+    }
+    '... got the meta instance okay';
+    isa_ok( $meta_instance, 'Class::MOP::Instance' );
+    is( $meta_instance, $meta->get_meta_instance,
+        '... and we know it is cached' );
 
     my @cpl;
     lives_ok {
         @cpl = $meta->class_precedence_list;
-    } '... got the class precedence list okay';
+    }
+    '... got the class precedence list okay';
     is_deeply(
-    \@cpl,
-    [ 'Baz', 'Bar', 'Foo'],
-    '... we just have ourselves in the class precedence list');
+        \@cpl,
+        [ 'Baz', 'Bar', 'Foo' ],
+        '... we just have ourselves in the class precedence list'
+    );
 
     my @attributes;
     lives_ok {
         @attributes = $meta->compute_all_applicable_attributes;
-    } '... got the attribute list okay';
+    }
+    '... got the attribute list okay';
     is_deeply(
-    [ sort { $a->name cmp $b->name } @attributes ],
-    [ $meta->get_attribute('bah'), Foo->meta->get_attribute('bar'), Bar->meta->get_attribute('baz') ],
-    '... got the right list of attributes');
+        [ sort { $a->name cmp $b->name } @attributes ],
+        [
+            $meta->get_attribute('bah'), Foo->meta->get_attribute('bar'),
+            Bar->meta->get_attribute('baz')
+        ],
+        '... got the right list of attributes'
+    );
 }
-
-
index bf8d748..b19320d 100644 (file)
@@ -10,9 +10,10 @@ use Scalar::Util;
 
 use Class::MOP;
 
-use lib catdir($FindBin::Bin, 'lib');
+use lib catdir( $FindBin::Bin, 'lib' );
 
 {
+
     package Foo;
 
     use strict;
@@ -35,29 +36,38 @@ use lib catdir($FindBin::Bin, 'lib');
     use warnings;
     use metaclass 'MyMetaClass';
 
-    sub mymetaclass_attributes{
-      shift->meta->mymetaclass_attributes;
+    sub mymetaclass_attributes {
+        shift->meta->mymetaclass_attributes;
     }
 
-    ::lives_ok {
-        Baz->meta->superclasses('Bar');
-    } '... we survive the metaclass incompatibility test';
+    ::lives_ok{ Baz->meta->superclasses('Bar') }
+        '... we survive the metaclass incompatibility test';
 }
 
 {
     my $meta = Baz->meta;
-    ok($meta->is_mutable, '... Baz is mutable');
-    isnt(Scalar::Util::blessed(Foo->meta), Scalar::Util::blessed(Bar->meta),
-         'Foo and Bar immutable metaclasses do not match');
-    is(Scalar::Util::blessed($meta), 'MyMetaClass', 'Baz->meta blessed as MyMetaClass');
-    ok(Baz->can('mymetaclass_attributes'), '... Baz can do method before immutable');
-    ok($meta->can('mymetaclass_attributes'), '... meta can do method before immutable');
+    ok( $meta->is_mutable, '... Baz is mutable' );
+    isnt(
+        Scalar::Util::blessed( Foo->meta ),
+        Scalar::Util::blessed( Bar->meta ),
+        'Foo and Bar immutable metaclasses do not match'
+    );
+    is( Scalar::Util::blessed($meta), 'MyMetaClass',
+        'Baz->meta blessed as MyMetaClass' );
+    ok( Baz->can('mymetaclass_attributes'),
+        '... Baz can do method before immutable' );
+    ok( $meta->can('mymetaclass_attributes'),
+        '... meta can do method before immutable' );
     lives_ok { $meta->make_immutable } "Baz is now immutable";
-    ok($meta->is_immutable, '... Baz is immutable');
-    isa_ok($meta, 'MyMetaClass', 'Baz->meta');
-    ok(Baz->can('mymetaclass_attributes'), '... Baz can do method after imutable');
-    ok($meta->can('mymetaclass_attributes'), '... meta can do method after immutable');
-    isnt(Scalar::Util::blessed(Baz->meta), Scalar::Util::blessed(Bar->meta), 'Baz and Bar immutable metaclasses are different');
+    ok( $meta->is_immutable, '... Baz is immutable' );
+    isa_ok( $meta, 'MyMetaClass', 'Baz->meta' );
+    ok( Baz->can('mymetaclass_attributes'),
+        '... Baz can do method after imutable' );
+    ok( $meta->can('mymetaclass_attributes'),
+        '... meta can do method after immutable' );
+    isnt( Scalar::Util::blessed( Baz->meta ),
+        Scalar::Util::blessed( Bar->meta ),
+        'Baz and Bar immutable metaclasses are different' );
     lives_ok { $meta->make_mutable } "Baz is now mutable";
-    ok($meta->is_mutable, '... Baz is mutable again');
+    ok( $meta->is_mutable, '... Baz is mutable again' );
 }
index 81143c9..ae6210f 100644 (file)
@@ -41,7 +41,10 @@ use Class::MOP;
 {
     my $meta = Baz->meta;
     is($meta->name, 'Baz', '... checking the Baz metaclass');
-    my @orig_keys = sort grep { !/^_/ } keys %$meta;
+    my %orig_keys = map { $_ => 1 } grep { !/^_/ } keys %$meta;
+    # Since this has no default it won't be present yet, but it will
+    # be after the class is made immutable.
+    $orig_keys{immutable_transformer} = 1;
 
     lives_ok {$meta->make_immutable; } '... changed Baz to be immutable';
     ok(!$meta->is_mutable,              '... our class is no longer mutable');
@@ -49,7 +52,7 @@ use Class::MOP;
     ok(!$meta->make_immutable,          '... make immutable now returns nothing');
     ok($meta->get_method_map->{new},    '... inlined constructor created');
     ok($meta->has_method('new'),        '... inlined constructor created for sure');    
-    ok($meta->get_immutable_transformer->inlined_constructor,
+    ok($meta->immutable_transformer->inlined_constructor,
        '... transformer says it did inline the constructor');
 
     lives_ok { $meta->make_mutable; }  '... changed Baz to be mutable';
@@ -58,11 +61,11 @@ use Class::MOP;
     ok(!$meta->make_mutable,            '... make mutable now returns nothing');
     ok(!$meta->get_method_map->{new},   '... inlined constructor removed');
     ok(!$meta->has_method('new'),        '... inlined constructor removed for sure');    
-    ok(!$meta->get_immutable_transformer->inlined_constructor,
+    ok(!$meta->immutable_transformer->inlined_constructor,
        '... transformer says it did not inline the constructor');
 
-    my @new_keys = sort grep { !/^_/ } keys %$meta;
-    is_deeply(\@orig_keys, \@new_keys, '... no straneous hashkeys');
+    my %new_keys = map { $_ => 1 } grep { !/^_/ } keys %$meta;
+    is_deeply(\%orig_keys, \%new_keys, '... no extraneous hashkeys');
 
     isa_ok($meta, 'Class::MOP::Class', '... Baz->meta isa Class::MOP::Class');
 
@@ -123,7 +126,8 @@ use Class::MOP;
 
     ok(Baz->meta->is_immutable,  'Superclass is immutable');
     my $meta = Baz->meta->create_anon_class(superclasses => ['Baz']);
-    my @orig_keys  = sort grep { !/^_/ } keys %$meta;
+    my %orig_keys = map { $_ => 1 } grep { !/^_/ } keys %$meta;
+    $orig_keys{immutable_transformer} = 1;
     my @orig_meths = sort { $a->name cmp $b->name }
       $meta->get_all_methods;
     ok($meta->is_anon_class,                  'We have an anon metaclass');
@@ -147,10 +151,10 @@ use Class::MOP;
     ok($meta->is_anon_class,          '... still marked as an anon class');
     my $instance = $meta->new_object;
 
-    my @new_keys  = sort grep { !/^_/ } keys %$meta;
+    my %new_keys  = map { $_ => 1 } grep { !/^_/ } keys %$meta;
     my @new_meths = sort { $a->name cmp $b->name }
       $meta->get_all_methods;
-    is_deeply(\@orig_keys, \@new_keys, '... no straneous hashkeys');
+    is_deeply(\%orig_keys, \%new_keys, '... no extraneous hashkeys');
     is_deeply(\@orig_meths, \@new_meths, '... no straneous methods');
 
     isa_ok($meta, 'Class::MOP::Class', '... Anon class isa Class::MOP::Class');
@@ -218,6 +222,6 @@ use Class::MOP;
     Bar->meta->make_immutable;
     Bar->meta->make_mutable;
 
-    isnt( Foo->meta->get_immutable_transformer, Bar->meta->get_immutable_transformer,
+    isnt( Foo->meta->immutable_transformer, Bar->meta->immutable_transformer,
           'Foo and Bar should have different immutable transformer objects' );
 }
diff --git a/t/086_rebless_instance_away.t b/t/086_rebless_instance_away.t
new file mode 100644 (file)
index 0000000..5d6a181
--- /dev/null
@@ -0,0 +1,44 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+use Test::More tests => 9;
+use Class::MOP;
+
+my @calls;
+
+do {
+    package My::Meta::Class;
+    use base 'Class::MOP::Class';
+
+    sub rebless_instance_away {
+        push @calls, [@_];
+        shift->SUPER::rebless_instance_away(@_);
+    }
+};
+
+do {
+    package Parent;
+    use metaclass 'My::Meta::Class';
+
+    package Child;
+    use metaclass 'My::Meta::Class';
+    use base 'Parent';
+};
+
+my $person = Parent->meta->new_object;
+Child->meta->rebless_instance($person);
+
+is(@calls, 1, "one call to rebless_instance_away");
+is($calls[0][0]->name, 'Parent', 'rebless_instance_away is called on the old metaclass');
+is($calls[0][1], $person, 'with the instance');
+is($calls[0][2]->name, 'Child', 'and the new metaclass');
+splice @calls;
+
+Child->meta->rebless_instance($person, foo => 1);
+is($calls[0][0]->name, 'Child');
+is($calls[0][1], $person);
+is($calls[0][2]->name, 'Child');
+is($calls[0][3], 'foo');
+is($calls[0][4], 1);
+splice @calls;
+
index 7850e2d..38aadce 100644 (file)
@@ -46,11 +46,10 @@ my %trustme = (
 
     ],
 
-    'Class::MOP::Immutable' => [
-        qw( create_immutable_metaclass
-            create_methods_for_immutable_metaclass
-            make_metaclass_immutable
-            make_metaclass_mutable )
+    'Class::MOP::Instance' => [
+        qw( BUILDARGS
+            bless_instance_structure
+            is_dependent_on_superclasses ),
     ],
 
     'Class::MOP::Instance' => [