MooseX::Extended versus the debugger
I've released MooseX::Extended 0.35 and it resolves a long-standing bug. If you tried to use multi
subs, it would trigger this bug in Syntax::Keyword::MultiSub. To fix that, you had to manually patch the latter module:
--- old/lib/Syntax/Keyword/MultiSub.xs 2021-12-16 10:59:30 +0000
+++ new/lib/Syntax/Keyword/MultiSub.xs 2022-08-12 10:23:06 +0000
@@ -129,6 +129,7 @@
redo:
switch(o->op_type) {
case OP_NEXTSTATE:
+ case OP_DBSTATE:
o = o->op_next;
goto redo;
Not good. However, Syntax::Keyword::MultiSub 0.03 has been released with that patch included, so that's a relief.
However, I was still struggling with switching WebService::OpenSky to MooseX::Extended
but under the debugger, we have a serious problem.
This error pops up, making the debugger useless:
The 'add_attribute' method cannot be called on an immutable instance at ...
When you use MooseX::Extended
, it takes years of best practices that have evolved for Moose and applies them to your Moose classes. Using this module is sort of equivalent to this:
package My::Class {
use v5.20.0;
use Moose;
use MooseX::StrictConstructor;
use feature qw( signatures postderef postderef_qq );
no warnings qw( experimental::signatures experimental::postderef );
use namespace::autoclean;
use Carp;
use mro 'c3';
... your code here
__PACKAGE__->meta->make_immutable;
}
1;
That's right: you no longer need to remember to declare your classes as immutable, or even end them with a true value. But ... automatically making your classes immutable has a trade-off. It relies on B::Hooks::AtRuntime and when using that under the debugger, the hook is triggered too early, making your classes immutable before Moose has built them! Oops.
Early versions of MooseX::Extended
fixed this by automatically disabling the immutable
behavior when running under the debugger, but I reverted that after haarg filed a ticket, explaining the issue. B::Hooks::AtRuntime was patched to fix this, but I still get the error with the new code, so this is still an unresolved issue.
That's where WebService::OpenSky
comes in. I wanted to use MooseX::Extended
in some non-trivial code, but the debugger issue kept biting me. I finally fixed it with this:
package WebService::OpenSky::Moose;
use MooseX::Extended::Custom;
use PerlX::Maybe 'provided';
# If $^P is true, we're running under the debugger.
#
# When running under the debugger, we disable
# __PACKAGE__->meta->make_immutable
# because the way the debugger works with B::Hooks::AtRuntime
# will cause the class to be made immutable before the Moose class
# is fully built. This causes the code to die.
sub import ( $class, %args ) {
MooseX::Extended::Custom->create(
includes => 'method',
provided $^P, excludes => 'immutable',
%args
);
}
I think it's an elegant little hack, with the caveat that your code behavior might change under the debugger. Very frustrating. However, for those who want to use MooseX::Extended
, I'm thinking about this change:
use MooseX::Extended
debugger_excludes => [qw/autoclean immutable/];
That disables both namespace::autoclean
and the immutable behavior under the debugger, but you have to ask for this behavior rather than have it happen silently. That being said, I don't like this proposal. We are changing the behavior and other modules can trigger $^P
to be true, so I can't guarantee we're truly under the debugger. You could have key features disabled in production code.
MooseX::Extended
is a lovely module for writing Moose classes in a safer manner, but this little nit is frustrating
Suggestions welcome.
Leave a comment