Merge train 182r: #10199, #10203, #10213 - #10216
Merged
Merged
Conversation
added 5 commits
September 13, 2026 18:35
#10197) `ns.member(...spread)` had a fast path (#6475) for namespace members that are rest-parameter exports: bundle every argument into one array and call `perry_fn_<src>__<member>` directly. For a `let`/`const`-bound export (`export const mergeAll = (...ctxs) => …`) that symbol is the export's zero-arg VALUE getter, not the function body, so the call returned the closure itself and the expression evaluated to the function. Effect's `Layer.mergeAll` does exactly `Context.mergeAll(...contexts)` through a namespace import, which is why every OpenCode command died in its bootstrap with `Cannot read properties of undefined (reading 'size')`. Mirror `try_lower_namespace_member_call`: when the member is in `imported_vars`, skip the fast path so the closure-callee path reads the value through the getter and applies the spread with `js_closure_call_apply_with_spread`. Function declarations keep the direct symbol call. Claude-Session: https://claude.ai/code/session_01As1fetJAqDFib4n7Wm5Suo (cherry picked from commit f869baa)
(cherry picked from commit 388e83a)
…eritage (#10210) A static getter on a class whose `extends` clause is a call expression (effect v4 `class Svc extends Context.Service<Svc, Shape>()(id) {}`, i.e. a plain `function KeyClass(){}` whose [[Prototype]] was swapped with `Object.setPrototypeOf`) threw `of is not a function` on `this.of(x)` while the plain read `this.of` returned the function. Two gaps, both on the miss path only: - The dynamic method-call dispatcher's class-object arm resolved nothing but the static-method vtable. It now mirrors the class-ref arm (#5437): when the vtable misses, read the property exactly as the read path does (static accessors, the per-evaluation parent class object's statics, the function-valued ancestor's swapped prototype) and call the closure with `this` bound to the receiver. - The class-ref read paths (string and symbol keys) looked for the function-valued parent edge only on the receiver's own class id. They now walk the class chain like `super()` dispatch already did, so a subclass of the class that `extends <function>` inherits those statics too. Unblocks OpenCode v1.18.30's runtime bootstrap (`ConfigService.Service` → `static get layer()` → `tag.of(config)` while AppRuntime builds RuntimeFlags). Claude-Session: https://claude.ai/code/session_01As1fetJAqDFib4n7Wm5Suo (cherry picked from commit 14126f3)
This was referenced Sep 13, 2026
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.
Merge train 182r: lands #10199 (route const rest exports through the closure spread call; fixes #10197) at
f869baa9c5, #10203 (route the traversal-feedback counters through the hot thread-local cache) at388e83a742and #10213 (resolve static-getter method calls on call-expression heritage; fixes #10210) at14126f371a, plus the workspace version bump to 0.5.1559. (Named 182r to stay clear of the other merge lane's train numbers.)The PR commits were cherry-picked onto
44e78debf9without conflicts.Validation (macOS arm64)
Validation ran on the same three PRs over
64f5249ac0. Main has since gained only #10212, which touches none of their files.RUSTFLAGS=-Dwarnings cargo check -p perry --bins,raw_handle_debt.py(both invocations),gc_runtime_root_holders.py,check_test_registration.py,check_file_size.shscripts/check_thread_locals.py:json/traversal_feedback.rsis no longer flagged. The one remaining violation,regex/perex_owner.rs, is identical on main.cargo test --release -p perry-codegen --lib: 1530 passed / 0 failedcargo test --release -p perry --test issue_10210_static_getter_call: 1 / 0;--test source_graph_export_regressions: 25 / 0, includingissue_10197test_gap_json36 pass plus the known JSON.parse lazy array: Object.defineProperty index accessor is bypassed by reads #10097 failure.class115 pass / 3 fail andstatic45 pass / 2 fail:2159_defineproperty_class_prototypeand2899_2779_2777_static_helpersare main's known reds, andtest_issue_7769_thread_class_dispatch,test_three_like_native_class_descriptorsandtest_ws_static_constants_6117fail identically with a9b911855f8compiler (Node exits 1 on this host).Confirmation on this exact tree:
RUSTFLAGS=-Dwarnings cargo check -p perry --bins;cargo test --release -p perry-runtime: 3765 passed, 1 failed. The failure isgc::tests::heap_generation::a_free_or_move_outside_every_scope_is_caught_in_debug_builds, already on main from #10205 (release-mode assertion test; noted there).CI attribution (vs main's run at
b5a82cfeae)cargo-testpassed.native_stackfailure, the same four gated gap regressions with identical output, and the same gc-stress failure.Review notes
let/const-bound export has no callableperry_fn_<src>__<name>(that symbol is its value getter), so the rest-bundling fast path now excludesimported_varsand those calls take the closure-callee path, mirroringtry_lower_namespace_member_call.parent_closure_in_chain(the helpersuper()dispatch uses), and native method dispatch falls back to the ordinary property read plus athis-rebound closure call only after the static vtable misses. The method is rooted before the rebind and the receiver is re-read from its handle.