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
# before a release.
sub check_conflicts {
my %conflicts = (
- 'Moose' => '0.71',
+ 'Moose' => '0.72',
);
my $found = 0;
-Class::MOP version 0.78_01
+Class::MOP version 0.78_02
===========================
See the individual module documentation for more information
*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';
))
);
+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
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';
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';
# 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:
$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)
$instance;
}
+sub rebless_instance_away {
+ # this intentionally does nothing, it is just a hook
+}
+
# Inheritance
sub superclasses {
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
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;
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
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
use Carp 'confess';
use Scalar::Util 'blessed';
-our $VERSION = '0.78_01';
+our $VERSION = '0.78_02';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
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,
);
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;
}
sub _make_uncallable_methods {
- my ( $self, $metaclass, $meta ) = @_;
+ my $self = shift;
my %methods;
foreach my $cannot_call_method ( @{ $self->options->{cannot_call} } ) {
}
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 {
}
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};
}
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:
# 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;
}
}
}
});
- $immutable_metaclass->make_metaclass_immutable(@_)
+ $immutable_metaclass->make_metaclass_immutable;
=head1 DESCRIPTION
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
use Scalar::Util 'weaken', 'blessed';
-our $VERSION = '0.78_01';
+our $VERSION = '0.78_02';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Carp 'confess';
use Scalar::Util 'weaken';
-our $VERSION = '0.78_01';
+our $VERSION = '0.78_02';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
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';
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';
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
use Carp 'confess';
-our $VERSION = '0.78_01';
+our $VERSION = '0.78_02';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Carp 'confess';
use Scalar::Util 'blessed';
-our $VERSION = '0.78_01';
+our $VERSION = '0.78_02';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Carp 'confess';
use Scalar::Util 'blessed';
-our $VERSION = '0.78_01';
+our $VERSION = '0.78_02';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Scalar::Util 'blessed';
-our $VERSION = '0.78_01';
+our $VERSION = '0.78_02';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Scalar::Util 'blessed';
use Carp 'confess';
-our $VERSION = '0.78_01';
+our $VERSION = '0.78_02';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Carp 'confess';
use Scalar::Util 'blessed';
-our $VERSION = '0.78_01';
+our $VERSION = '0.78_02';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
#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 {
use strict;
use warnings;
-use Test::More tests => 254;
+use Test::More tests => 260;
use Test::Exception;
use Class::MOP;
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
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
);
'attribute_metaclass',
'method_metaclass',
'wrapped_method_metaclass',
- 'instance_metaclass'
+ 'instance_metaclass',
+ 'immutable_transformer',
);
# check class
use strict;
use warnings;
-use Test::More tests => 86;
+use Test::More tests => 80;
use Test::Exception;
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'
+ );
}
-
-
use Class::MOP;
-use lib catdir($FindBin::Bin, 'lib');
+use lib catdir( $FindBin::Bin, 'lib' );
{
+
package Foo;
use strict;
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' );
}
{
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');
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';
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');
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');
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');
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' );
}
--- /dev/null
+#!/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;
+
],
- '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' => [