test(gap): lock commander's outputError/writeErr indirection — #10711 does not reproduce - #10728
proggeramlug wants to merge 2 commits into
Conversation
#10711 reports that a function read from an object property silently drops its own call to a second function passed to it as a parameter — commander's `_displayError` shape, where `outputError(str, write)` invokes the `writeErr` it was handed: this._outputConfiguration.outputError( message, this._outputConfiguration.writeErr); It does not reproduce. The reporter's own isolated repro prints the expected text on all three trees that matter — current main (v0.5.1598), the main commit their branch forks from (8df83f8), and their actual tree (PR #10712 on top of #10699, head 463c4fa) — and real commander 14.0.3 compiled from source via `perry.compilePackages` matches Node 26.5.1 byte for byte across the whole output surface the issue names: `--help`, `--version`, missing required argument, unknown option, unknown command and `program.error()`, under both the default output configuration and a `configureOutput()` override. 32 further shapes of the same indirection agree with Node too. So this adds the regression lock rather than a fix. The shape is worth gating: #10689 — an inherited property read folding to the constant `undefined` on a scalar-replaced object — landed one commit before this issue was filed and is the same family, silent in the same way. The fixture covers the reported form verbatim plus the method-shorthand, class-field, `configureOutput`-override, spread, nested-receiver, cross-object-writer and in-loop spellings. Two of the cases exist to keep the fixture from passing vacuously. One traces `before` / `typeof write` / `after` around the inner call, so "the outer body ran and the inner call evaporated" cannot read as a pass. The other omits the writer entirely and asserts a TypeError: that a missing callee is LOUD is the property that keeps this bug class from ever presenting as a plausible wrong answer. Every writer sinks to stdout because the parity harness merges stdout and stderr into one compared stream; the stream is incidental to the indirection. Refs #10711
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (2)
Included review availability: Your plan provides up to 8 included reviews per hour; 4 remain after this review. 📝 WalkthroughWalkthroughThe pull request adds a regression fixture for property-function callback indirection and documents that the reported defect does not reproduce on current sources. The fixture covers multiple object shapes, writer replacement, repeated dispatch, and missing-writer errors. ChangesProperty callback regression lock
Priority: ⬇️ Low Estimated code review effort: 2 (Simple) | ~10 minutes Change: Other 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 1 files. (1 skipped: 1 unsupported.)
✨ Finishing Touches 💡 2📝 Generate docstrings 💡
🛠️ Fix failing CI checks 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Landed in merge train 224 (#10742), released as v0.5.1603 — main is now Closing rather than merging is how trains work here: the PRs were cherry-picked onto one tree, validated together, and landed under the train's own commit, so GitHub cannot mark this one merged even though your change is on main. One deliberate divergence, for #10719 only: the train carries Validation: all nine cheap gates, |
#10711 does not reproduce
The issue reports that a function read from an object property silently drops its own
call to a second function passed to it as a parameter — commander's
_displayErrorshape:
I could not make it fail anywhere.
The reporter's own isolated repro, verbatim
node --experimental-strip-types)error: something went wrong4715bc2f(v0.5.1598, train 220)error: something went wrong8df83f8c— the commit the reporter's branch forks fromerror: something went wrong463c4fa5(on #10699) — the reporter's actual treeerror: something went wrongAll three were full
cargo build --release -p perry -p perry-runtime-static -p perry-stdlib-staticbuilds with
PERRY_RUNTIME_DIRpinned to the matchingrelease/, so no arm could havelinked a stale
.a. Byte-identical to Node in every case, and the text really is onstderr (
2>/dev/nullswallows it,2>&1 >/dev/nullkeeps it).Real commander, compiled from source
commander 14.0.3 via
perry.compilePackages, with the real JS class confirmed in use(
_outputConfigurationis a live object,outputError/writeErrare functions,constructor.name === "Command"). Diffed against Node across the entire surface theissue says is lost —
--help,--version, missing required argument, unknown option,unknown command,
program.error()— under both the default output configuration and aconfigureOutput()override that proves the two-level indirection actually ran:on main and on the reporter's tree alike.
Everything else
32 further spellings of the same indirection all match Node: method shorthand, class
field,
Object.assignoverride, spread-built config, nested receivera.b.outputError(m, a.b.writeErr),cross-object writer, computed keys, array-element receiver, getter-provided writer,
Object.createprototype chain,Object.freeze, destructuring, three-level chaining,two plain-function hops, async caller, nested closure, in a loop, and the shape inside a
CommonJS module reached through
createRequire. A missing writer throwsTypeErrorrather than being dropped (Perry says "value is not a function" where Node names the
callee — a separate, cosmetic message gap).
What does lose commander's output today
Compiled from source, commander is fine. What is not fine on
mainis the path you getwhen commander is not listed in
perry.compilePackages:Against that shim the same program prints nothing at all — no error text, and no
CommanderErroreither, so thecatchnever runs:and
--help/--versionare empty withprogram.args === undefined. That is thepre-existing native-binding gap PR #10712 exists to delete, and it is the only
configuration I found where commander's output disappears.
This matters for triage: "codes right, text missing" is a blend of the two paths, not
something either produces on its own. The compiled-source path gets both right; the
shim gets both wrong. A build where part of the program reaches the shim and part
reaches the real source — which is what a stale
libperry_stdlib.aproduces on a branchthat removes
perry-ext-commanderand editscrates/perry-stdlib/Cargo.toml— wouldlook exactly like the report.
What this PR does
Adds the regression lock, not a fix. The shape earns a gate: #10689 — an inherited
property read folding to the constant
undefinedon a scalar-replaced object — landedone commit before this issue was filed, is the same family, and was silent in exactly
the same way. Nothing in
test-files/covered this indirection before.Two cases exist so the fixture cannot pass vacuously:
before/typeof write/afteraround the inner call, so "the outerbody ran and the inner call evaporated" cannot read as a pass;
TypeError, because a missing callee being loudis the property that keeps this bug class from presenting as a plausible wrong answer.
Every writer sinks to stdout: the parity harness merges stdout and stderr into one
compared stream, so a fixture using both would race on the interleaving. The stream is
incidental to the indirection under test.
This fixture passes on unfixed main — it does not discriminate, because there is
nothing to discriminate. That is the finding, and it is why this is filed as a lock
rather than a fix.
Suggested next step for #10711
Ask the reporter for the exact build that produced the empty output. The most likely
explanation is the trap CLAUDE.md documents:
perry-runtime/perry-stdlibarerlib-only, socargo build -p perry-runtime -p perry-stdlibdoes not refreshlibperry_{runtime,stdlib}.aandperry compilelinks a stale archive. PR #10712removes
perry-ext-commanderand editscrates/perry-stdlib/Cargo.toml, so a stalestdlib archive on that branch is exactly the situation where the compiler and the linked
runtime disagree about who owns commander.
I'd hold #10711 open until that is ruled out rather than close it on this PR, so no
close keyword here.
Verification
PERRY_SKIP_BUILD=1 PERRY_BIN=… ./run_parity_tests.sh --filter test_gap_./scripts/check_file_size.sh— cleanSummary by CodeRabbit
TypeErrorinstead of silently skipping the call.