fix: #837 — emit wrapper for default/null/undefined-named exports#870
Merged
Conversation
…ports
The wrapper-emission asymmetry: regular wrappers (codegen.rs:2552-2586)
key on the local HIR function name, while consumer references
(expr.rs:~3819) build wrapper symbols from the *exported* name. For
`export { local as exported }` renames, the consumer-facing
`__perry_wrap_perry_fn_<src>__<exported>` had no definition and the link
failed.
This adds a parallel emission pass right after the regular wrapper loop
that walks `hir.exports`, picks out `Named { local, exported }` entries
where `exported != local`, and emits the renamed wrapper:
- Function rename → forward to `perry_fn_<src>__<local>` (closure-call
ABI, mirroring the regular wrapper).
- Variable/class/type rename or `export default function NAME` whose
body the HIR lowerer skipped (lower.rs:5296 TODO) → no-op returning
undefined, mirroring `__perry_wrap_perry_unknown_func`.
Validated:
- `__perry_wrap_perry_fn_<v35.js>__default` now emitted (issue #837).
- `__perry_wrap_perry_fn_<regexes.ts>__null` / `__undefined` now
emitted (issue #836 partial — the variable-rename leg).
Refs #836 (partial — cross-module class re-exports remain a separate PR).
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
crates/perry-codegen/src/codegen.rs:2552-2586keyed__perry_wrap_<...>on each function's local HIR name, while the consumer-side reference atcrates/perry-codegen/src/expr.rs:~3819builds the same symbol from the exported name. For renamed exports —export { local as exported }orexport default function NAME— the exported wrapper symbol was never defined and the link failed.hir.exports, picks outNamed { local, exported }entries withexported != local, and emits__perry_wrap_perry_fn_<src>__<sanitize(exported)>with external linkage.perry_fn_<src>__<local>using the closure-call ABI.export default function NAMEwhose body the HIR lowerer never recorded (crates/perry-hir/src/lower.rs:5296TODO) → no-op returning undefined, mirroring the existing__perry_wrap_perry_unknown_funcfallback.Reproductions (pre-fix)
#837— uuid'sdist/esm-browser/v35.jsusesexport default function v35(...). Consumers inv3.js/v5.jspassv35as a closure value, which transitively pulls the wrapper symbol:#836(partial) — zod'ssrc/v4/core/regexes.tsusesconst _null = /.../; export { _null as null };(same forundefined). A consumer that readsregexes.null/regexes.undefinedas a value falls through to the function-shape branch and references:Validation
nmonnode_modules_uuid_dist_esm_browser_v35_js.onow showsT ___perry_wrap_perry_fn_<v35.js>__default. uuid repro reaches the linker successfully (sha1.js'sCall callee shape not supported (PropertyGet) with 20 argsis a separate codegen gap and surfaces independently; the wrapper-emission failure no longer blocks).nmonnode_modules_zod_src_v4_core_regexes_ts.onow showsT ___perry_wrap_..._nullandT ___perry_wrap_..._undefined. The repro program (import * as regexes from "zod/v4/core/regexes"; console.log(typeof regexes.null);) links and runs, printingfunction(the closure handle, perjs_closure_alloc_singletonsemantics).cargo build --releaseclean.cargo test --release --workspace --exclude perry-ui-ios --exclude perry-ui-tvos --exclude perry-ui-watchos --exclude perry-ui-visionos --exclude perry-ui-android --exclude perry-ui-windows --exclude perry-ui-gtk4— all green (no regressions in the 231-testperry-codegen/perrysuites or anywhere else in the workspace).cargo fmt --allclean.Scope notes
v35.jsruntime ("v3()returns undefined" rather than a uuid string) is a separate HIR-level bug:crates/perry-hir/src/lower.rs:5296has a literal// TODO: properly lower function expressionin theExportDefaultDecl::Fnarm and never registers the function body inmodule.functions. This PR's scope is codegen-only; the runtime fix needs an HIR change and a different PR.#836's cross-module class re-exports are out of scope per the task brief — that's a separate PR.Refs #837 (link error only — runtime gaps tracked in #871).Refs #836 (partial — null/undefined wrappers fixed; cross-module class re-exports remain a separate PR).Test plan
__perry_wrap_..._defaultis emitted with external linkage inv35.js's.o.__perry_wrap_..._null/__perry_wrap_..._undefinedare emitted inregexes.ts's.o.cargo testclean.