Conversation
a885a41 to
969a05a
Compare
`./jcpan -t RPG::Traveller::Person` failed because the test chain
required Devel::Symdump (used by Test::Pod::Coverage) to introspect
the symbol table, and several PerlOnJava-side glob-handling bugs
made that introspection report wrong answers — or refuse to run.
Root causes addressed:
1. `*{"main::"}` returned an empty hash on dereference.
`RuntimeGlob.getGlobHash()` stripped a leading `"main::"` even when
that was the *entire* glob name, ending up looking up `""` in the
global hashes table. Now we only strip the prefix when there's
something after it, mirroring `GlobalVariable.getGlobalHash()`.
2. `local(*X) = $glob` made `*X{ARRAY|HASH}` falsely report defined.
`dynamicSaveState` eagerly auto-vivified empty array/hash slots so
that writes during the local scope wouldn't leak. That auto-vivify
leaked back out as `defined *X{ARRAY|HASH}` returning true even
when neither side ever had a slot — Devel::Symdump's `_symdump`
uses exactly that test to walk the stash and was getting bogus
hits for every imported sub. Now save/restore tracks pre-existence
directly via the underlying maps and only repopulates slots that
really existed before `local`. Glob-to-glob aliasing in
`set(RuntimeGlob)` also now skips slots that don't exist on the
source, except for stash globs (`*Pkg::`) where the HASH slot is
intrinsic.
3. `open(Pkg::FH, ...)` IO didn't surface through stash entries.
`open` only sets the IO on the canonical glob in `globalIORefs`,
but `*{$Pkg::{FH}}{IO}` and `local(*X) = $Pkg::{FH}` operate on a
`RuntimeStashEntry`/glob clone whose `IO` field was an empty
placeholder. `getGlobSlot("IO")` now falls back to the canonical
glob when the local slot is empty, and `set(RuntimeGlob)` only
prefers `value.IO` when it actually carries a `RuntimeIO` (or a
tied handle) — otherwise it picks up the IO from the source's
canonical glob. This makes Devel::Symdump's `filehandles` and
`dirhandles` see opened handles installed under qualified names.
4. `B::GV::GvFLAGS` / `B::GVf_IMPORTED_CV` were missing.
Pod::Coverage uses these to skip imported helpers; without them
it could not load and `t/PodCoverage.t` produced no plan. Stubs
are now provided. To approximate the real-Perl `GVf_IMPORTED_CV`
bit, a new `Internals::jperl_is_imported_sub($fqn)` probe exposes
`GlobalVariable.isSubs`, which already records typeglob CODE
assignments (Exporter-style imports). `use constant` constants
that take the proxy-constant path are also flagged via the empty
prototype, mirroring real Perl's PCS handling so packages that
only declare constants don't fail Pod::Coverage tests. A
`B::GV::CV` slot accessor was added at the same time.
5. `$Config{d_telldir}` (and friends) were undef.
PerlOnJava implements `telldir`/`seekdir`/`rewinddir`/`readdir`
via `java.nio`, but Config.pm didn't advertise them. Devel::Symdump
branches on `d_telldir` to choose between `telldir()` and B::IO
introspection for `_is_dirhandle`; with the flag now defined,
`dirhandles` correctly reports opened directory handles.
End-to-end: `./jcpan -t RPG::Traveller::Person` now exits 0 with all
tests successful (including `t/PodCoverage.t`). Devel::Symdump's own
`t/symdump.t` improved from 9/22 failed to 3/13 failed; the remaining
three tests are sensitive to specific Perl-internal symbol layout
(filehandles count, special-variable hash list, ordering of
`main::_`) and are out of scope for this PR.
Files touched:
- src/main/java/org/perlonjava/runtime/runtimetypes/RuntimeGlob.java
Stash-name fix in getGlobHash; lazy slot population in
dynamicSaveState/dynamicRestoreState; conditional aliasing in
set(RuntimeGlob) for ARRAY/HASH/SCALAR; canonical-glob fallback
for *X{IO}.
- src/main/java/org/perlonjava/runtime/perlmodule/Internals.java
Added Internals::jperl_is_imported_sub.
- src/main/perl/lib/B.pm
Added B::GV::GvFLAGS, B::GV::CV, B::GVf_IMPORTED_CV.
- src/main/perl/lib/Config.pm
Added d_telldir/d_seekdir/d_rewinddir/d_readdir.
- src/main/java/org/perlonjava/core/Configuration.java
Auto-updated by `make`.
Generated with [Devin](https://cli.devin.ai/docs)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
969a05a to
d787d06
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Makes
./jcpan -t RPG::Traveller::Personpass end-to-end. The test chain depends on Devel::Symdump (via Test::Pod::Coverage) for stash introspection, and several PerlOnJava-side glob bugs were making that introspection lie or refuse to load.Bugs fixed
*{"main::"}returned an empty hash on dereference —RuntimeGlob.getGlobHash()stripped a leading"main::"even when that was the entire glob name.local(*X) = $globmade*X{ARRAY|HASH}falsely defined —dynamicSaveStateeagerly auto-vivified empty array/hash slots, leaking back as a defined slot. Devel::Symdump uses exactly that test to walk the symbol table. Save/restore now tracks pre-existence and only repopulates slots that really existed; glob-to-glob aliasing also skips non-existent source slots (with the stash-glob HASH treated as intrinsic).open(Pkg::FH, ...)IO didn't surface through stash entries —openonly sets IO on the canonical glob inglobalIORefs, while*{$Pkg::{FH}}{IO}andlocal(*X) = $Pkg::{FH}operate on aRuntimeStashEntryclone whoseIOfield was an empty placeholder.getGlobSlot("IO")now falls back to the canonical glob;set(RuntimeGlob)only prefersvalue.IOwhen it actually carries aRuntimeIO(or a tied handle).B::GV::GvFLAGS/B::GVf_IMPORTED_CVwere missing — Pod::Coverage requires them; without themt/PodCoverage.tproduced no plan. Stubs added; a newInternals::jperl_is_imported_sub($fqn)probe exposes the existingGlobalVariable.isSubsmap so imports are skipped. Constants (subs with empty prototype) are also treated as imported, mirroring real Perl's PCS handling.$Config{d_telldir}(and friends) were undef — PerlOnJava implements telldir/seekdir/rewinddir/readdir viajava.nio, but Config.pm didn't advertise them. Devel::Symdump's_is_dirhandlebranches ond_telldir; with the flag defined,dirhandlesnow reports opened directory handles.Result
./jcpan -t RPG::Traveller::Personexits 0, all 17 subtests across 6 test files pass (includingt/PodCoverage.t).t/symdump.timproved from 9/22 failed to 3/13 failed. The remaining three are sensitive to specific Perl-internal symbol layout (filehandles count, special-variable hash list, ordering ofmain::_) and are out of scope here.Test plan
make(all unit tests pass)./jcpan -t RPG::Traveller::Personpasseslocal(*X) = $glob,*{$stash{FH}}{IO}, dirhandle introspection)Generated with Devin