Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
142 commits
Select commit Hold shift + click to select a range
f904a4e
Add Zod compatibility fixture
TheHypnoo Jun 29, 2026
607e2a1
Expand Zod compatibility coverage
TheHypnoo Jun 29, 2026
e667e61
Improve Zod constructor compatibility
TheHypnoo Jun 29, 2026
339146a
Expand Zod compatibility coverage
TheHypnoo Jun 29, 2026
edd42c1
Fix dynamic arithmetic for Zod compatibility
TheHypnoo Jun 29, 2026
2b4160b
Expand Zod fixture coverage
TheHypnoo Jun 29, 2026
14b6301
Fix Zod 4 literal and file compatibility
TheHypnoo Jun 29, 2026
b4676b3
Expand Zod async and function coverage
TheHypnoo Jun 29, 2026
bbfa907
Add Zod standard schema coverage
TheHypnoo Jun 29, 2026
340ba67
Expand Zod factory and error map coverage
TheHypnoo Jun 29, 2026
ce13d20
Fix forward-captured lexical bindings
TheHypnoo Jun 29, 2026
1a26d06
Expand Zod recursive object coverage
TheHypnoo Jun 29, 2026
b808da0
Expand Zod string format coverage
TheHypnoo Jun 29, 2026
073777d
Expand Zod error coverage
TheHypnoo Jun 29, 2026
522f6cb
Expand Zod metadata coverage
TheHypnoo Jun 29, 2026
454eb19
Expand Zod function coverage
TheHypnoo Jun 29, 2026
fc0c631
Expand Zod object coverage
TheHypnoo Jun 29, 2026
992060a
Expand Zod collection coverage
TheHypnoo Jun 29, 2026
0db000f
Expand Zod custom error coverage
TheHypnoo Jun 29, 2026
7e466ed
Expand Zod array and promise coverage
TheHypnoo Jun 29, 2026
dfaa826
Expand Zod readonly coverage
TheHypnoo Jun 29, 2026
1100193
Expand Zod async effect coverage
TheHypnoo Jun 29, 2026
9c5ee43
Fix Error subclass field initialization
TheHypnoo Jun 29, 2026
5596c2f
Expand Zod fatal effect coverage
TheHypnoo Jun 29, 2026
bfef247
Expand Zod union error coverage
TheHypnoo Jun 29, 2026
fedc913
Expand Zod factory coverage
TheHypnoo Jun 30, 2026
c2e5216
Expand Zod modifier coverage
TheHypnoo Jun 30, 2026
30d26db
Expand Zod introspection coverage
TheHypnoo Jun 30, 2026
48c36cf
Expand Zod collection error coverage
TheHypnoo Jun 30, 2026
9932c39
Expand Zod function error coverage
TheHypnoo Jun 30, 2026
828a44b
Expand Zod issue metadata coverage
TheHypnoo Jun 30, 2026
79143e3
Expand Zod issue code coverage
TheHypnoo Jun 30, 2026
15cefed
Expand Zod bound issue metadata coverage
TheHypnoo Jun 30, 2026
f951a61
Expand Zod async issue coverage
TheHypnoo Jun 30, 2026
01f2e46
Expand Zod modifier composition coverage
TheHypnoo Jun 30, 2026
a7843fa
Expand Zod default object coverage
TheHypnoo Jun 30, 2026
4d4da8e
Expand Zod function effects coverage
TheHypnoo Jun 30, 2026
5e10b18
Expand Zod custom schema coverage
TheHypnoo Jun 30, 2026
3493961
Expand Zod package subpath coverage
TheHypnoo Jun 30, 2026
1a086f5
Expand Zod JSON-like coverage
TheHypnoo Jun 30, 2026
4a05b1b
Expand Zod effect factory coverage
TheHypnoo Jun 30, 2026
ec3011f
Expand Zod string format coverage
TheHypnoo Jun 30, 2026
be73b1f
Fix exported enum runtime objects
TheHypnoo Jun 30, 2026
3746ec0
Expand Zod primitive edge coverage
TheHypnoo Jun 30, 2026
47633c6
Fix imported binding named re-exports
TheHypnoo Jun 30, 2026
911e124
Expand Zod parse helper coverage
TheHypnoo Jun 30, 2026
84759ba
Expand Zod class factory coverage
TheHypnoo Jun 30, 2026
ef0401f
Expand Zod string method coverage
TheHypnoo Jun 30, 2026
4d2161f
Fix namespace subobject method dispatch
TheHypnoo Jun 30, 2026
15cdf77
Expand Zod object fixture coverage
TheHypnoo Jun 30, 2026
ade6110
Expand Zod array tuple fixture coverage
TheHypnoo Jun 30, 2026
f602296
Expand Zod union fixture coverage
TheHypnoo Jun 30, 2026
70315fe
Expand Zod collection fixture coverage
TheHypnoo Jun 30, 2026
2180902
Expand Zod literal enum fixture coverage
TheHypnoo Jun 30, 2026
1080f0a
Fix missing Error errors property
TheHypnoo Jun 30, 2026
9764335
Expand Zod modifier fixture coverage
TheHypnoo Jun 30, 2026
cd7a4ee
Expand Zod primitive metadata coverage
TheHypnoo Jun 30, 2026
2fda192
Expand Zod object shape fixture coverage
TheHypnoo Jun 30, 2026
f501538
Expand Zod effects fixture coverage
TheHypnoo Jun 30, 2026
292107e
Expand Zod function fixture coverage
TheHypnoo Jun 30, 2026
2acc1e8
Expand Zod async fixture coverage
TheHypnoo Jun 30, 2026
f6c982a
Expand Zod error formatting coverage
TheHypnoo Jun 30, 2026
75ba43d
Expand Zod metadata fixture coverage
TheHypnoo Jun 30, 2026
b714696
Expand Zod record key fixture coverage
TheHypnoo Jun 30, 2026
eb3e3b7
Fix Reflect.set on frozen array indices
TheHypnoo Jun 30, 2026
bb29160
Expand Zod JSON fixture coverage
TheHypnoo Jun 30, 2026
08bbff1
Expand Zod async error fixture coverage
TheHypnoo Jun 30, 2026
6484a15
Fix computed string property access
TheHypnoo Jun 30, 2026
77adbff
Expand Zod promise fixture coverage
TheHypnoo Jun 30, 2026
54f1488
Expand Zod parse options coverage
TheHypnoo Jun 30, 2026
9dbd584
Expand Zod recursive fixture coverage
TheHypnoo Jun 30, 2026
fb19add
Fix class name defineProperty descriptors
TheHypnoo Jun 30, 2026
69ef759
Fix dynamic class parent snapshots
TheHypnoo Jul 1, 2026
bf3baa2
Expand Zod function fixture coverage
TheHypnoo Jul 1, 2026
4eb0852
Expand Zod branded fixture coverage
TheHypnoo Jul 1, 2026
dd5a681
Fix large number toString formatting
TheHypnoo Jul 1, 2026
d8aefe5
Expand Zod standard validation coverage
TheHypnoo Jul 1, 2026
2c781a9
Expand Zod object merge coverage
TheHypnoo Jul 1, 2026
fe884b6
Cover remaining Zod export aliases
TheHypnoo Jul 1, 2026
f5ec574
Expand Zod default catch factory coverage
TheHypnoo Jul 1, 2026
ae2bd74
Expand Zod union error formatting coverage
TheHypnoo Jul 1, 2026
7cda8cf
Expand Zod discriminated enum coverage
TheHypnoo Jul 1, 2026
b6219ab
Expand Zod import interop coverage
TheHypnoo Jul 1, 2026
edc545e
Expand Zod native enum coverage
TheHypnoo Jul 1, 2026
277b371
Expand Zod subpath import coverage
TheHypnoo Jul 1, 2026
54ea26d
Expand Zod function rest coverage
TheHypnoo Jul 1, 2026
89a9842
Expand Zod intersection merge coverage
TheHypnoo Jul 1, 2026
04b32e1
Expand Zod map clone coverage
TheHypnoo Jul 1, 2026
84f429d
Expand Zod readonly coverage
TheHypnoo Jul 1, 2026
163590f
Expand Zod date clone coverage
TheHypnoo Jul 1, 2026
e739ebe
Expand Zod object mask coverage
TheHypnoo Jul 1, 2026
4b307c5
Fix in operator prototype lookup
TheHypnoo Jul 1, 2026
d056743
Expand Zod promise clone coverage
TheHypnoo Jul 1, 2026
e74d873
Expand Zod inherited passthrough coverage
TheHypnoo Jul 1, 2026
7069d64
Expand Zod function clone coverage
TheHypnoo Jul 1, 2026
dbfd186
Expand Zod lazy clone coverage
TheHypnoo Jul 1, 2026
b737c2a
Fix Object.create prototype reflection
TheHypnoo Jul 1, 2026
2643654
Expand Zod factory alias coverage
TheHypnoo Jul 1, 2026
c1d7147
Expand Zod record key coverage
TheHypnoo Jul 1, 2026
88bc71b
Expand Zod inherited composition coverage
TheHypnoo Jul 1, 2026
5cca96d
Expand Zod inherited discriminator coverage
TheHypnoo Jul 1, 2026
4c563ef
Expand Zod getter input coverage
TheHypnoo Jul 1, 2026
a28bd2d
Expand Zod null prototype coverage
TheHypnoo Jul 1, 2026
83c55fc
Expand Zod sparse array coverage
TheHypnoo Jul 1, 2026
ec3c20a
Fix Map Set default subclass initialization
TheHypnoo Jul 1, 2026
d42a849
Fix builtin prototype and fetch reflection
TheHypnoo Jul 1, 2026
f42cf6d
Fix URL href normalization
TheHypnoo Jul 1, 2026
038e0df
Fix Unicode regex and URL reflection
TheHypnoo Jul 1, 2026
f50c80b
Fix namespace reexport arity and JSON replacer order
TheHypnoo Jul 2, 2026
fb2099f
Fix namespace default alias calls
TheHypnoo Jul 2, 2026
84aceb1
Improve Zod compatibility support
TheHypnoo Jul 2, 2026
c9bee8f
Merge remote-tracking branch 'origin/main' into feat/zod-compat-fixtures
TheHypnoo Jul 2, 2026
3df0361
Fix Zod compatibility CI regressions
TheHypnoo Jul 2, 2026
30ccd11
Fix raw closure instanceof prototype lookup
TheHypnoo Jul 2, 2026
fbe0e55
Reject handle-band URL object pointers
TheHypnoo Jul 2, 2026
69082cd
Include namespace import prefixes in cache tests
TheHypnoo Jul 2, 2026
6ea3e42
Fix dynamic import registry deferral
TheHypnoo Jul 2, 2026
c4b6818
Merge branch 'main' into feat/zod-compat-fixtures
proggeramlug Jul 3, 2026
d027ea3
Address Zod compatibility review feedback
TheHypnoo Jul 3, 2026
87f86e4
Merge branch 'main' into feat/zod-compat-fixtures
TheHypnoo Jul 3, 2026
b2e810e
Fix class static initialization ordering
TheHypnoo Jul 3, 2026
821afe5
fix(runtime): bound has_property prototype recursion and extend BigIn…
TheHypnoo Jul 3, 2026
5dbe433
fix(codegen+hir): cap Map/Set super-kind walk and visit missing exprs…
TheHypnoo Jul 3, 2026
86dbcc3
chore: comment cleanups, drop dead code, and harden node-oracle tests
TheHypnoo Jul 3, 2026
7d696ce
test: add shared _perry_test_lib.sh harness and adopt it in two regre…
TheHypnoo Jul 3, 2026
4865837
fix(runtime): switch/case strict-equality compares BigInt by value
TheHypnoo Jul 3, 2026
afb5391
fix(codegen): run field initializers on implicit-constructor builtin …
TheHypnoo Jul 3, 2026
e000f65
chore(runtime): centralize Blob/File/URL class-id constants
TheHypnoo Jul 3, 2026
f51c9c2
test: derive runtime-lib dir from the selected perry binary in _perry…
TheHypnoo Jul 3, 2026
ec20478
chore(codegen): align map_set_default_super_kind depth cap across bot…
TheHypnoo Jul 3, 2026
4cfe4c3
test(release): add zod4-basic tier-3 fixture (Zod 4.4.3)
TheHypnoo Jul 4, 2026
10760f4
test: strengthen homonymous-class-export assertion (positive-only -> …
TheHypnoo Jul 4, 2026
d4fe546
test(parity): add test_parity_bigint_switch and test_parity_builtin_s…
TheHypnoo Jul 4, 2026
dd8933c
test: strengthen 3 more under-specified assertions from the audit
TheHypnoo Jul 4, 2026
950b036
fix(runtime): validate raw string pointer via GcHeader in js_dyn_inde…
TheHypnoo Jul 4, 2026
23b3388
fix(hir): new Function() with no args folds to an empty function (int…
TheHypnoo Jul 4, 2026
6a4825b
Merge remote-tracking branch 'origin/main' into feat/zod-compat-fixtures
TheHypnoo Jul 4, 2026
464c176
Merge remote-tracking branch 'origin/main' into feat/zod-compat-fixtures
TheHypnoo Jul 4, 2026
020c1fa
test(parity): triage test_gap_class_advanced as known regression (#5952)
TheHypnoo Jul 4, 2026
5b077a0
Merge remote-tracking branch 'origin/main' into feat/zod-compat-fixtures
TheHypnoo Jul 4, 2026
84fb915
test(parity): triage 2 standing categorical gaps missed by #5947
TheHypnoo Jul 4, 2026
5d6426a
Merge remote-tracking branch 'origin/main' into feat/zod-compat-fixtures
TheHypnoo Jul 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added constv
Binary file not shown.
47 changes: 45 additions & 2 deletions crates/perry-codegen/src/codegen/artifacts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1348,6 +1348,47 @@ pub(super) fn emit_module_artifacts(c: ModuleArtifactsCtx<'_>) -> Result<()> {
namespace_key_globals.push((gname, byte_len));
}
}
let mut namespace_extern_prefixes = std::collections::BTreeSet::new();
for entry in &cross_module.namespace_entries {
if let super::opts::NamespaceEntryKind::NestedNamespace { source_prefix } = &entry.kind {
if source_prefix != module_prefix {
namespace_extern_prefixes.insert(source_prefix.clone());
}
}
}
for source_prefix in cross_module.namespace_import_prefixes.values() {
if source_prefix != module_prefix {
namespace_extern_prefixes.insert(source_prefix.clone());
}
}
for source_prefix in cross_module.namespace_member_namespace_prefixes.values() {
if source_prefix != module_prefix {
namespace_extern_prefixes.insert(source_prefix.clone());
}
}
let mut emitted_namespace_extern_prefixes = std::collections::BTreeSet::new();
for source_prefix in namespace_extern_prefixes {
if emitted_namespace_extern_prefixes.insert(source_prefix.clone()) {
llmod.add_external_global(&format!("__perry_ns_{}", source_prefix), DOUBLE);
}
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
for export in &hir.exports {
let perry_hir::Export::Named { local, exported } = export else {
continue;
};
let Some(source_prefix) = cross_module.namespace_import_prefixes.get(local) else {
continue;
};
let getter_name = format!("perry_fn_{}__{}", module_prefix, sanitize(exported));
if llmod.has_function(&getter_name) {
continue;
}
let getter = llmod.define_function(&getter_name, DOUBLE, vec![]);
let _ = getter.create_block("entry");
let blk = getter.block_mut(0).unwrap();
let value = blk.load(DOUBLE, &format!("@__perry_ns_{}", source_prefix));
blk.ret(DOUBLE, &value);
}
// For each `Expr::DynamicImport` target this module dispatches to,
// declare the foreign module's `@__perry_ns_<target_prefix>` as an
// extern global so the dispatch site can load it. Deduped via
Expand All @@ -1374,8 +1415,10 @@ pub(super) fn emit_module_artifacts(c: ModuleArtifactsCtx<'_>) -> Result<()> {
if prefix.starts_with("__native_mod__") || prefix.starts_with("__node_submod__") {
continue;
}
let ns_name = format!("__perry_ns_{}", prefix);
llmod.add_external_global(&ns_name, DOUBLE);
if emitted_namespace_extern_prefixes.insert(prefix.clone()) {
let ns_name = format!("__perry_ns_{}", prefix);
llmod.add_external_global(&ns_name, DOUBLE);
}
// Issue #753: declare each dynamic-import target's `__init`
// so the dispatch site in `Expr::DynamicImport` can call it
// before loading the namespace. The wrapper-side init is
Expand Down
3 changes: 3 additions & 0 deletions crates/perry-codegen/src/codegen/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,9 @@ pub(super) fn compile_closure(
namespace_reexport_named_imports: &cross_module.namespace_reexport_named_imports,
namespace_member_prefixes: &cross_module.namespace_member_prefixes,
namespace_member_origin_names: &cross_module.namespace_member_origin_names,
namespace_member_vars: &cross_module.namespace_member_vars,
namespace_member_namespace_prefixes: &cross_module.namespace_member_namespace_prefixes,
namespace_import_prefixes: &cross_module.namespace_import_prefixes,
imported_async_funcs: &cross_module.imported_async_funcs,
local_async_funcs: &cross_module.local_async_funcs,
local_generator_funcs: &cross_module.local_generator_funcs,
Expand Down
6 changes: 6 additions & 0 deletions crates/perry-codegen/src/codegen/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,9 @@ pub(super) fn compile_module_entry(
namespace_reexport_named_imports: &cross_module.namespace_reexport_named_imports,
namespace_member_prefixes: &cross_module.namespace_member_prefixes,
namespace_member_origin_names: &cross_module.namespace_member_origin_names,
namespace_member_vars: &cross_module.namespace_member_vars,
namespace_member_namespace_prefixes: &cross_module.namespace_member_namespace_prefixes,
namespace_import_prefixes: &cross_module.namespace_import_prefixes,
imported_async_funcs: &cross_module.imported_async_funcs,
local_async_funcs: &cross_module.local_async_funcs,
local_generator_funcs: &cross_module.local_generator_funcs,
Expand Down Expand Up @@ -1121,6 +1124,9 @@ pub(super) fn compile_module_entry(
namespace_reexport_named_imports: &cross_module.namespace_reexport_named_imports,
namespace_member_prefixes: &cross_module.namespace_member_prefixes,
namespace_member_origin_names: &cross_module.namespace_member_origin_names,
namespace_member_vars: &cross_module.namespace_member_vars,
namespace_member_namespace_prefixes: &cross_module.namespace_member_namespace_prefixes,
namespace_import_prefixes: &cross_module.namespace_import_prefixes,
imported_async_funcs: &cross_module.imported_async_funcs,
local_async_funcs: &cross_module.local_async_funcs,
local_generator_funcs: &cross_module.local_generator_funcs,
Expand Down
3 changes: 3 additions & 0 deletions crates/perry-codegen/src/codegen/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,9 @@ pub(super) fn compile_function(
namespace_reexport_named_imports: &cross_module.namespace_reexport_named_imports,
namespace_member_prefixes: &cross_module.namespace_member_prefixes,
namespace_member_origin_names: &cross_module.namespace_member_origin_names,
namespace_member_vars: &cross_module.namespace_member_vars,
namespace_member_namespace_prefixes: &cross_module.namespace_member_namespace_prefixes,
namespace_import_prefixes: &cross_module.namespace_import_prefixes,
imported_async_funcs: &cross_module.imported_async_funcs,
local_async_funcs: &cross_module.local_async_funcs,
local_generator_funcs: &cross_module.local_generator_funcs,
Expand Down
2 changes: 1 addition & 1 deletion crates/perry-codegen/src/codegen/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1145,7 +1145,7 @@ pub(super) fn emit_namespace_populator(
let wrapper_name = format!(
"__perry_wrap_perry_fn_{}__{}",
source_prefix,
sanitize(source_local)
sanitize_member(source_local)
);
let arity = (*param_count).min(16);
let mut wrapper_params: Vec<crate::types::LlvmType> = vec![I64];
Expand Down
56 changes: 56 additions & 0 deletions crates/perry-codegen/src/codegen/method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,31 @@ fn node_stream_parent_kind(
None
}

fn map_set_default_super_kind<'a>(
classes: &HashMap<String, &'a perry_hir::Class>,
mut parent: Option<&'a str>,
) -> Option<i32> {
let mut depth = 0usize;
while let Some(name) = parent {
match name {
"Map" => return Some(0),
"Set" => return Some(1),
_ => {}
}
let class = classes.get(name).copied()?;
if class.constructor.is_some() {
return None;
}
parent = class.extends_name.as_deref();
depth += 1;
// Keep this bound in sync with the twin in lower_call/new_helpers.rs.
if depth > 64 {
break;
}
}
None
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

/// Compile a class instance method as a top-level LLVM function with the
/// signature `perry_method_<class>_<name>(this_box: double, args: double…)
/// -> double`. The first parameter (`this`) is stored in a slot whose
Expand Down Expand Up @@ -400,6 +425,9 @@ pub(super) fn compile_method(
namespace_reexport_named_imports: &cross_module.namespace_reexport_named_imports,
namespace_member_prefixes: &cross_module.namespace_member_prefixes,
namespace_member_origin_names: &cross_module.namespace_member_origin_names,
namespace_member_vars: &cross_module.namespace_member_vars,
namespace_member_namespace_prefixes: &cross_module.namespace_member_namespace_prefixes,
namespace_import_prefixes: &cross_module.namespace_import_prefixes,
imported_async_funcs: &cross_module.imported_async_funcs,
local_async_funcs: &cross_module.local_async_funcs,
local_generator_funcs: &cross_module.local_generator_funcs,
Expand Down Expand Up @@ -717,6 +745,31 @@ pub(super) fn compile_method(
ctx.block()
.call(DOUBLE, runtime_fn, &[(DOUBLE, &this_box), (DOUBLE, &opts)]);
}
if let Some(kind) = map_set_default_super_kind(classes, class.extends_name.as_deref()) {
let undef_lit =
crate::nanbox::double_literal(f64::from_bits(crate::nanbox::TAG_UNDEFINED));
let iterable = method
.params
.first()
.and_then(|param| ctx.locals.get(&param.id).cloned())
.map(|slot| ctx.block().load(DOUBLE, &slot))
.unwrap_or_else(|| undef_lit.clone());
let this_box = ctx
.this_stack
.last()
.cloned()
.map(|slot| ctx.block().load(DOUBLE, &slot))
.unwrap_or_else(|| undef_lit.clone());
ctx.block().call(
DOUBLE,
"js_map_set_subclass_init",
&[
(DOUBLE, &this_box),
(I32, &kind.to_string()),
(DOUBLE, &iterable),
],
);
}

// Wall 51: a no-own-ctor class with a DYNAMIC / cross-module parent
// (`class X extends _mod.Parent {}`, captured as `extends_expr`) that
Expand Down Expand Up @@ -1273,6 +1326,9 @@ pub(super) fn compile_static_method(
namespace_reexport_named_imports: &cross_module.namespace_reexport_named_imports,
namespace_member_prefixes: &cross_module.namespace_member_prefixes,
namespace_member_origin_names: &cross_module.namespace_member_origin_names,
namespace_member_vars: &cross_module.namespace_member_vars,
namespace_member_namespace_prefixes: &cross_module.namespace_member_namespace_prefixes,
namespace_import_prefixes: &cross_module.namespace_import_prefixes,
imported_async_funcs: &cross_module.imported_async_funcs,
local_async_funcs: &cross_module.local_async_funcs,
local_generator_funcs: &cross_module.local_generator_funcs,
Expand Down
4 changes: 4 additions & 0 deletions crates/perry-codegen/src/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1457,6 +1457,9 @@ pub fn compile_module(hir: &HirModule, opts: CompileOptions) -> Result<Vec<u8>>
namespace_reexport_named_imports: opts.namespace_reexport_named_imports.clone(),
namespace_member_prefixes: opts.namespace_member_prefixes,
namespace_member_origin_names: opts.namespace_member_origin_names,
namespace_member_vars: opts.namespace_member_vars,
namespace_member_namespace_prefixes: opts.namespace_member_namespace_prefixes,
namespace_import_prefixes: opts.namespace_import_prefixes,
imported_async_funcs: opts.imported_async_funcs,
local_async_funcs,
local_generator_funcs,
Expand Down Expand Up @@ -1490,6 +1493,7 @@ pub fn compile_module(hir: &HirModule, opts: CompileOptions) -> Result<Vec<u8>>
symbol: ctor_name,
param_count: ic.constructor_param_count,
has_own_constructor: ic.has_own_constructor,
uses_new_target: ic.constructor_uses_new_target,
has_instance_fields: ic.has_instance_fields,
has_rest: ic.constructor_has_rest,
},
Expand Down
8 changes: 7 additions & 1 deletion crates/perry-codegen/src/codegen/module_globals_emit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,13 @@ pub(crate) fn emit_module_globals(
// semantically wrong (it'd return the closure value instead
// of invoking it).
let is_function_alias = hir.exported_functions.iter().any(|(exp, _)| exp == name);
if is_exported && !is_also_function && !is_function_alias {
let is_exported_alias_source = hir.exports.iter().any(|export| {
matches!(export, perry_hir::Export::Named { local, .. } if local == name)
});
if (is_exported || is_exported_alias_source)
&& !is_also_function
&& !is_function_alias
{
let fn_name = format!("perry_fn_{}__{}", module_prefix, sanitize(name),);
let getter = llmod.define_function(&fn_name, DOUBLE, vec![]);
let _ = getter.create_block("entry");
Expand Down
49 changes: 38 additions & 11 deletions crates/perry-codegen/src/codegen/opts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,16 +175,35 @@ pub struct CompileOptions {
/// it dispatched `tracer.make(Math.random())` instead of
/// `random.make(Math.random())`.
pub namespace_member_prefixes: std::collections::HashMap<(String, String), String>,
/// Issue #5924 (companion to #680/#678): per-namespace origin-name
/// resolution. Keyed by `(namespace_local_name, member_name)` →
/// `origin_name`. `import_function_origin_names` is a flat map, so when
/// two namespaces imported into the same file both have a member with
/// the same name and only one of them is a re-export rename, the
/// rename's origin-name override clobbers the other namespace's
/// (correct, unrenamed) suffix — `import { Effect, Context } from
/// "effect"` broke `Context.Service` because `Effect`'s own re-exported
/// `Service` clobbered the flat map first.
/// Issue #680 / #5924 follow-up: per-namespace member origin-name overrides.
/// `namespace_member_prefixes` picks the producer module, but re-exported
/// members can be stored under a different origin export name; without this
/// `ns.alias` calls the right module with the wrong symbol name. Keyed by
/// `(namespace_local_name, exported_member_name)` → `origin_export_name`.
/// Being per-namespace also fixes #5924: `import_function_origin_names` is a
/// flat map, so two namespaces imported into the same file that both expose
/// a member with the same name (only one of them a re-export rename) would
/// clobber each other — `import { Effect, Context } from "effect"` broke
/// `Context.Service` because `Effect`'s own re-exported `Service` clobbered
/// the flat map first.
pub namespace_member_origin_names: std::collections::HashMap<(String, String), String>,
/// Issue #680 follow-up: per-namespace exported-variable members. Namespace
/// member calls need to know when `ns.member` is a getter returning a
/// closure rather than a direct function symbol; otherwise codegen emits a
/// direct call to the zero-arg getter. Keyed by `(namespace_local_name,
/// exported_member_name)`.
pub namespace_member_vars: std::collections::HashSet<(String, String)>,
/// Issue #680 follow-up: per-namespace nested namespace re-exports.
/// `export * as child` members are namespace objects, not callable/value
/// exports from the parent prefix; this map preserves the nested target
/// prefix. Keyed by `(namespace_local_name, exported_member_name)` →
/// nested module prefix.
pub namespace_member_namespace_prefixes: std::collections::HashMap<(String, String), String>,
/// Issue #680 follow-up: namespace import local → target module prefix.
/// Member-specific maps are insufficient when the namespace binding itself
/// is read as a value; codegen must return the producer's real module
/// namespace object, including nested `export * as` members.
pub namespace_import_prefixes: std::collections::HashMap<String, String>,
/// When true, `compile_module` returns the textual LLVM IR (`.ll`)
/// as bytes instead of invoking `clang -c` to produce an object file.
/// Used by the bitcode-link path (`PERRY_LLVM_BITCODE_LINK=1`).
Expand Down Expand Up @@ -475,6 +494,8 @@ pub struct ImportedClass {
pub constructor_param_count: usize,
/// Whether the source class declared its own constructor body.
pub has_own_constructor: bool,
/// Whether the source constructor symbol may read `new.target`.
pub constructor_uses_new_target: bool,
/// Whether the source class's constructor's last declared parameter is
/// `...rest`. Symmetric to `method_has_rest` but for the constructor: the
/// source module compiled `<class>_constructor(this, arg0, …)` expecting
Expand Down Expand Up @@ -549,6 +570,7 @@ pub(crate) struct ImportedCtor {
pub symbol: String,
pub param_count: usize,
pub has_own_constructor: bool,
pub uses_new_target: bool,
pub has_instance_fields: bool,
/// True when the constructor's last declared param is `...rest`. Tells
/// the cross-module `new` dispatch to pack the trailing args into an
Expand All @@ -574,9 +596,14 @@ pub(crate) struct CrossModuleCtx {
/// Issue #680: per-namespace member resolution. See doc on
/// `CompileOptions::namespace_member_prefixes`.
pub namespace_member_prefixes: std::collections::HashMap<(String, String), String>,
/// Issue #5924: per-namespace origin-name resolution. See doc on
/// `CompileOptions::namespace_member_origin_names`.
/// See `CompileOptions::namespace_member_origin_names` (#680 / #5924).
pub namespace_member_origin_names: std::collections::HashMap<(String, String), String>,
/// See `CompileOptions::namespace_member_vars`.
pub namespace_member_vars: std::collections::HashSet<(String, String)>,
/// See `CompileOptions::namespace_member_namespace_prefixes`.
pub namespace_member_namespace_prefixes: std::collections::HashMap<(String, String), String>,
/// See `CompileOptions::namespace_import_prefixes`.
pub namespace_import_prefixes: std::collections::HashMap<String, String>,
pub imported_async_funcs: std::collections::HashSet<String>,
/// FuncIds of locally-defined async functions in this module. Populated
/// from `hir.functions.is_async`. Used by `is_promise_expr` to refine
Expand Down
Loading
Loading