diff --git a/docs/about/changelog.md b/docs/about/changelog.md index b389c5e7b..1afdfb7b4 100644 --- a/docs/about/changelog.md +++ b/docs/about/changelog.md @@ -19,6 +19,7 @@ Release history of PerlOnJava. See [Roadmap](roadmap.md) for future plans. CFB128, OFB, and CTR compatibility. - Preserve string-compatible scalar channels for arithmetic results derived from string operands on both execution backends. +- Honor imported overrides of the core `chmod` and `lock` built-ins. ## v5.44.1: Regex, Threads, Async/Await, and CPAN Compatibility diff --git a/src/main/java/org/perlonjava/frontend/parser/ParserTables.java b/src/main/java/org/perlonjava/frontend/parser/ParserTables.java index 160eabf04..7985d187a 100644 --- a/src/main/java/org/perlonjava/frontend/parser/ParserTables.java +++ b/src/main/java/org/perlonjava/frontend/parser/ParserTables.java @@ -27,13 +27,13 @@ public class ParserTables { public static final Set OVERRIDABLE_OP = Set.of( "bless", "atan2", - "caller", "chdir", "close", "connect", + "caller", "chdir", "chmod", "close", "connect", "die", "do", "dump", "exec", "exit", "fork", "getgrgid", "gethostbyname", "getpwuid", "glob", "hex", - "kill", + "kill", "lock", "localtime", "log", "oct", "open", "rand", "readline", "readpipe", "rename", "require", diff --git a/src/test/resources/unit/imported_core_builtin_override.t b/src/test/resources/unit/imported_core_builtin_override.t new file mode 100644 index 000000000..9c714621b --- /dev/null +++ b/src/test/resources/unit/imported_core_builtin_override.t @@ -0,0 +1,41 @@ +use strict; +use warnings; +use Test::More; + +# Model the way a pure-Perl module exports a subroutine: assigning its CODE +# slot into the caller's package during import must make the imported sub win +# over a same-named core builtin. +BEGIN { + package ImportedCoreBuiltins; + + sub chmod { + return 'imported chmod'; + } + + sub lock { + return 'imported lock'; + } + + sub import { + my ($class, $caller) = @_; + $caller //= caller; + no strict 'refs'; + *{"${caller}::chmod"} = \&chmod; + *{"${caller}::lock"} = \&lock; + } + + __PACKAGE__->import('main'); +} + +is(chmod('+r', 'unused'), 'imported chmod', + 'imported chmod overrides the core builtin'); +my $lock_name = 'unused'; +is(lock($lock_name), 'imported lock', + 'imported lock overrides the core builtin'); +is(CORE::chmod(0, 'unused'), 0, + 'CORE::chmod still selects the core builtin'); +my $lock_target = 'unused'; +is(CORE::lock($lock_target), 'unused', + 'CORE::lock still selects the core builtin'); + +done_testing();