use strict;
use warnings;
+use Class::Load qw(load_class);
use Class::MOP;
-
use Carp qw( confess );
use Data::OptList;
use List::Util qw( first );
my $params = @_ == 1 ? $_[0] : {@_};
my $object = $self->SUPER::new_object($params);
+ $self->_call_all_triggers($object, $params);
+
+ $object->BUILDALL($params) if $object->can('BUILDALL');
+
+ return $object;
+}
+
+sub _call_all_triggers {
+ my ($self, $object, $params) = @_;
+
foreach my $attr ( $self->get_all_attributes() ) {
next unless $attr->can('has_trigger') && $attr->has_trigger;
my $init_arg = $attr->init_arg;
-
next unless defined $init_arg;
-
next unless exists $params->{$init_arg};
$attr->trigger->(
),
);
}
-
- $object->BUILDALL($params) if $object->can('BUILDALL');
-
- return $object;
}
sub _generate_fallback_constructor {
return @BUILD_calls;
}
+sub _eval_environment {
+ my $self = shift;
+
+ my @attrs = sort { $a->name cmp $b->name } $self->get_all_attributes;
+
+ my $triggers = [
+ map { $_->can('has_trigger') && $_->has_trigger ? $_->trigger : undef }
+ @attrs
+ ];
+
+ # We need to check if the attribute ->can('type_constraint')
+ # since we may be trying to immutabilize a Moose meta class,
+ # which in turn has attributes which are Class::MOP::Attribute
+ # objects, rather than Moose::Meta::Attribute. And
+ # Class::MOP::Attribute attributes have no type constraints.
+ # However we need to make sure we leave an undef value there
+ # because the inlined code is using the index of the attributes
+ # to determine where to find the type constraint
+
+ my @type_constraints = map {
+ $_->can('type_constraint') ? $_->type_constraint : undef
+ } @attrs;
+
+ my @type_constraint_bodies = map {
+ defined $_ ? $_->_compiled_type_constraint : undef;
+ } @type_constraints;
+
+ my @type_coercions = map {
+ defined $_ && $_->has_coercion
+ ? $_->coercion->_compiled_type_coercion
+ : undef
+ } @type_constraints;
+
+ my @type_constraint_messages = map {
+ defined $_
+ ? ($_->has_message ? $_->message : $_->_default_message)
+ : undef
+ } @type_constraints;
+
+ return {
+ %{ $self->SUPER::_eval_environment },
+ ((any { defined && $_->has_initializer } @attrs)
+ ? ('$attrs' => \[@attrs])
+ : ()),
+ '$triggers' => \$triggers,
+ '@type_coercions' => \@type_coercions,
+ '@type_constraint_bodies' => \@type_constraint_bodies,
+ '@type_constraint_messages' => \@type_constraint_messages,
+ ( map { defined($_) ? %{ $_->inline_environment } : () }
+ @type_constraints ),
+ # pretty sure this is only going to be closed over if you use a custom
+ # error class at this point, but we should still get rid of this
+ # at some point
+ '$meta' => \$self,
+ };
+}
+
sub superclasses {
my $self = shift;
my $supers = Data::OptList::mkopt(\@_);
foreach my $super (@{ $supers }) {
my ($name, $opts) = @{ $super };
- Class::MOP::load_class($name, $opts);
+ load_class($name, $opts);
my $meta = Class::MOP::class_of($name);
$self->throw_error("You cannot inherit from a Moose Role ($name)")
if $meta && $meta->isa('Moose::Meta::Role')
);
}
+sub _fixup_attributes_after_rebless {
+ my $self = shift;
+ my ($instance, $rebless_from, %params) = @_;
+
+ $self->SUPER::_fixup_attributes_after_rebless(
+ $instance,
+ $rebless_from,
+ %params
+ );
+
+ $self->_call_all_triggers( $instance, \%params );
+}
+
## -------------------------------------------------
our $error_level;
sub _inline_raise_error {
my ( $self, $message ) = @_;
- return (
- 'die ' . $message . ';',
- );
+ return 'die ' . $message;
}
sub create_error {
my $class = ref $self ? $self->error_class : "Moose::Error::Default";
- Class::MOP::load_class($class);
+ load_class($class);
$class->new(
Carp::caller_info($args{depth}),
my $class = ref $self ? $self->error_class : "Moose::Error::Default";
- Class::MOP::load_class($class);
+ load_class($class);
# don't check inheritance here - the intention is that the class needs
# to provide a non-inherited inlining method, because falling back to
# the default inlining method is most likely going to be wrong
# yes, this is a huge hack, but so is the entire error system, so.
- return '$meta->create_error(' . $msg . ', ' . $args . ');'
+ return
+ '$meta->create_error('
+ . $msg
+ . ( defined $args ? ', ' . $args : q{} ) . ');'
unless $class->meta->has_method('_inline_new');
$class->_inline_new(
argument, but the option hash reference can also contain any other
role relevant values like exclusions or parameterized role arguments.
-=item B<< $metaclass->make_immutable(%options) >>
-
-This overrides the parent's method to add a few options. Specifically,
-it uses the Moose-specific constructor and destructor classes, and
-enables inlining the destructor.
-
-Since Moose always inlines attributes, it sets the C<inline_accessors> option
-to false.
-
=item B<< $metaclass->new_object(%params) >>
This overrides the parent's method in order to add support for