Subject: | Sub::Quote breaks with charnames, Function::Parameters |
Sub::Quote tries to copy runtime %^H settings from the point of call of quote_sub into the compilation environment of the quoted code.
This breaks all modules that put references in %^H (because it stringifies them). In case you're wondering "but who would do that?", Function::Parameters and charnames are among the affected modules. The latter even says (see https://metacpan.org/pod/charnames#CUSTOM-TRANSLATORS):
Show quoted text
> The mechanism of translation of \N{...} escapes is general and not hardwired into charnames.pm. A module can install custom translations (inside the scope which uses the module) with the following magic incantation:
Show quoted text> sub import {
> shift;
> $^H{charnames} = \&translator;
> }
I.e. putting coderefs into %^H is an official Perl interface.
Example using Function::Parameters:
$ cat try2.pl
#!perl
use strict;
use warnings;
use Sub::Quote qw( quote_sub );
use Function::Parameters 2.001_001;
my $subref = quote_sub 'return';
$subref->();
__END__
$ perl try2.pl
Eval went very, very wrong:
1: {
2: my $_QUOTED = ${$_[1]->{"\$_QUOTED"}};
3: my $_UNQUOTED = ${$_[1]->{"\$_UNQUOTED"}};
4: package main;
5: $$_UNQUOTED = sub {
6: ($_QUOTED,$_UNQUOTED) if 0;
7: # BEGIN quote_sub PRELUDE
8: package main;
9: BEGIN {
10: $^H = 133090;
11: ${^WARNING_BITS} = "UUUUUUUUUUUUUUUU\025";
12: %^H = (
13: "Function::Parameters/config" => "HASH(0x8eee090)",
14: );
15: }
16: # END quote_sub PRELUDE
17: return };
18: }
19: 1;
Function::Parameters: internal error: $^H{'Function::Parameters/config'} not a hashref: HASH(0x8eee090) at (eval 6) line 17.
at try2.pl line 8.
Example using charnames:
$ cat try.pl
#!perl
use strict;
use warnings;
use Sub::Quote qw( quote_sub );
print "\N{DEGREE SIGN}_\N{DEGREE SIGN}\n";
my $subref = quote_sub 'print "\N{INVERTED EXCLAMATION MARK}Hola, mundo!\n"';
$subref->();
__END__
$ perl try.pl
°_°
Eval went very, very wrong:
1: {
2: my $_UNQUOTED = ${$_[1]->{"\$_UNQUOTED"}};
3: my $_QUOTED = ${$_[1]->{"\$_QUOTED"}};
4: package main;
5: $$_UNQUOTED = sub {
6: ($_QUOTED,$_UNQUOTED) if 0;
7: # BEGIN quote_sub PRELUDE
8: package main;
9: BEGIN {
10: $^H = 133090;
11: ${^WARNING_BITS} = "UUUUUUUUUUUUUUUU\025";
12: %^H = (
13: "charnames_full" => 1,
14: "charnames_stringified_ords" => "",
15: "charnames_name_aliases" => "HASH(0x89c5020)",
16: "charnames_loose" => 0,
17: "charnames_stringified_names" => "",
18: "charnames" => "CODE(0x8a1b840)",
19: "charnames_ord_aliases" => "HASH(0x89a83e0)",
20: "charnames_inverse_ords" => "HASH(0x89c5600)",
21: "charnames_short" => 1,
22: "charnames_stringified_inverse_ords" => "",
23: "charnames_scripts" => "",
24: );
25: }
26: # END quote_sub PRELUDE
27: print "\N{INVERTED EXCLAMATION MARK}Hola, mundo!\n" };
28: }
29: 1;
Undefined subroutine &main::CODE(0x8a1b840) called at (eval 6) line 27.
at try.pl line 8.