Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 50 additions & 0 deletions crates/perry-codegen/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5522,6 +5522,32 @@ fn emit_string_pool(
packed_global_names.push(name);
}

// Pre-allocate string constants for class-name registration. We need
// these BEFORE `init_fn` is created, because once `init_fn` borrows
// `llmod` we can no longer mutate the module's constant pool. (#1021.)
let mut named_class_name_constants: Vec<(u32, String, usize)> = Vec::new();
{
let mut named: Vec<(u32, String)> = Vec::new();
for (class_name, class) in classes.iter() {
if *class_name != class.name {
continue;
}
let cid = match class_ids.get(class_name).copied() {
Some(c) if c != 0 => c,
_ => continue,
};
if !class_name.starts_with("__AnonShape_") {
named.push((cid, class_name.clone()));
}
}
named.sort_by(|a, b| a.0.cmp(&b.0));
named.dedup_by_key(|(cid, _)| *cid);
for (cid, name) in named {
let (const_name, byte_len) = llmod.add_string_constant(&name);
named_class_name_constants.push((cid, const_name, byte_len));
}
}

let init_name = format!("__perry_init_strings_{}", module_prefix);
let init_fn = llmod.define_function(&init_name, VOID, vec![]);
let _ = init_fn.create_block("entry");
Expand Down Expand Up @@ -5711,6 +5737,10 @@ fn emit_string_pool(
{
let mut all_class_ids: Vec<u32> = Vec::new();
let mut anon_shape_ids: Vec<u32> = Vec::new();
// Also collect `(cid, name)` pairs so we can mirror Perry's
// user-visible class name into the runtime — V8 reads it back as
// `metatype.name` (#1021 NestJS module token factory).
let mut named_classes: Vec<(u32, String)> = Vec::new();
for (class_name, class) in classes.iter() {
if *class_name != class.name {
continue;
Expand All @@ -5729,6 +5759,8 @@ fn emit_string_pool(
// class ref.
if class_name.starts_with("__AnonShape_") {
anon_shape_ids.push(cid);
} else {
named_classes.push((cid, class_name.clone()));
}
}
all_class_ids.sort_unstable();
Expand All @@ -5747,6 +5779,24 @@ fn emit_string_pool(
&[(crate::types::I32, &cid.to_string())],
);
}
// (Class-name registration uses pre-allocated string constants — see
// `named_class_name_constants` below.) Drop the named_classes
// collection here since the pre-computed list is what we'll emit.
let _ = named_classes;
}
// Mirror class names into the runtime so the V8 bridge can surface them
// as `metatype.name`. Strings were pre-allocated above before `init_fn`
// borrowed `llmod`. (#1021 NestJS.)
for (cid, const_name, byte_len) in &named_class_name_constants {
let const_ref = format!("@{}", const_name);
blk.call_void(
"js_register_class_name",
&[
(crate::types::I32, &cid.to_string()),
(crate::types::PTR, &const_ref),
(crate::types::I32, &byte_len.to_string()),
],
);
}

// Refs #486 (hono logger middleware): also register every class
Expand Down
4 changes: 4 additions & 0 deletions crates/perry-codegen/src/runtime_decls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -700,6 +700,10 @@ pub fn declare_phase_b_strings(module: &mut LlModule) {
module.declare_function("js_instanceof_dynamic", DOUBLE, &[DOUBLE, DOUBLE]);
module.declare_function("js_register_class_extends_error", VOID, &[I32]);
module.declare_function("js_register_class_id", VOID, &[I32]);
// #1021 NestJS: surface Perry class names to V8 so `metatype.name`
// is non-empty. Codegen emits one call per registered class id at
// program init, mirroring `js_register_class_id`.
module.declare_function("js_register_class_name", VOID, &[I32, PTR, I32]);
// Anon-shape class registration so `.constructor` reads on object
// literals (`{ x: 1 }`) return the global `Object` constructor
// instead of the synthetic class ref. Refs #968 / date-fns
Expand Down
6 changes: 6 additions & 0 deletions crates/perry-jsruntime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ bytes = "1.5"
# `perry-stdlib`'s `crypto` feature so we don't duplicate the dep graph.
hmac = "0.12"
sha2 = "0.10"
# Plain hash digests for `op_perry_hash` so the V8-side
# `crypto.createHash(...).update(...).digest('hex')` path returns real
# hashes instead of empty strings — load-bearing for NestJS's
# `ModuleTokenFactory` (#1021).
sha1 = "0.10"
md-5 = "0.10"

[features]
default = []
Loading
Loading