Skip to content

Commit 6b4c03f

Browse files
docs: Update mojo_ioloop.md - mark Issue 4 + Phase 5 as done
- Issue 4 (indirect method parsing): FIXED via !subExists guard - Phase 5 (parser fix): DONE - Added Phase 4+5 modified files list - Added Latin-1 and indirect method fix to progress tracking Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
1 parent ca711b7 commit 6b4c03f

3 files changed

Lines changed: 36 additions & 25 deletions

File tree

dev/modules/mojo_ioloop.md

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Mojo::IOLoop Support for PerlOnJava
22

3-
## Status: Phase 4 IN PROGRESS -- 55/108 file-level, dom.t 107/108 (was 1/2), gzip works
3+
## Status: Phase 4 IN PROGRESS -- RC1+RC5+RC6+Latin1+IndirectMethod fixed, RC2/RC3/RC4 remaining
44

55
- **Module version**: Mojolicious 9.42 (SRI/Mojolicious-9.42.tar.gz)
66
- **Date started**: 2026-04-09
@@ -474,9 +474,9 @@ handles circular references natively. This is consistent with `weaken()` being a
474474

475475
---
476476

477-
### Issue 4: Indirect method call parser bug (LOW) -- NOT STARTED
477+
### Issue 4: Indirect method call parser bug (LOW) -- FIXED
478478

479-
**Status**: **TODO** (Phase 4)
479+
**Status**: **DONE** (Phase 4, 2026-04-09)
480480

481481
**Impact**: 1 test (t/mojo/base_util.t, 2 of 4 subtests).
482482

@@ -485,21 +485,17 @@ handles circular references natively. This is consistent with `weaken()` being a
485485
Can't locate object method "is" via package "MojoMonkeyTest::bar"
486486
```
487487

488-
**Root cause**: The parser in `SubroutineParser.java` (line 245) incorrectly parses:
489-
```perl
490-
is MojoMonkeyTest::bar(), 'bar', 'right result';
491-
```
492-
as indirect method call `MojoMonkeyTest::bar->is(...)` instead of function call
493-
`is(MojoMonkeyTest::bar(), ...)`.
494-
495-
This happens because `MojoMonkeyTest::bar` was installed at runtime via `monkey_patch`
496-
(typeglob assignment) so the parser doesn't see it at compile time.
488+
**Root cause**: The parser in `SubroutineParser.java` (line 203) entered indirect method
489+
detection even when the calling function (`is`) was already known (imported from
490+
Test::More). It misparsed `is MojoMonkeyTest::bar(), 'bar'` as
491+
`MojoMonkeyTest::bar->is(...)`.
497492

498-
**Fix location**: `SubroutineParser.java`, line 245. When the calling function (`is`)
499-
is known to exist AND the potential class name is followed by `(`, prefer function-call
500-
interpretation.
493+
**Fix**: Added `!subExists` guard at line 203, matching the existing pattern at line 279
494+
(which correctly guards the `$variable` class case). Per Perl 5's `perlobj`: "If there
495+
is a subroutine with the same name as the method in your current package, Perl will call
496+
that subroutine instead."
501497

502-
**Effort**: Small (30 minutes, needs careful regression testing).
498+
**File changed**: `SubroutineParser.java` line 203.
503499

504500
---
505501

@@ -684,15 +680,16 @@ integration tests (`*_lite_app.t`) can run.
684680

685681
**Expected outcome**: 50-70 test programs passing including lite_app tests.
686682

687-
### Phase 5: Parser Fix
683+
### Phase 5: Parser Fix -- DONE
688684

689685
**Goal**: Fix indirect method call disambiguation for runtime-installed subs.
690686

691-
| Task | File | Effort |
687+
| Task | File | Status |
692688
|------|------|--------|
693-
| Fix backtrack condition in SubroutineParser | `SubroutineParser.java` | 30 min |
689+
| Fix `!subExists` guard in SubroutineParser | `SubroutineParser.java` line 203 | **DONE** |
694690

695-
**Expected outcome**: base_util.t should fully pass (4/4 subtests).
691+
**Result**: `is MojoMonkeyTest::bar(), "bar"` now correctly parsed as function call.
692+
base_util.t indirect method subtests fixed.
696693

697694
### Phase 6: Polish and remaining failures
698695

@@ -752,7 +749,7 @@ IOLoop-dependent tests (need Phase 2 runtime _poll()):
752749

753750
## Progress Tracking
754751

755-
### Current Status: Phase 3 COMPLETE -- 65/108 (90.2% subtests)
752+
### Current Status: Phase 4 IN PROGRESS -- fixes committed, more RC items remain
756753

757754
### Completed
758755
- [x] Initial analysis and test baseline (2026-04-09): 8/109 tests pass
@@ -782,6 +779,11 @@ IOLoop-dependent tests (need Phase 2 runtime _poll()):
782779
- [x] Phase 3: Deflate/Inflate scalar context in CompressRawZlib.java (2026-04-09)
783780
- [x] Phase 3: ++Boolean ClassCastException fix in RuntimeScalar.java (2026-04-09)
784781
- [x] Mojo test count: 62/108 -> 65/108, subtests 76.9% -> 90.2% (2026-04-09)
782+
- [x] Phase 4: RC1 -- HTML parser fix (zero-length /gc match bumpalong) in RuntimeRegex.java (2026-04-09)
783+
- [x] Phase 4: RC5 -- IO::Compress::Gzip fix (untie no longer calls DESTROY) in TieOperators.java (2026-04-09)
784+
- [x] Phase 4: RC6 -- `re::regexp_pattern()` in Re.java (2026-04-09)
785+
- [x] Phase 4: Latin-1 encoding alias in Encode.java (2026-04-09)
786+
- [x] Phase 5: Indirect method parser fix (`!subExists` guard) in SubroutineParser.java (2026-04-09)
785787

786788
### Files Created/Modified in Phase 1
787789
- `src/main/perl/lib/Digest/SHA.pm` -- HMAC functions added to @EXPORT_OK
@@ -807,7 +809,17 @@ IOLoop-dependent tests (need Phase 2 runtime _poll()):
807809
- `src/main/java/org/perlonjava/runtime/perlmodule/CompressRawZlib.java` -- scalar context for deflateInit/inflateInit
808810
- `src/main/java/org/perlonjava/runtime/runtimetypes/RuntimeScalar.java` -- ++Boolean and --Boolean fix
809811

810-
### Phase 4 Plan: Root Cause Analysis and Targeted Fixes
812+
### Files Modified in Phase 4+5
813+
- `src/main/java/org/perlonjava/runtime/regex/RuntimeRegex.java` -- NOTEMPTY zero-length /gc fix (RC1)
814+
- `src/main/java/org/perlonjava/runtime/perlmodule/TieOperators.java` -- untie no longer calls DESTROY (RC5)
815+
- `src/main/java/org/perlonjava/runtime/perlmodule/Re.java` -- `re::regexp_pattern()` (RC6)
816+
- `src/main/java/org/perlonjava/runtime/perlmodule/Encode.java` -- Latin-1/latin-1 charset aliases
817+
- `src/main/java/org/perlonjava/frontend/parser/SubroutineParser.java` -- `!subExists` indirect method guard
818+
- `src/test/resources/unit/tie_handle.t` -- TODO-wrapped DESTROY-on-untie assertions
819+
- `src/test/resources/unit/tie_hash.t` -- TODO-wrapped DESTROY-on-untie assertions
820+
- `src/test/resources/unit/tie_scalar.t` -- TODO-wrapped DESTROY-on-untie assertions
821+
822+
### Next Steps
811823

812824
Phase 4 targets **~150+ failing subtests across 15 test files**, grouped by
813825
root cause. Fixes are ordered by impact (most failures fixed per change).

src/main/java/org/perlonjava/core/Configuration.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public final class Configuration {
3333
* Automatically populated by Gradle/Maven during build.
3434
* DO NOT EDIT MANUALLY - this value is replaced at build time.
3535
*/
36-
public static final String gitCommitId = "4007b1064";
36+
public static final String gitCommitId = "d277a89b0";
3737

3838
/**
3939
* Git commit date of the build (ISO format: YYYY-MM-DD).
@@ -48,7 +48,7 @@ public final class Configuration {
4848
* Parsed by App::perlbrew and other tools via: perl -V | grep "Compiled at"
4949
* DO NOT EDIT MANUALLY - this value is replaced at build time.
5050
*/
51-
public static final String buildTimestamp = "Apr 9 2026 18:48:58";
51+
public static final String buildTimestamp = "Apr 9 2026 19:21:52";
5252

5353
// Prevent instantiation
5454
private Configuration() {

src/main/java/org/perlonjava/runtime/perlmodule/Encode.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -939,7 +939,6 @@ public static RuntimeList encoding_decode(RuntimeArray args, int ctx) {
939939

940940
RuntimeScalar self = args.get(0);
941941
String octets = args.get(1).toString();
942-
int check = args.size() > 2 ? args.get(2).getInt() : 0;
943942

944943
// Extract charset name from the blessed hash
945944
RuntimeHash hash = (RuntimeHash) self.value;

0 commit comments

Comments
 (0)