diff --git a/Cargo.lock b/Cargo.lock index b17f4f075..5f00ed470 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5283,7 +5283,7 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "perry" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "anyhow", "base64", @@ -5340,14 +5340,14 @@ dependencies = [ [[package]] name = "perry-api-manifest" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "serde", ] [[package]] name = "perry-audio-miniaudio" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "cc", "libc", @@ -5355,7 +5355,7 @@ dependencies = [ [[package]] name = "perry-codegen" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "anyhow", "log", @@ -5370,7 +5370,7 @@ dependencies = [ [[package]] name = "perry-codegen-arkts" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "anyhow", "perry-hir", @@ -5379,7 +5379,7 @@ dependencies = [ [[package]] name = "perry-codegen-glance" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "anyhow", "perry-hir", @@ -5387,7 +5387,7 @@ dependencies = [ [[package]] name = "perry-codegen-js" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "anyhow", "perry-dispatch", @@ -5397,7 +5397,7 @@ dependencies = [ [[package]] name = "perry-codegen-swiftui" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "anyhow", "perry-hir", @@ -5406,7 +5406,7 @@ dependencies = [ [[package]] name = "perry-codegen-wasm" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "anyhow", "base64", @@ -5419,7 +5419,7 @@ dependencies = [ [[package]] name = "perry-codegen-wear-tiles" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "anyhow", "perry-hir", @@ -5427,7 +5427,7 @@ dependencies = [ [[package]] name = "perry-container-compose" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "anyhow", "async-trait", @@ -5456,14 +5456,14 @@ dependencies = [ [[package]] name = "perry-container-e2e" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "anyhow", ] [[package]] name = "perry-diagnostics" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "serde", "serde_json", @@ -5471,7 +5471,7 @@ dependencies = [ [[package]] name = "perry-dispatch" -version = "0.5.1190" +version = "0.5.1191" [[package]] name = "perry-doc-fixture-my-bindings" @@ -5482,7 +5482,7 @@ dependencies = [ [[package]] name = "perry-doc-tests" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "anyhow", "clap", @@ -5497,14 +5497,14 @@ dependencies = [ [[package]] name = "perry-ext-ads" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "perry-ffi", ] [[package]] name = "perry-ext-argon2" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "argon2", "perry-ffi", @@ -5512,7 +5512,7 @@ dependencies = [ [[package]] name = "perry-ext-axios" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "perry-ffi", "reqwest", @@ -5521,7 +5521,7 @@ dependencies = [ [[package]] name = "perry-ext-bcrypt" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "bcrypt", "perry-ffi", @@ -5529,7 +5529,7 @@ dependencies = [ [[package]] name = "perry-ext-better-sqlite3" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "perry-ffi", "rusqlite", @@ -5537,7 +5537,7 @@ dependencies = [ [[package]] name = "perry-ext-cheerio" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "perry-ffi", "scraper", @@ -5545,7 +5545,7 @@ dependencies = [ [[package]] name = "perry-ext-commander" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "perry-ffi", "perry-runtime", @@ -5553,7 +5553,7 @@ dependencies = [ [[package]] name = "perry-ext-cron" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "chrono", "cron 0.16.0", @@ -5563,7 +5563,7 @@ dependencies = [ [[package]] name = "perry-ext-dayjs" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "chrono", "perry-ffi", @@ -5571,7 +5571,7 @@ dependencies = [ [[package]] name = "perry-ext-decimal" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "perry-ffi", "rust_decimal", @@ -5579,7 +5579,7 @@ dependencies = [ [[package]] name = "perry-ext-dotenv" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "perry-ffi", "serde_json", @@ -5587,7 +5587,7 @@ dependencies = [ [[package]] name = "perry-ext-ethers" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "perry-ffi", "rand 0.8.6", @@ -5595,7 +5595,7 @@ dependencies = [ [[package]] name = "perry-ext-events" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "perry-ffi", "perry-runtime", @@ -5603,14 +5603,14 @@ dependencies = [ [[package]] name = "perry-ext-exponential-backoff" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "perry-ffi", ] [[package]] name = "perry-ext-fastify" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "bytes", "http-body-util", @@ -5627,7 +5627,7 @@ dependencies = [ [[package]] name = "perry-ext-fetch" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "lazy_static", "perry-ffi", @@ -5639,7 +5639,7 @@ dependencies = [ [[package]] name = "perry-ext-http" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "bytes", "lazy_static", @@ -5653,7 +5653,7 @@ dependencies = [ [[package]] name = "perry-ext-http-server" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "bytes", "h2", @@ -5676,7 +5676,7 @@ dependencies = [ [[package]] name = "perry-ext-ioredis" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "lazy_static", "perry-ffi", @@ -5686,7 +5686,7 @@ dependencies = [ [[package]] name = "perry-ext-jsonwebtoken" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "base64", "jsonwebtoken", @@ -5697,7 +5697,7 @@ dependencies = [ [[package]] name = "perry-ext-lru-cache" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "lru", "perry-ffi", @@ -5705,7 +5705,7 @@ dependencies = [ [[package]] name = "perry-ext-moment" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "chrono", "perry-ffi", @@ -5713,7 +5713,7 @@ dependencies = [ [[package]] name = "perry-ext-mongodb" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "bson", "futures-util", @@ -5725,7 +5725,7 @@ dependencies = [ [[package]] name = "perry-ext-mysql2" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "chrono", "perry-ffi", @@ -5735,7 +5735,7 @@ dependencies = [ [[package]] name = "perry-ext-nanoid" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "nanoid", "perry-ffi", @@ -5744,7 +5744,7 @@ dependencies = [ [[package]] name = "perry-ext-net" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "perry-ffi", "perry-runtime", @@ -5756,7 +5756,7 @@ dependencies = [ [[package]] name = "perry-ext-nodemailer" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "lettre", "perry-ffi", @@ -5766,7 +5766,7 @@ dependencies = [ [[package]] name = "perry-ext-pdf" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "perry-ffi", "printpdf", @@ -5774,7 +5774,7 @@ dependencies = [ [[package]] name = "perry-ext-pg" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "perry-ffi", "sqlx", @@ -5783,7 +5783,7 @@ dependencies = [ [[package]] name = "perry-ext-ratelimit" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "governor", "perry-ffi", @@ -5791,7 +5791,7 @@ dependencies = [ [[package]] name = "perry-ext-sharp" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "image", "perry-ffi", @@ -5799,14 +5799,14 @@ dependencies = [ [[package]] name = "perry-ext-slugify" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "perry-ffi", ] [[package]] name = "perry-ext-streams" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "lazy_static", "perry-ffi", @@ -5815,7 +5815,7 @@ dependencies = [ [[package]] name = "perry-ext-uuid" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "perry-ffi", "uuid", @@ -5823,7 +5823,7 @@ dependencies = [ [[package]] name = "perry-ext-validator" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "perry-ffi", "regex", @@ -5833,7 +5833,7 @@ dependencies = [ [[package]] name = "perry-ext-ws" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "futures-util", "lazy_static", @@ -5845,7 +5845,7 @@ dependencies = [ [[package]] name = "perry-ext-zlib" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "brotli", "flate2", @@ -5854,7 +5854,7 @@ dependencies = [ [[package]] name = "perry-ffi" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "dashmap", "once_cell", @@ -5863,7 +5863,7 @@ dependencies = [ [[package]] name = "perry-hir" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "anyhow", "perry-api-manifest", @@ -5881,7 +5881,7 @@ dependencies = [ [[package]] name = "perry-parser" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "anyhow", "perry-diagnostics", @@ -5893,7 +5893,7 @@ dependencies = [ [[package]] name = "perry-runtime" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "anyhow", "base64", @@ -5926,7 +5926,7 @@ dependencies = [ [[package]] name = "perry-stdlib" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "aes 0.8.4", "aes-gcm", @@ -6018,7 +6018,7 @@ dependencies = [ [[package]] name = "perry-transform" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "anyhow", "perry-hir", @@ -6028,7 +6028,7 @@ dependencies = [ [[package]] name = "perry-types" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "anyhow", "thiserror 1.0.69", @@ -6036,14 +6036,14 @@ dependencies = [ [[package]] name = "perry-ui" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "perry-ui-model", ] [[package]] name = "perry-ui-android" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "base64", "itoa", @@ -6060,7 +6060,7 @@ dependencies = [ [[package]] name = "perry-ui-geisterhand" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "rand 0.8.6", "serde", @@ -6070,7 +6070,7 @@ dependencies = [ [[package]] name = "perry-ui-gtk4" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "base64", "cairo-rs", @@ -6093,7 +6093,7 @@ dependencies = [ [[package]] name = "perry-ui-ios" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "base64", "block2", @@ -6109,7 +6109,7 @@ dependencies = [ [[package]] name = "perry-ui-macos" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "base64", "block2", @@ -6124,7 +6124,7 @@ dependencies = [ [[package]] name = "perry-ui-model" -version = "0.5.1190" +version = "0.5.1191" [[package]] name = "perry-ui-test" @@ -6132,11 +6132,11 @@ version = "0.1.0" [[package]] name = "perry-ui-testkit" -version = "0.5.1190" +version = "0.5.1191" [[package]] name = "perry-ui-tvos" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "base64", "block2", @@ -6152,7 +6152,7 @@ dependencies = [ [[package]] name = "perry-ui-visionos" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "base64", "block2", @@ -6168,7 +6168,7 @@ dependencies = [ [[package]] name = "perry-ui-watchos" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "block2", "libc", @@ -6181,7 +6181,7 @@ dependencies = [ [[package]] name = "perry-ui-windows" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "base64", "libc", @@ -6198,14 +6198,14 @@ dependencies = [ [[package]] name = "perry-ui-windows-winui" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "perry-ui-windows", ] [[package]] name = "perry-updater" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "base64", "ed25519-dalek", @@ -6219,7 +6219,7 @@ dependencies = [ [[package]] name = "perry-wasm-host" -version = "0.5.1190" +version = "0.5.1191" dependencies = [ "wasmi", ] diff --git a/crates/perry-hir/src/analysis.rs b/crates/perry-hir/src/analysis.rs index 75f2e57e9..d94a5adc7 100644 --- a/crates/perry-hir/src/analysis.rs +++ b/crates/perry-hir/src/analysis.rs @@ -15,10 +15,7 @@ pub(crate) use builtins::{ }; mod uses_this; -pub(crate) use uses_this::{ - closure_uses_new_target, closure_uses_this, uses_new_target_expr, uses_new_target_stmt, - uses_this_expr, uses_this_stmt, -}; +pub(crate) use uses_this::{closure_uses_new_target, closure_uses_this, uses_this_stmt}; mod value_types; pub use value_types::{infer_expr_type, infer_refinable_expr_type, HirTypeEnv, HirTypeFacts}; @@ -467,7 +464,7 @@ pub fn substitute_lexical_this_in_stmts(stmts: &mut [Stmt], replacement: &Expr) } fn substitute_lexical_this_in_stmt(stmt: &mut Stmt, replacement: &Expr) { - let mut on_expr = |e: &mut Expr| substitute_lexical_this_in_expr(e, replacement); + let on_expr = |e: &mut Expr| substitute_lexical_this_in_expr(e, replacement); match stmt { Stmt::Let { init, .. } => { if let Some(e) = init { diff --git a/crates/perry-hir/src/capability.rs b/crates/perry-hir/src/capability.rs index 65e2abc1e..b7484edd5 100644 --- a/crates/perry-hir/src/capability.rs +++ b/crates/perry-hir/src/capability.rs @@ -101,7 +101,7 @@ pub fn audit_module_capabilities( // `is_host = false`. Default-deny still safer than crash. Vec::new() }; - if allowed.iter().any(|t| *t == "*") { + if allowed.contains(&"*") { return Vec::new(); } let mut ctx = WalkCtx { @@ -227,7 +227,7 @@ fn visit_stmt(stmt: &Stmt, ctx: &mut WalkCtx) { fn visit_expr(expr: &Expr, ctx: &mut WalkCtx) { if let Some((cap, kind)) = required_capability(expr) { - if !ctx.allowed.iter().any(|t| *t == cap) { + if !ctx.allowed.contains(&cap) { ctx.violations.push(CapabilityViolation { source: ctx.source.clone(), package: ctx.package.clone(), diff --git a/crates/perry-hir/src/destructuring/helpers.rs b/crates/perry-hir/src/destructuring/helpers.rs index be6f71f36..e98aaca3e 100644 --- a/crates/perry-hir/src/destructuring/helpers.rs +++ b/crates/perry-hir/src/destructuring/helpers.rs @@ -146,7 +146,7 @@ pub(crate) fn ast_expr_contains_function_expr(e: &ast::Expr) -> bool { } Expr::New(n) => { ast_expr_contains_function_expr(&n.callee) - || n.args.as_ref().map_or(false, |args| { + || n.args.as_ref().is_some_and(|args| { args.iter() .any(|a| ast_expr_contains_function_expr(&a.expr)) }) diff --git a/crates/perry-hir/src/destructuring/mod.rs b/crates/perry-hir/src/destructuring/mod.rs index 5c2e0a067..d4563d714 100644 --- a/crates/perry-hir/src/destructuring/mod.rs +++ b/crates/perry-hir/src/destructuring/mod.rs @@ -40,6 +40,4 @@ pub(crate) use helpers::{ }; pub(crate) use pattern_binding::{lower_pattern_binding, lower_pattern_binding_into}; pub(crate) use var_decl::lower_var_decl_with_destructuring; -pub(crate) use var_decl_sources::{ - require_resolvable_native_specifier, resolvable_native_module_for_spec, -}; +pub(crate) use var_decl_sources::resolvable_native_module_for_spec; diff --git a/crates/perry-hir/src/destructuring/var_decl.rs b/crates/perry-hir/src/destructuring/var_decl.rs index b32e0a513..d254e63b8 100644 --- a/crates/perry-hir/src/destructuring/var_decl.rs +++ b/crates/perry-hir/src/destructuring/var_decl.rs @@ -1463,7 +1463,7 @@ pub(crate) fn lower_var_decl_with_destructuring( ) || decl .init .as_deref() - .map_or(false, ast_expr_contains_function_expr); + .is_some_and(ast_expr_contains_function_expr); let pre_id = if is_function_expr_init && !ctx.pre_registered_module_vars.contains(&name) && ctx.lookup_local(&name).is_none() @@ -1479,10 +1479,10 @@ pub(crate) fn lower_var_decl_with_destructuring( let init = decl.init.as_ref().map(|e| lower_expr(ctx, e)).transpose()?; if matches!(ty, Type::Any) { match &init { - Some(Expr::NativeMethodCall { module, method, .. }) => { - if module == "stream" && method == "from" { - ty = Type::Named("Readable".to_string()); - } + Some(Expr::NativeMethodCall { module, method, .. }) + if module == "stream" && method == "from" => + { + ty = Type::Named("Readable".to_string()); } Some(Expr::NewDynamic { callee, .. }) => { if let Expr::PropertyGet { object, property } = callee.as_ref() { @@ -1858,10 +1858,10 @@ pub(crate) fn lower_var_decl_with_destructuring( // recogniser later emits // `RegisterFunctionPrototypeMethod { func: // LocalGet(M_id), … }`. - Expr::LocalGet(src_local) => { - if ctx.function_valued_locals.contains(src_local) { - ctx.prototype_function_locals.insert(id, *src_local); - } + Expr::LocalGet(src_local) + if ctx.function_valued_locals.contains(src_local) => + { + ctx.prototype_function_locals.insert(id, *src_local); } _ => {} } diff --git a/crates/perry-hir/src/egress.rs b/crates/perry-hir/src/egress.rs index 845c4b66a..8d7f40129 100644 --- a/crates/perry-hir/src/egress.rs +++ b/crates/perry-hir/src/egress.rs @@ -236,6 +236,10 @@ fn visit_expr(expr: &Expr, ctx: &mut WalkCtx) { fn check_url(ctx: &mut WalkCtx, kind: &'static str, url: &Expr) { match url { + // NOTE: do not collapse this into a match-guard (`Expr::String(s) if ...`). + // An allowlisted literal must be accepted here, not fall through to the + // dynamic-host arm below. clippy's collapsible_if/match-guard rewrite + // changes the semantics; keep the explicit nested `if`. Expr::String(s) => { if !url_matches_allowlist(s, ctx.allowed_hosts) { ctx.violations.push(EgressViolation { @@ -260,6 +264,10 @@ fn check_url(ctx: &mut WalkCtx, kind: &'static str, url: &Expr) { fn check_host(ctx: &mut WalkCtx, kind: &'static str, host: &Expr) { match host { + // NOTE: do not collapse this into a match-guard (`Expr::String(s) if ...`). + // An allowlisted literal must be accepted here, not fall through to the + // dynamic-host arm below. clippy's collapsible_if/match-guard rewrite + // changes the semantics; keep the explicit nested `if`. Expr::String(s) => { if !host_matches_allowlist(s, ctx.allowed_hosts) { ctx.violations.push(EgressViolation { diff --git a/crates/perry-hir/src/js_transform/cross_module_natives.rs b/crates/perry-hir/src/js_transform/cross_module_natives.rs index fd36bb4ae..e73cf06c1 100644 --- a/crates/perry-hir/src/js_transform/cross_module_natives.rs +++ b/crates/perry-hir/src/js_transform/cross_module_natives.rs @@ -1,8 +1,6 @@ use crate::ir::{Expr, Module, ModuleKind, Stmt}; -use perry_types::LocalId; -use std::collections::{BTreeMap, HashMap, HashSet}; +use std::collections::{BTreeMap, HashMap}; -use super::*; /// Information about a native instance exported from another module #[derive(Debug, Clone)] pub struct ExportedNativeInstance { diff --git a/crates/perry-hir/src/js_transform/imports.rs b/crates/perry-hir/src/js_transform/imports.rs index dc40ff5de..2b5b7178c 100644 --- a/crates/perry-hir/src/js_transform/imports.rs +++ b/crates/perry-hir/src/js_transform/imports.rs @@ -1,8 +1,7 @@ use crate::ir::{Expr, Module, ModuleKind, Stmt}; use perry_types::LocalId; -use std::collections::{BTreeMap, HashMap, HashSet}; +use std::collections::{HashMap, HashSet}; -use super::*; /// Information about a JavaScript module import #[derive(Debug, Clone)] pub struct JsImportInfo { diff --git a/crates/perry-hir/src/js_transform/local_natives.rs b/crates/perry-hir/src/js_transform/local_natives.rs index b994ab162..8df8e96e5 100644 --- a/crates/perry-hir/src/js_transform/local_natives.rs +++ b/crates/perry-hir/src/js_transform/local_natives.rs @@ -1,8 +1,7 @@ -use crate::ir::{Expr, Module, ModuleKind, Stmt}; +use crate::ir::{Expr, Module, Stmt}; use perry_types::LocalId; -use std::collections::{BTreeMap, HashMap, HashSet}; +use std::collections::HashMap; -use super::*; /// Fix local native instance method calls within the same module /// /// This function tracks variables that are assigned from native module creation functions diff --git a/crates/perry-hir/src/js_transform/mod.rs b/crates/perry-hir/src/js_transform/mod.rs index fbf156797..53869a9a9 100644 --- a/crates/perry-hir/src/js_transform/mod.rs +++ b/crates/perry-hir/src/js_transform/mod.rs @@ -10,10 +10,6 @@ //! 6. Transforms new expressions for JS classes to JsNew //! 7. Wraps closures passed to JS functions with JsCreateCallback -use crate::ir::{Expr, Module, ModuleKind, Stmt}; -use perry_types::LocalId; -use std::collections::{BTreeMap, HashMap, HashSet}; - mod cross_module_natives; mod imports; mod local_natives; diff --git a/crates/perry-hir/src/lower/eval_super_scan.rs b/crates/perry-hir/src/lower/eval_super_scan.rs index fe8a163f0..93ffcdc3e 100644 --- a/crates/perry-hir/src/lower/eval_super_scan.rs +++ b/crates/perry-hir/src/lower/eval_super_scan.rs @@ -509,15 +509,11 @@ fn scan_expr(scan: &mut Scan, expr: &ast::Expr, transparent: bool) { E::PrivateName(p) => { scan.private_refs.push(format!("#{}", p.name)); } - E::Ident(id) => { - if transparent && id.sym.as_ref() == "arguments" { - scan.arguments_ref = true; - } + E::Ident(id) if transparent && id.sym.as_ref() == "arguments" => { + scan.arguments_ref = true; } - E::MetaProp(mp) => { - if transparent && mp.kind == ast::MetaPropKind::NewTarget { - scan.new_target = true; - } + E::MetaProp(mp) if transparent && mp.kind == ast::MetaPropKind::NewTarget => { + scan.new_target = true; } E::Unary(u) => scan_expr(scan, &u.arg, transparent), E::Update(u) => scan_expr(scan, &u.arg, transparent), diff --git a/crates/perry-hir/src/lower/expr_assign.rs b/crates/perry-hir/src/lower/expr_assign.rs index bd3ae1f90..0799b5dcb 100644 --- a/crates/perry-hir/src/lower/expr_assign.rs +++ b/crates/perry-hir/src/lower/expr_assign.rs @@ -685,19 +685,9 @@ fn lower_assignment_target( } else { None } - } else if let Some(func_id) = ctx.lookup_func(&cls_name) { - // Top-level / globally-registered function - // without a corresponding local binding - // (rare; most function decls also get a - // local). FuncRef lowering produces the - // singleton wrapper closure — paired - // with the matching `new` site that - // also lowers `` through FuncRef - // (the codegen-side `try_static_class_name` - // path), the bits agree. - Some(ProtoOwner::Func(Expr::FuncRef(func_id))) } else { - None + ctx.lookup_func(&cls_name) + .map(|func_id| ProtoOwner::Func(Expr::FuncRef(func_id))) } } else { None @@ -724,12 +714,11 @@ fn lower_assignment_target( ctx.prototype_function_aliases.get(&id).copied() { Some(ProtoOwner::Func(Expr::FuncRef(func_id))) - } else if let Some(src_local) = - ctx.prototype_function_locals.get(&id).copied() - { - Some(ProtoOwner::Func(Expr::LocalGet(src_local))) } else { - None + ctx.prototype_function_locals + .get(&id) + .copied() + .map(|src_local| ProtoOwner::Func(Expr::LocalGet(src_local))) } } else { None diff --git a/crates/perry-hir/src/lower/expr_call/array_only_methods.rs b/crates/perry-hir/src/lower/expr_call/array_only_methods.rs index 0a7e04eb5..b0ce37dbb 100644 --- a/crates/perry-hir/src/lower/expr_call/array_only_methods.rs +++ b/crates/perry-hir/src/lower/expr_call/array_only_methods.rs @@ -2,12 +2,11 @@ //! //! Extracted from `expr_call/mod.rs` as a mechanical move. -use anyhow::{anyhow, Result}; -use perry_types::{LocalId, Type}; +use anyhow::Result; +use perry_types::Type; use swc_ecma_ast as ast; use crate::ir::*; -use crate::lower_types::extract_ts_type_with_ctx; /// Is `expr` a reference to a node:stream class constructor — bare /// (`Readable`) or namespaced (`stream.Readable`)? Used by @@ -240,10 +239,7 @@ fn chain_roots_at_iterator_from(expr: &ast::Expr) -> bool { } } -use super::super::{ - extract_typed_parse_source_order, is_generator_call_expr, is_widget_modifier_name, lower_expr, - resolve_typed_parse_ty, LoweringContext, -}; +use super::super::{lower_expr, LoweringContext}; pub(super) fn try_array_only_methods( ctx: &mut LoweringContext, @@ -438,11 +434,7 @@ pub(super) fn try_array_only_methods( ) || ctx .fetch_call_response_locals .contains(obj_ident.sym.as_ref())); - if is_fetch_headers { - true - } else { - false - } + is_fetch_headers } else { false } @@ -1161,7 +1153,7 @@ pub(super) fn try_array_only_methods( // final length, which is exactly what the last // element of the `Sequence` yields. (#4508) let mut stmts: Vec = Vec::with_capacity(args.len()); - for (ast_arg, arg) in call.args.iter().zip(args.into_iter()) { + for (ast_arg, arg) in call.args.iter().zip(args) { let method = if ast_arg.spread.is_some() { "push_spread" } else { diff --git a/crates/perry-hir/src/lower/expr_call/globals.rs b/crates/perry-hir/src/lower/expr_call/globals.rs index c0c7f7001..7bf19cc74 100644 --- a/crates/perry-hir/src/lower/expr_call/globals.rs +++ b/crates/perry-hir/src/lower/expr_call/globals.rs @@ -3,16 +3,11 @@ //! Extracted from `expr_call/mod.rs` as a mechanical move. use anyhow::{anyhow, Result}; -use perry_types::{LocalId, Type}; use swc_ecma_ast as ast; use crate::ir::*; -use crate::lower_types::extract_ts_type_with_ctx; -use super::super::{ - extract_typed_parse_source_order, is_generator_call_expr, is_widget_modifier_name, lower_expr, - resolve_typed_parse_ty, LoweringContext, -}; +use super::super::{lower_expr, LoweringContext}; use super::os::user_info_expr_for_call; pub(super) fn try_global_builtins( @@ -492,125 +487,105 @@ pub(super) fn try_global_builtins( if let Some((module_name, _method)) = ctx.lookup_native_module(func_name) { if module_name == "child_process" { match func_name { - "execSync" => { - if !args.is_empty() { - let mut args_iter = args.into_iter(); - let command = args_iter.next().unwrap(); - let options = args_iter.next().map(Box::new); - return Ok(Ok(Expr::ChildProcessExecSync { - command: Box::new(command), - options, - })); - } + "execSync" if !args.is_empty() => { + let mut args_iter = args.into_iter(); + let command = args_iter.next().unwrap(); + let options = args_iter.next().map(Box::new); + return Ok(Ok(Expr::ChildProcessExecSync { + command: Box::new(command), + options, + })); } - "spawnSync" => { - if !args.is_empty() { - let mut args_iter = args.into_iter(); - let command = args_iter.next().unwrap(); - let spawn_args = args_iter.next().map(Box::new); - let options = args_iter.next().map(Box::new); - return Ok(Ok(Expr::ChildProcessSpawnSync { - command: Box::new(command), - args: spawn_args, - options, - })); - } + "spawnSync" if !args.is_empty() => { + let mut args_iter = args.into_iter(); + let command = args_iter.next().unwrap(); + let spawn_args = args_iter.next().map(Box::new); + let options = args_iter.next().map(Box::new); + return Ok(Ok(Expr::ChildProcessSpawnSync { + command: Box::new(command), + args: spawn_args, + options, + })); } - "spawn" => { - if !args.is_empty() { - let mut args_iter = args.into_iter(); - let command = args_iter.next().unwrap(); - let spawn_args = args_iter.next().map(Box::new); - let options = args_iter.next().map(Box::new); - return Ok(Ok(Expr::ChildProcessSpawn { - command: Box::new(command), - args: spawn_args, - options, - })); - } + "spawn" if !args.is_empty() => { + let mut args_iter = args.into_iter(); + let command = args_iter.next().unwrap(); + let spawn_args = args_iter.next().map(Box::new); + let options = args_iter.next().map(Box::new); + return Ok(Ok(Expr::ChildProcessSpawn { + command: Box::new(command), + args: spawn_args, + options, + })); } - "fork" => { - if !args.is_empty() { - let mut args_iter = args.into_iter(); - let module = args_iter.next().unwrap(); - let fork_args = args_iter.next().map(Box::new); - let options = args_iter.next().map(Box::new); - return Ok(Ok(Expr::ChildProcessFork { - module: Box::new(module), - args: fork_args, - options, - })); - } + "fork" if !args.is_empty() => { + let mut args_iter = args.into_iter(); + let module = args_iter.next().unwrap(); + let fork_args = args_iter.next().map(Box::new); + let options = args_iter.next().map(Box::new); + return Ok(Ok(Expr::ChildProcessFork { + module: Box::new(module), + args: fork_args, + options, + })); } - "exec" => { - if !args.is_empty() { - let mut args_iter = args.into_iter(); - let command = args_iter.next().unwrap(); - let options = args_iter.next().map(Box::new); - let callback = args_iter.next().map(Box::new); - return Ok(Ok(Expr::ChildProcessExec { - command: Box::new(command), - options, - callback, - })); - } + "exec" if !args.is_empty() => { + let mut args_iter = args.into_iter(); + let command = args_iter.next().unwrap(); + let options = args_iter.next().map(Box::new); + let callback = args_iter.next().map(Box::new); + return Ok(Ok(Expr::ChildProcessExec { + command: Box::new(command), + options, + callback, + })); } - "execFile" => { - if !args.is_empty() { - let mut args_iter = args.into_iter(); - let file = args_iter.next().unwrap(); - let file_args = args_iter.next().map(Box::new); - let options = args_iter.next().map(Box::new); - let callback = args_iter.next().map(Box::new); - return Ok(Ok(Expr::ChildProcessExecFile { - file: Box::new(file), - args: file_args, - options, - callback, - })); - } + "execFile" if !args.is_empty() => { + let mut args_iter = args.into_iter(); + let file = args_iter.next().unwrap(); + let file_args = args_iter.next().map(Box::new); + let options = args_iter.next().map(Box::new); + let callback = args_iter.next().map(Box::new); + return Ok(Ok(Expr::ChildProcessExecFile { + file: Box::new(file), + args: file_args, + options, + callback, + })); } - "execFileSync" => { - if !args.is_empty() { - let mut args_iter = args.into_iter(); - let file = args_iter.next().unwrap(); - let file_args = args_iter.next().map(Box::new); - let options = args_iter.next().map(Box::new); - return Ok(Ok(Expr::ChildProcessExecFileSync { - file: Box::new(file), - args: file_args, - options, - })); - } + "execFileSync" if !args.is_empty() => { + let mut args_iter = args.into_iter(); + let file = args_iter.next().unwrap(); + let file_args = args_iter.next().map(Box::new); + let options = args_iter.next().map(Box::new); + return Ok(Ok(Expr::ChildProcessExecFileSync { + file: Box::new(file), + args: file_args, + options, + })); } - "spawnBackground" => { - if args.len() >= 3 { - let mut args_iter = args.into_iter(); - let command = args_iter.next().unwrap(); - let spawn_args = args_iter.next().map(Box::new); - let log_file = args_iter.next().unwrap(); - let env_json = args_iter.next().map(Box::new); - return Ok(Ok(Expr::ChildProcessSpawnBackground { - command: Box::new(command), - args: spawn_args, - log_file: Box::new(log_file), - env_json, - })); - } + "spawnBackground" if args.len() >= 3 => { + let mut args_iter = args.into_iter(); + let command = args_iter.next().unwrap(); + let spawn_args = args_iter.next().map(Box::new); + let log_file = args_iter.next().unwrap(); + let env_json = args_iter.next().map(Box::new); + return Ok(Ok(Expr::ChildProcessSpawnBackground { + command: Box::new(command), + args: spawn_args, + log_file: Box::new(log_file), + env_json, + })); } - "getProcessStatus" => { - if !args.is_empty() { - return Ok(Ok(Expr::ChildProcessGetProcessStatus(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "getProcessStatus" if !args.is_empty() => { + return Ok(Ok(Expr::ChildProcessGetProcessStatus(Box::new( + args.into_iter().next().unwrap(), + )))); } - "killProcess" => { - if !args.is_empty() { - return Ok(Ok(Expr::ChildProcessKillProcess(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "killProcess" if !args.is_empty() => { + return Ok(Ok(Expr::ChildProcessKillProcess(Box::new( + args.into_iter().next().unwrap(), + )))); } _ => {} // Fall through } @@ -635,12 +610,10 @@ pub(super) fn try_global_builtins( } return Ok(Ok(result)); } - "dirname" => { - if !args.is_empty() { - return Ok(Ok(Expr::PathDirname(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "dirname" if !args.is_empty() => { + return Ok(Ok(Expr::PathDirname(Box::new( + args.into_iter().next().unwrap(), + )))); } "basename" => { if args.len() >= 2 { @@ -658,12 +631,10 @@ pub(super) fn try_global_builtins( )))); } } - "extname" => { - if !args.is_empty() { - return Ok(Ok(Expr::PathExtname(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "extname" if !args.is_empty() => { + return Ok(Ok(Expr::PathExtname(Box::new( + args.into_iter().next().unwrap(), + )))); } "resolve" => { if args.is_empty() { @@ -682,59 +653,45 @@ pub(super) fn try_global_builtins( return Ok(Ok(Expr::PathResolve(Box::new(joined)))); } } - "isAbsolute" => { - if !args.is_empty() { - return Ok(Ok(Expr::PathIsAbsolute(Box::new( - args.into_iter().next().unwrap(), - )))); - } - } - "relative" => { - if args.len() >= 2 { - let mut iter = args.into_iter(); - let from = iter.next().unwrap(); - let to = iter.next().unwrap(); - return Ok(Ok(Expr::PathRelative(Box::new(from), Box::new(to)))); - } - } - "normalize" => { - if !args.is_empty() { - return Ok(Ok(Expr::PathNormalize(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "isAbsolute" if !args.is_empty() => { + return Ok(Ok(Expr::PathIsAbsolute(Box::new( + args.into_iter().next().unwrap(), + )))); } - "parse" => { - if !args.is_empty() { - return Ok(Ok(Expr::PathParse(Box::new( - args.into_iter().next().unwrap(), - )))); - } - } - "format" => { - if !args.is_empty() { - return Ok(Ok(Expr::PathFormat(Box::new( - args.into_iter().next().unwrap(), - )))); - } - } - "toNamespacedPath" | "_makeLong" => { - if !args.is_empty() { - return Ok(Ok(Expr::PathToNamespacedPath(Box::new( - args.into_iter().next().unwrap(), - )))); - } - } - "matchesGlob" => { - if args.len() >= 2 { - let mut iter = args.into_iter(); - let path_arg = iter.next().unwrap(); - let pattern = iter.next().unwrap(); - return Ok(Ok(Expr::PathMatchesGlob( - Box::new(path_arg), - Box::new(pattern), - ))); - } + "relative" if args.len() >= 2 => { + let mut iter = args.into_iter(); + let from = iter.next().unwrap(); + let to = iter.next().unwrap(); + return Ok(Ok(Expr::PathRelative(Box::new(from), Box::new(to)))); + } + "normalize" if !args.is_empty() => { + return Ok(Ok(Expr::PathNormalize(Box::new( + args.into_iter().next().unwrap(), + )))); + } + "parse" if !args.is_empty() => { + return Ok(Ok(Expr::PathParse(Box::new( + args.into_iter().next().unwrap(), + )))); + } + "format" if !args.is_empty() => { + return Ok(Ok(Expr::PathFormat(Box::new( + args.into_iter().next().unwrap(), + )))); + } + "toNamespacedPath" | "_makeLong" if !args.is_empty() => { + return Ok(Ok(Expr::PathToNamespacedPath(Box::new( + args.into_iter().next().unwrap(), + )))); + } + "matchesGlob" if args.len() >= 2 => { + let mut iter = args.into_iter(); + let path_arg = iter.next().unwrap(); + let pattern = iter.next().unwrap(); + return Ok(Ok(Expr::PathMatchesGlob( + Box::new(path_arg), + Box::new(pattern), + ))); } _ => {} // Fall through } @@ -743,17 +700,16 @@ pub(super) fn try_global_builtins( // Check if this is a named import from url (e.g., fileURLToPath) if module_name == "url" { match func_name { - "fileURLToPath" => { + "fileURLToPath" // Only the 1-arg form takes the dedicated fast path. The // 2-arg form `fileURLToPath(url, { windows })` (#2975) // must fall through to the native dispatch table so the // options object reaches the runtime. - if args.len() == 1 { + if args.len() == 1 => { return Ok(Ok(Expr::FileURLToPath(Box::new( args.into_iter().next().unwrap(), )))); } - } _ => {} // Fall through } } @@ -761,70 +717,51 @@ pub(super) fn try_global_builtins( // Check if this is a named import from fs (e.g., existsSync, mkdirSync, etc.) if module_name == "fs" { match func_name { - "readFileSync" => { - if args.len() == 1 { - // readFileSync(path) without encoding — returns Buffer (Node parity) - return Ok(Ok(Expr::FsReadFileBinary(Box::new( - args.into_iter().next().unwrap(), - )))); - } - } - "writeFileSync" => { - if args.len() == 2 { - let mut iter = args.into_iter(); - let path = iter.next().unwrap(); - let content = iter.next().unwrap(); - return Ok(Ok(Expr::FsWriteFileSync( - Box::new(path), - Box::new(content), - ))); - } - } - "existsSync" => { - if !args.is_empty() { - return Ok(Ok(Expr::FsExistsSync(Box::new( - args.into_iter().next().unwrap(), - )))); - } - } - "mkdirSync" => { - if args.len() == 1 { - return Ok(Ok(Expr::FsMkdirSync(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "readFileSync" if args.len() == 1 => { + // readFileSync(path) without encoding — returns Buffer (Node parity) + return Ok(Ok(Expr::FsReadFileBinary(Box::new( + args.into_iter().next().unwrap(), + )))); } - "unlinkSync" => { - if !args.is_empty() { - return Ok(Ok(Expr::FsUnlinkSync(Box::new( - args.into_iter().next().unwrap(), - )))); - } - } - "appendFileSync" => { - if args.len() == 2 { - let mut iter = args.into_iter(); - let path = iter.next().unwrap(); - let content = iter.next().unwrap(); - return Ok(Ok(Expr::FsAppendFileSync( - Box::new(path), - Box::new(content), - ))); - } - } - "readFileBuffer" => { - if !args.is_empty() { - return Ok(Ok(Expr::FsReadFileBinary(Box::new( - args.into_iter().next().unwrap(), - )))); - } - } - "rmRecursive" => { - if !args.is_empty() { - return Ok(Ok(Expr::FsRmRecursive(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "writeFileSync" if args.len() == 2 => { + let mut iter = args.into_iter(); + let path = iter.next().unwrap(); + let content = iter.next().unwrap(); + return Ok(Ok(Expr::FsWriteFileSync(Box::new(path), Box::new(content)))); + } + "existsSync" if !args.is_empty() => { + return Ok(Ok(Expr::FsExistsSync(Box::new( + args.into_iter().next().unwrap(), + )))); + } + "mkdirSync" if args.len() == 1 => { + return Ok(Ok(Expr::FsMkdirSync(Box::new( + args.into_iter().next().unwrap(), + )))); + } + "unlinkSync" if !args.is_empty() => { + return Ok(Ok(Expr::FsUnlinkSync(Box::new( + args.into_iter().next().unwrap(), + )))); + } + "appendFileSync" if args.len() == 2 => { + let mut iter = args.into_iter(); + let path = iter.next().unwrap(); + let content = iter.next().unwrap(); + return Ok(Ok(Expr::FsAppendFileSync( + Box::new(path), + Box::new(content), + ))); + } + "readFileBuffer" if !args.is_empty() => { + return Ok(Ok(Expr::FsReadFileBinary(Box::new( + args.into_iter().next().unwrap(), + )))); + } + "rmRecursive" if !args.is_empty() => { + return Ok(Ok(Expr::FsRmRecursive(Box::new( + args.into_iter().next().unwrap(), + )))); } // Issue #648 fallout: see twin arm above. "rmSync" => {} @@ -864,24 +801,22 @@ pub(super) fn try_global_builtins( // call-site form already exercises (handled in // `expr.rs` near the createHash/createHmac block) // so both shapes share one codegen path. - "createSecretKey" => { - if !args.is_empty() { - let mut iter = args.into_iter(); - let key_arg = iter.next().unwrap(); - let mut new_args = vec![key_arg]; - if let Some(enc) = iter.next() { - new_args.push(enc); - } - return Ok(Ok(Expr::Call { - callee: Box::new(Expr::PropertyGet { - object: Box::new(Expr::NativeModuleRef("crypto".to_string())), - property: "createSecretKey".to_string(), - }), - args: new_args, - type_args: vec![], - byte_offset: 0, - })); - } + "createSecretKey" if !args.is_empty() => { + let mut iter = args.into_iter(); + let key_arg = iter.next().unwrap(); + let mut new_args = vec![key_arg]; + if let Some(enc) = iter.next() { + new_args.push(enc); + } + return Ok(Ok(Expr::Call { + callee: Box::new(Expr::PropertyGet { + object: Box::new(Expr::NativeModuleRef("crypto".to_string())), + property: "createSecretKey".to_string(), + }), + args: new_args, + type_args: vec![], + byte_offset: 0, + })); } // #3927: `generateKeySync(alg, options)` from a named import. // Like createSecretKey above, rewrite to the dotted-form @@ -889,21 +824,19 @@ pub(super) fn try_global_builtins( // dedicated `js_crypto_generate_key_sync` dispatch in // `expr/calls.rs` (a generic NativeMethodCall has no runtime // dispatcher for it and returns undefined). - "generateKeySync" => { - if args.len() >= 2 { - let mut iter = args.into_iter(); - let alg_arg = iter.next().unwrap(); - let options_arg = iter.next().unwrap(); - return Ok(Ok(Expr::Call { - callee: Box::new(Expr::PropertyGet { - object: Box::new(Expr::NativeModuleRef("crypto".to_string())), - property: "generateKeySync".to_string(), - }), - args: vec![alg_arg, options_arg], - type_args: vec![], - byte_offset: 0, - })); - } + "generateKeySync" if args.len() >= 2 => { + let mut iter = args.into_iter(); + let alg_arg = iter.next().unwrap(); + let options_arg = iter.next().unwrap(); + return Ok(Ok(Expr::Call { + callee: Box::new(Expr::PropertyGet { + object: Box::new(Expr::NativeModuleRef("crypto".to_string())), + property: "generateKeySync".to_string(), + }), + args: vec![alg_arg, options_arg], + type_args: vec![], + byte_offset: 0, + })); } _ => {} // Fall through } diff --git a/crates/perry-hir/src/lower/expr_call/imported_array_methods.rs b/crates/perry-hir/src/lower/expr_call/imported_array_methods.rs index 00d340a4d..38d07960a 100644 --- a/crates/perry-hir/src/lower/expr_call/imported_array_methods.rs +++ b/crates/perry-hir/src/lower/expr_call/imported_array_methods.rs @@ -2,17 +2,13 @@ //! //! Extracted from `expr_call/mod.rs` as a mechanical move. -use anyhow::{anyhow, Result}; -use perry_types::{LocalId, Type}; +use anyhow::Result; +use perry_types::Type; use swc_ecma_ast as ast; use crate::ir::*; -use crate::lower_types::extract_ts_type_with_ctx; -use super::super::{ - extract_typed_parse_source_order, is_generator_call_expr, is_widget_modifier_name, lower_expr, - resolve_typed_parse_ty, LoweringContext, -}; +use super::super::LoweringContext; pub(super) fn try_imported_array_methods( ctx: &mut LoweringContext, @@ -78,8 +74,8 @@ pub(super) fn try_imported_array_methods( } // Fall through. } - "map" => { - if !args.is_empty() { + "map" + if !args.is_empty() => { let cb = args.into_iter().next().unwrap(); let cb = ctx.maybe_wrap_builtin_callback(cb, &call.args[0]); return Ok(Ok(Expr::ArrayMap { @@ -87,9 +83,8 @@ pub(super) fn try_imported_array_methods( callback: Box::new(cb), })); } - } - "filter" => { - if !args.is_empty() { + "filter" + if !args.is_empty() => { let cb = args.into_iter().next().unwrap(); let cb = ctx.maybe_wrap_builtin_callback(cb, &call.args[0]); return Ok(Ok(Expr::ArrayFilter { @@ -97,9 +92,8 @@ pub(super) fn try_imported_array_methods( callback: Box::new(cb), })); } - } - "forEach" => { - if !args.is_empty() { + "forEach" + if !args.is_empty() => { let cb = args.into_iter().next().unwrap(); let cb = ctx.maybe_wrap_builtin_callback(cb, &call.args[0]); return Ok(Ok(Expr::ArrayForEach { @@ -107,9 +101,8 @@ pub(super) fn try_imported_array_methods( callback: Box::new(cb), })); } - } - "find" => { - if !args.is_empty() { + "find" + if !args.is_empty() => { let cb = args.into_iter().next().unwrap(); let cb = ctx.maybe_wrap_builtin_callback(cb, &call.args[0]); return Ok(Ok(Expr::ArrayFind { @@ -117,8 +110,7 @@ pub(super) fn try_imported_array_methods( callback: Box::new(cb), })); } - } - "sort" => { + "sort" // Like `join` above: only fold when the // imported binding is statically Array-typed. // semver re-exports `sort = (list) => @@ -138,16 +130,15 @@ pub(super) fn try_imported_array_methods( Expr::ExternFuncRef { ref return_type, .. } if matches!(return_type, Type::Array(_)) ) - { + => { return Ok(Ok(Expr::ArraySort { array: Box::new(extern_ref), comparator: Box::new(args.into_iter().next().unwrap()), })); } - } - "indexOf" => { + "indexOf" // #2804: carry the optional fromIndex (2nd arg). - if !args.is_empty() { + if !args.is_empty() => { let mut it = args.into_iter(); let value = it.next().unwrap(); let from_index = it.next().map(Box::new); @@ -157,9 +148,8 @@ pub(super) fn try_imported_array_methods( from_index, })); } - } - "includes" => { - if !args.is_empty() { + "includes" + if !args.is_empty() => { let mut it = args.into_iter(); let value = it.next().unwrap(); let from_index = it.next().map(Box::new); @@ -169,9 +159,8 @@ pub(super) fn try_imported_array_methods( from_index, })); } - } - "slice" => { - if !args.is_empty() { + "slice" + if !args.is_empty() => { let mut args_iter = args.into_iter(); let start = args_iter.next().unwrap(); let end = args_iter.next(); @@ -181,9 +170,8 @@ pub(super) fn try_imported_array_methods( end: end.map(Box::new), })); } - } - "reduce" => { - if !args.is_empty() { + "reduce" + if !args.is_empty() => { let mut args_iter = args.into_iter(); let callback = args_iter.next().unwrap(); let initial = args_iter.next().map(Box::new); @@ -193,17 +181,15 @@ pub(super) fn try_imported_array_methods( initial, })); } - } - "flat" => { + "flat" // depth-aware calls fall through. - if args.is_empty() { + if args.is_empty() => { return Ok(Ok(Expr::ArrayFlat { array: Box::new(extern_ref), })); } - } - "reduceRight" => { - if !args.is_empty() { + "reduceRight" + if !args.is_empty() => { let mut args_iter = args.into_iter(); let callback = args_iter.next().unwrap(); let initial = args_iter.next().map(Box::new); @@ -213,7 +199,6 @@ pub(super) fn try_imported_array_methods( initial, })); } - } "toReversed" => { return Ok(Ok(Expr::ArrayToReversed { array: Box::new(extern_ref), @@ -244,8 +229,8 @@ pub(super) fn try_imported_array_methods( items, })); } - "with" => { - if args.len() >= 2 { + "with" + if args.len() >= 2 => { let mut args_iter = args.into_iter(); let index = args_iter.next().unwrap(); let value = args_iter.next().unwrap(); @@ -255,7 +240,6 @@ pub(super) fn try_imported_array_methods( value: Box::new(value), })); } - } "entries" => { return Ok(Ok(Expr::ArrayEntries(Box::new(extern_ref)))); } diff --git a/crates/perry-hir/src/lower/expr_call/inline_array_methods.rs b/crates/perry-hir/src/lower/expr_call/inline_array_methods.rs index 74f717056..18ba083ec 100644 --- a/crates/perry-hir/src/lower/expr_call/inline_array_methods.rs +++ b/crates/perry-hir/src/lower/expr_call/inline_array_methods.rs @@ -2,17 +2,12 @@ //! //! Extracted from `expr_call/mod.rs` as a mechanical move. -use anyhow::{anyhow, Result}; -use perry_types::{LocalId, Type}; +use anyhow::Result; use swc_ecma_ast as ast; use crate::ir::*; -use crate::lower_types::extract_ts_type_with_ctx; -use super::super::{ - extract_typed_parse_source_order, is_generator_call_expr, is_widget_modifier_name, lower_expr, - resolve_typed_parse_ty, LoweringContext, -}; +use super::super::{lower_expr, LoweringContext}; pub(super) fn try_inline_array_methods( ctx: &mut LoweringContext, @@ -63,8 +58,8 @@ pub(super) fn try_inline_array_methods( separator, })); } - "map" => { - if !args.is_empty() { + "map" + if !args.is_empty() => { let cb = args.into_iter().next().unwrap(); let cb = ctx.maybe_wrap_builtin_callback(cb, &call.args[0]); return Ok(Ok(Expr::ArrayMap { @@ -72,9 +67,8 @@ pub(super) fn try_inline_array_methods( callback: Box::new(cb), })); } - } - "filter" => { - if !args.is_empty() { + "filter" + if !args.is_empty() => { let cb = args.into_iter().next().unwrap(); let cb = ctx.maybe_wrap_builtin_callback(cb, &call.args[0]); return Ok(Ok(Expr::ArrayFilter { @@ -82,9 +76,8 @@ pub(super) fn try_inline_array_methods( callback: Box::new(cb), })); } - } - "forEach" => { - if !args.is_empty() { + "forEach" + if !args.is_empty() => { let cb = args.into_iter().next().unwrap(); let cb = ctx.maybe_wrap_builtin_callback(cb, &call.args[0]); return Ok(Ok(Expr::ArrayForEach { @@ -92,9 +85,8 @@ pub(super) fn try_inline_array_methods( callback: Box::new(cb), })); } - } - "find" => { - if !args.is_empty() { + "find" + if !args.is_empty() => { let cb = args.into_iter().next().unwrap(); let cb = ctx.maybe_wrap_builtin_callback(cb, &call.args[0]); return Ok(Ok(Expr::ArrayFind { @@ -102,18 +94,16 @@ pub(super) fn try_inline_array_methods( callback: Box::new(cb), })); } - } - "sort" => { - if !args.is_empty() { + "sort" + if !args.is_empty() => { return Ok(Ok(Expr::ArraySort { array: Box::new(array_expr), comparator: Box::new(args.into_iter().next().unwrap()), })); } - } - "indexOf" => { + "indexOf" // #2804: carry the optional fromIndex (2nd arg). - if !args.is_empty() { + if !args.is_empty() => { let mut it = args.into_iter(); let value = it.next().unwrap(); let from_index = it.next().map(Box::new); @@ -123,9 +113,8 @@ pub(super) fn try_inline_array_methods( from_index, })); } - } - "includes" => { - if !args.is_empty() { + "includes" + if !args.is_empty() => { let mut it = args.into_iter(); let value = it.next().unwrap(); let from_index = it.next().map(Box::new); @@ -135,9 +124,8 @@ pub(super) fn try_inline_array_methods( from_index, })); } - } - "slice" => { - if !args.is_empty() { + "slice" + if !args.is_empty() => { let mut args_iter = args.into_iter(); let start = args_iter.next().unwrap(); let end = args_iter.next(); @@ -147,9 +135,8 @@ pub(super) fn try_inline_array_methods( end: end.map(Box::new), })); } - } - "reduce" => { - if !args.is_empty() { + "reduce" + if !args.is_empty() => { let mut args_iter = args.into_iter(); let callback = args_iter.next().unwrap(); let initial = args_iter.next().map(Box::new); @@ -159,17 +146,15 @@ pub(super) fn try_inline_array_methods( initial, })); } - } - "flat" => { + "flat" // depth-aware calls fall through. - if args.is_empty() { + if args.is_empty() => { return Ok(Ok(Expr::ArrayFlat { array: Box::new(array_expr), })); } - } - "reduceRight" => { - if !args.is_empty() { + "reduceRight" + if !args.is_empty() => { let mut args_iter = args.into_iter(); let callback = args_iter.next().unwrap(); let initial = args_iter.next().map(Box::new); @@ -179,7 +164,6 @@ pub(super) fn try_inline_array_methods( initial, })); } - } "toReversed" => { return Ok(Ok(Expr::ArrayToReversed { array: Box::new(array_expr), @@ -210,8 +194,8 @@ pub(super) fn try_inline_array_methods( items, })); } - "with" => { - if args.len() >= 2 { + "with" + if args.len() >= 2 => { let mut args_iter = args.into_iter(); let index = args_iter.next().unwrap(); let value = args_iter.next().unwrap(); @@ -221,7 +205,6 @@ pub(super) fn try_inline_array_methods( value: Box::new(value), })); } - } "entries" => { return Ok(Ok(Expr::ArrayEntries(Box::new(array_expr)))); } diff --git a/crates/perry-hir/src/lower/expr_call/local_array_methods.rs b/crates/perry-hir/src/lower/expr_call/local_array_methods.rs index 292411452..b645f0b13 100644 --- a/crates/perry-hir/src/lower/expr_call/local_array_methods.rs +++ b/crates/perry-hir/src/lower/expr_call/local_array_methods.rs @@ -2,18 +2,14 @@ //! //! Extracted from `expr_call/mod.rs` as a mechanical move. -use anyhow::{anyhow, Result}; -use perry_types::{LocalId, Type}; +use anyhow::Result; +use perry_types::Type; use swc_ecma_ast as ast; use super::url_search_params::build_url_search_params_method_call; use crate::ir::*; -use crate::lower_types::extract_ts_type_with_ctx; -use super::super::{ - extract_typed_parse_source_order, is_generator_call_expr, is_widget_modifier_name, lower_expr, - resolve_typed_parse_ty, LoweringContext, -}; +use super::super::{lower_expr, LoweringContext}; /// True when `recv_ty` is a statically-known class/namespace instance type /// (a `Named` or `Generic` type that is not itself an array). Used to gate @@ -316,7 +312,7 @@ pub(super) fn try_local_array_methods( })); } let mut stmts: Vec = Vec::with_capacity(args.len()); - for (ast_arg, arg) in call.args.iter().zip(args.into_iter()) { + for (ast_arg, arg) in call.args.iter().zip(args) { if ast_arg.spread.is_some() { stmts.push(Expr::ArrayPushSpread { array_id, @@ -353,21 +349,20 @@ pub(super) fn try_local_array_methods( "shift" => { return Ok(Ok(Expr::ArrayShift(array_id))); } - "unshift" => { + "unshift" // #2814: the single-value fast path only handles // exactly one argument. Zero-arg and multi-arg // calls fall through to generic dispatch, which // routes to the variadic runtime helper. - if args.len() == 1 { + if args.len() == 1 => { return Ok(Ok(Expr::ArrayUnshift { array_id, value: Box::new(args.into_iter().next().unwrap()), })); } - } - "indexOf" => { + "indexOf" // #2804: carry the optional fromIndex (2nd arg). - if !args.is_empty() { + if !args.is_empty() => { let mut it = args.into_iter(); let value = it.next().unwrap(); let from_index = it.next().map(Box::new); @@ -377,9 +372,8 @@ pub(super) fn try_local_array_methods( from_index, })); } - } - "includes" => { - if !args.is_empty() { + "includes" + if !args.is_empty() => { let mut it = args.into_iter(); let value = it.next().unwrap(); let from_index = it.next().map(Box::new); @@ -389,14 +383,13 @@ pub(super) fn try_local_array_methods( from_index, })); } - } // arr.lastIndexOf(value, fromIndex?) — route to the // array runtime fn. Without this, a known-not-string // / typed-array local fell through to the *string* // lastIndexOf (#2457): `new Int32Array(...).lastIndexOf` // threw "(number).lastIndexOf is not a function". - "lastIndexOf" => { - if !args.is_empty() { + "lastIndexOf" + if !args.is_empty() => { let mut it = args.into_iter(); let value = it.next().unwrap(); let from_index = it.next().map(Box::new); @@ -406,7 +399,6 @@ pub(super) fn try_local_array_methods( from_index, })); } - } "slice" => { // arr.slice(start, end?) - returns new array // Only convert to ArraySlice if we KNOW it's an Array type @@ -566,8 +558,8 @@ pub(super) fn try_local_array_methods( } } } - "flatMap" => { - if !args.is_empty() { + "flatMap" + if !args.is_empty() => { let cb = args.into_iter().next().unwrap(); let cb = ctx.maybe_wrap_builtin_callback(cb, &call.args[0]); return Ok(Ok(Expr::ArrayFlatMap { @@ -575,8 +567,7 @@ pub(super) fn try_local_array_methods( callback: Box::new(cb), })); } - } - "sort" => { + "sort" // semver `module.exports.sort = (list) => …` is // re-exported as a plain function and called as // `semver.sort(list)`. The receiver there is a @@ -589,15 +580,14 @@ pub(super) fn try_local_array_methods( // the `map`/`filter`/`with` guards). if !args.is_empty() && !receiver_is_class_instance(ctx.lookup_local_type(&arr_name)) - { + => { return Ok(Ok(Expr::ArraySort { array: Box::new(Expr::LocalGet(array_id)), comparator: Box::new(args.into_iter().next().unwrap()), })); } - } - "reduce" => { - if !args.is_empty() { + "reduce" + if !args.is_empty() => { let mut args_iter = args.into_iter(); let callback = args_iter.next().unwrap(); let initial = args_iter.next().map(Box::new); @@ -607,7 +597,6 @@ pub(super) fn try_local_array_methods( initial, })); } - } "join" => { // arr.join(separator?) -> string let separator = args.into_iter().next().map(Box::new); @@ -616,20 +605,19 @@ pub(super) fn try_local_array_methods( separator, })); } - "flat" => { + "flat" // arr.flat() folds to depth=1 fast path; // arr.flat(depth) falls through so the // depth arg can reach the codegen // `lower_array_method.rs::flat` arm and // route to `js_array_flat_depth`. - if args.is_empty() { + if args.is_empty() => { return Ok(Ok(Expr::ArrayFlat { array: Box::new(Expr::LocalGet(array_id)), })); } - } - "reduceRight" => { - if !args.is_empty() { + "reduceRight" + if !args.is_empty() => { let mut args_iter = args.into_iter(); let callback = args_iter.next().unwrap(); let initial = args_iter.next().map(Box::new); @@ -639,7 +627,6 @@ pub(super) fn try_local_array_methods( initial, })); } - } "toReversed" => { return Ok(Ok(Expr::ArrayToReversed { array: Box::new(Expr::LocalGet(array_id)), @@ -1003,19 +990,17 @@ pub(super) fn try_local_array_methods( .lookup_local_type(&arr_name) .map(|ty| matches!(ty, Type::Named(name) if name == "TextDecoder")) .unwrap_or(false); - if is_text_decoder { - if method_name == "decode" { - let decoder = lower_expr(ctx, &member.obj)?; - let input = if !args.is_empty() { - args.into_iter().next().unwrap() - } else { - Expr::Undefined - }; - return Ok(Ok(Expr::TextDecoderDecode { - decoder: Box::new(decoder), - input: Box::new(input), - })); - } + if is_text_decoder && method_name == "decode" { + let decoder = lower_expr(ctx, &member.obj)?; + let input = if !args.is_empty() { + args.into_iter().next().unwrap() + } else { + Expr::Undefined + }; + return Ok(Ok(Expr::TextDecoderDecode { + decoder: Box::new(decoder), + input: Box::new(input), + })); } } } // close is_array_type check @@ -1029,12 +1014,10 @@ pub(super) fn try_local_array_methods( // Lower the object expression (e.g., 'this' or a local variable) let _object_expr = lower_expr(ctx, &obj_member.obj)?; - if method_name == "push" { - if !args.is_empty() { - // For now, fall through to generic Call handling - // We'll compile this in codegen using inline property access - // property-based push: object.{property}.push() - } + if method_name == "push" && !args.is_empty() { + // For now, fall through to generic Call handling + // We'll compile this in codegen using inline property access + // property-based push: object.{property}.push() } } } diff --git a/crates/perry-hir/src/lower/expr_call/mod.rs b/crates/perry-hir/src/lower/expr_call/mod.rs index f066dc3ef..d78a6919c 100644 --- a/crates/perry-hir/src/lower/expr_call/mod.rs +++ b/crates/perry-hir/src/lower/expr_call/mod.rs @@ -18,13 +18,9 @@ use anyhow::Result; use swc_ecma_ast as ast; use crate::ir::*; -use crate::lower_patterns::detect_native_instance_expr; use crate::lower_types::extract_ts_type_with_ctx; -use super::{ - extract_typed_parse_source_order, is_generator_call_expr, is_widget_modifier_name, lower_expr, - resolve_typed_parse_ty, LoweringContext, -}; +use super::{lower_expr, LoweringContext}; mod array_only_methods; mod crypto; diff --git a/crates/perry-hir/src/lower/expr_call/module_class_static.rs b/crates/perry-hir/src/lower/expr_call/module_class_static.rs index 05efa743f..4d8705819 100644 --- a/crates/perry-hir/src/lower/expr_call/module_class_static.rs +++ b/crates/perry-hir/src/lower/expr_call/module_class_static.rs @@ -2,19 +2,13 @@ //! //! Extracted from `expr_call/mod.rs` as a mechanical move. -use anyhow::{anyhow, Result}; -use perry_types::{LocalId, Type}; +use anyhow::Result; +use perry_types::Type; use swc_ecma_ast as ast; -use super::super::unimpl_hints; -use super::stream::is_stream_api_method; use crate::ir::*; -use crate::lower_types::extract_ts_type_with_ctx; -use super::super::{ - extract_typed_parse_source_order, is_generator_call_expr, is_widget_modifier_name, lower_expr, - resolve_typed_parse_ty, LoweringContext, -}; +use super::super::LoweringContext; pub(super) fn try_module_class_static( ctx: &mut LoweringContext, @@ -207,33 +201,29 @@ pub(super) fn try_module_class_static( if let ast::MemberProp::Ident(method_ident) = &outer_member.prop { let method_name = method_ident.sym.as_ref(); match (stream, method_name) { - ("stdin", "setRawMode") => { - if !args.is_empty() { - let arg = args.into_iter().next().unwrap(); - return Ok(Ok(Expr::ProcessStdinSetRawMode(Box::new(arg)))); - } + ("stdin", "setRawMode") if !args.is_empty() => { + let arg = args.into_iter().next().unwrap(); + return Ok(Ok(Expr::ProcessStdinSetRawMode(Box::new(arg)))); } - ("stdin", "on") | ("stdin", "addListener") => { - if args.len() >= 2 { - let mut iter = args.into_iter(); - let event = iter.next().unwrap(); - let handler = iter.next().unwrap(); - return Ok(Ok(Expr::ProcessStdinOn { - event: Box::new(event), - handler: Box::new(handler), - })); - } + ("stdin", "on") | ("stdin", "addListener") if args.len() >= 2 => { + let mut iter = args.into_iter(); + let event = iter.next().unwrap(); + let handler = iter.next().unwrap(); + return Ok(Ok(Expr::ProcessStdinOn { + event: Box::new(event), + handler: Box::new(handler), + })); } - ("stdin", "removeListener") | ("stdin", "off") => { - if args.len() >= 2 { - let mut iter = args.into_iter(); - let event = iter.next().unwrap(); - let handler = iter.next().unwrap(); - return Ok(Ok(Expr::ProcessStdinRemoveListener { - event: Box::new(event), - handler: Box::new(handler), - })); - } + ("stdin", "removeListener") | ("stdin", "off") + if args.len() >= 2 => + { + let mut iter = args.into_iter(); + let event = iter.next().unwrap(); + let handler = iter.next().unwrap(); + return Ok(Ok(Expr::ProcessStdinRemoveListener { + event: Box::new(event), + handler: Box::new(handler), + })); } ("stdin", "pause") => { return Ok(Ok(Expr::ProcessStdinLifecycle( @@ -260,16 +250,14 @@ pub(super) fn try_module_class_static( ProcessStdinLifecycleMethod::Destroy, ))); } - ("stdout", "on") => { - if args.len() >= 2 { - let mut iter = args.into_iter(); - let event = iter.next().unwrap(); - let handler = iter.next().unwrap(); - return Ok(Ok(Expr::ProcessStdoutOn { - event: Box::new(event), - handler: Box::new(handler), - })); - } + ("stdout", "on") if args.len() >= 2 => { + let mut iter = args.into_iter(); + let event = iter.next().unwrap(); + let handler = iter.next().unwrap(); + return Ok(Ok(Expr::ProcessStdoutOn { + event: Box::new(event), + handler: Box::new(handler), + })); } _ => {} } diff --git a/crates/perry-hir/src/lower/expr_call/module_static.rs b/crates/perry-hir/src/lower/expr_call/module_static.rs index b8a5631a3..a2e7732d6 100644 --- a/crates/perry-hir/src/lower/expr_call/module_static.rs +++ b/crates/perry-hir/src/lower/expr_call/module_static.rs @@ -3,19 +3,14 @@ //! Extracted from `expr_call/mod.rs` as a mechanical move. use anyhow::Result; -use perry_types::{LocalId, Type}; +use perry_types::Type; use swc_ecma_ast as ast; -use super::super::unimpl_hints; use super::static_receiver::static_receiver_class; -use super::url_search_params::build_url_search_params_method_call; use crate::ir::*; use crate::lower_types::extract_ts_type_with_ctx; -use super::super::{ - extract_typed_parse_source_order, is_generator_call_expr, is_widget_modifier_name, lower_expr, - resolve_typed_parse_ty, LoweringContext, -}; +use super::super::{extract_typed_parse_source_order, resolve_typed_parse_ty, LoweringContext}; use super::os::user_info_expr_for_call; fn peel_webassembly_receiver_expr(mut expr: &ast::Expr) -> &ast::Expr { @@ -74,33 +69,27 @@ pub(super) fn try_module_static_methods( && is_webassembly_namespace_receiver(ctx, class_member.obj.as_ref()) { match method_ident.sym.as_ref() { - "exports" => { - if !args.is_empty() { - ctx.uses_webassembly = true; - return Ok(Ok(Expr::WebAssemblyModuleExports(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "exports" if !args.is_empty() => { + ctx.uses_webassembly = true; + return Ok(Ok(Expr::WebAssemblyModuleExports(Box::new( + args.into_iter().next().unwrap(), + )))); } - "imports" => { - if !args.is_empty() { - ctx.uses_webassembly = true; - return Ok(Ok(Expr::WebAssemblyModuleImports(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "imports" if !args.is_empty() => { + ctx.uses_webassembly = true; + return Ok(Ok(Expr::WebAssemblyModuleImports(Box::new( + args.into_iter().next().unwrap(), + )))); } - "customSections" => { - if args.len() >= 2 { - ctx.uses_webassembly = true; - let mut it = args.into_iter(); - let module = it.next().unwrap(); - let name = it.next().unwrap(); - return Ok(Ok(Expr::WebAssemblyModuleCustomSections { - module: Box::new(module), - name: Box::new(name), - })); - } + "customSections" if args.len() >= 2 => { + ctx.uses_webassembly = true; + let mut it = args.into_iter(); + let module = it.next().unwrap(); + let name = it.next().unwrap(); + return Ok(Ok(Expr::WebAssemblyModuleCustomSections { + module: Box::new(module), + name: Box::new(name), + })); } _ => {} } @@ -112,35 +101,29 @@ pub(super) fn try_module_static_methods( if let ast::MemberProp::Ident(method_ident) = &member.prop { let method_name = method_ident.sym.as_ref(); match method_name { - "validate" => { - if !args.is_empty() { - ctx.uses_webassembly = true; - return Ok(Ok(Expr::WebAssemblyValidate(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "validate" if !args.is_empty() => { + ctx.uses_webassembly = true; + return Ok(Ok(Expr::WebAssemblyValidate(Box::new( + args.into_iter().next().unwrap(), + )))); } - "instantiate" => { - if !args.is_empty() { - ctx.uses_webassembly = true; - return Ok(Ok(Expr::WebAssemblyInstantiate(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "instantiate" if !args.is_empty() => { + ctx.uses_webassembly = true; + return Ok(Ok(Expr::WebAssemblyInstantiate(Box::new( + args.into_iter().next().unwrap(), + )))); } - "callExport" => { - if args.len() >= 2 { - ctx.uses_webassembly = true; - let mut it = args.into_iter(); - let instance = it.next().unwrap(); - let name = it.next().unwrap(); - let rest: Vec = it.collect(); - return Ok(Ok(Expr::WebAssemblyCallExport { - instance: Box::new(instance), - name: Box::new(name), - args: rest, - })); - } + "callExport" if args.len() >= 2 => { + ctx.uses_webassembly = true; + let mut it = args.into_iter(); + let instance = it.next().unwrap(); + let name = it.next().unwrap(); + let rest: Vec = it.collect(); + return Ok(Ok(Expr::WebAssemblyCallExport { + instance: Box::new(instance), + name: Box::new(name), + args: rest, + })); } _ => {} } @@ -155,70 +138,54 @@ pub(super) fn try_module_static_methods( if let ast::MemberProp::Ident(method_ident) = &member.prop { let method_name = method_ident.sym.as_ref(); match method_name { - "readFileSync" => { - if args.len() == 1 { - // readFileSync(path) without encoding — returns Buffer (Node parity) - return Ok(Ok(Expr::FsReadFileBinary(Box::new( - args.into_iter().next().unwrap(), - )))); - } - } - "writeFileSync" => { - if args.len() == 2 { - let mut iter = args.into_iter(); - let path = iter.next().unwrap(); - let content = iter.next().unwrap(); - return Ok(Ok(Expr::FsWriteFileSync( - Box::new(path), - Box::new(content), - ))); - } - } - "appendFileSync" => { - if args.len() == 2 { - let mut iter = args.into_iter(); - let path = iter.next().unwrap(); - let content = iter.next().unwrap(); - return Ok(Ok(Expr::FsAppendFileSync( - Box::new(path), - Box::new(content), - ))); - } + "readFileSync" if args.len() == 1 => { + // readFileSync(path) without encoding — returns Buffer (Node parity) + return Ok(Ok(Expr::FsReadFileBinary(Box::new( + args.into_iter().next().unwrap(), + )))); } - "existsSync" => { - if !args.is_empty() { - return Ok(Ok(Expr::FsExistsSync(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "writeFileSync" if args.len() == 2 => { + let mut iter = args.into_iter(); + let path = iter.next().unwrap(); + let content = iter.next().unwrap(); + return Ok(Ok(Expr::FsWriteFileSync( + Box::new(path), + Box::new(content), + ))); + } + "appendFileSync" if args.len() == 2 => { + let mut iter = args.into_iter(); + let path = iter.next().unwrap(); + let content = iter.next().unwrap(); + return Ok(Ok(Expr::FsAppendFileSync( + Box::new(path), + Box::new(content), + ))); + } + "existsSync" if !args.is_empty() => { + return Ok(Ok(Expr::FsExistsSync(Box::new( + args.into_iter().next().unwrap(), + )))); } - "mkdirSync" => { - if args.len() == 1 { - return Ok(Ok(Expr::FsMkdirSync(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "mkdirSync" if args.len() == 1 => { + return Ok(Ok(Expr::FsMkdirSync(Box::new( + args.into_iter().next().unwrap(), + )))); } - "unlinkSync" => { - if !args.is_empty() { - return Ok(Ok(Expr::FsUnlinkSync(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "unlinkSync" if !args.is_empty() => { + return Ok(Ok(Expr::FsUnlinkSync(Box::new( + args.into_iter().next().unwrap(), + )))); } - "readFileBuffer" => { - if !args.is_empty() { - return Ok(Ok(Expr::FsReadFileBinary(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "readFileBuffer" if !args.is_empty() => { + return Ok(Ok(Expr::FsReadFileBinary(Box::new( + args.into_iter().next().unwrap(), + )))); } - "rmRecursive" => { - if !args.is_empty() { - return Ok(Ok(Expr::FsRmRecursive(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "rmRecursive" if !args.is_empty() => { + return Ok(Ok(Expr::FsRmRecursive(Box::new( + args.into_iter().next().unwrap(), + )))); } // Issue #648 fallout: `fs.rmSync(path, opts?)` was // historically silently no-op'd by `js_native_call_method`'s @@ -257,12 +224,10 @@ pub(super) fn try_module_static_methods( } return Ok(Ok(result)); } - "dirname" => { - if !args.is_empty() { - return Ok(Ok(Expr::PathDirname(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "dirname" if !args.is_empty() => { + return Ok(Ok(Expr::PathDirname(Box::new( + args.into_iter().next().unwrap(), + )))); } "basename" => { if args.len() >= 2 { @@ -280,12 +245,10 @@ pub(super) fn try_module_static_methods( )))); } } - "extname" => { - if !args.is_empty() { - return Ok(Ok(Expr::PathExtname(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "extname" if !args.is_empty() => { + return Ok(Ok(Expr::PathExtname(Box::new( + args.into_iter().next().unwrap(), + )))); } "resolve" => { if args.is_empty() { @@ -308,59 +271,45 @@ pub(super) fn try_module_static_methods( return Ok(Ok(Expr::PathResolve(Box::new(joined)))); } } - "isAbsolute" => { - if !args.is_empty() { - return Ok(Ok(Expr::PathIsAbsolute(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "isAbsolute" if !args.is_empty() => { + return Ok(Ok(Expr::PathIsAbsolute(Box::new( + args.into_iter().next().unwrap(), + )))); } - "relative" => { - if args.len() >= 2 { - let mut iter = args.into_iter(); - let from = iter.next().unwrap(); - let to = iter.next().unwrap(); - return Ok(Ok(Expr::PathRelative(Box::new(from), Box::new(to)))); - } + "relative" if args.len() >= 2 => { + let mut iter = args.into_iter(); + let from = iter.next().unwrap(); + let to = iter.next().unwrap(); + return Ok(Ok(Expr::PathRelative(Box::new(from), Box::new(to)))); } - "normalize" => { - if !args.is_empty() { - return Ok(Ok(Expr::PathNormalize(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "normalize" if !args.is_empty() => { + return Ok(Ok(Expr::PathNormalize(Box::new( + args.into_iter().next().unwrap(), + )))); } - "parse" => { - if !args.is_empty() { - return Ok(Ok(Expr::PathParse(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "parse" if !args.is_empty() => { + return Ok(Ok(Expr::PathParse(Box::new( + args.into_iter().next().unwrap(), + )))); } - "format" => { - if !args.is_empty() { - return Ok(Ok(Expr::PathFormat(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "format" if !args.is_empty() => { + return Ok(Ok(Expr::PathFormat(Box::new( + args.into_iter().next().unwrap(), + )))); } - "toNamespacedPath" | "_makeLong" => { - if !args.is_empty() { - return Ok(Ok(Expr::PathToNamespacedPath(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "toNamespacedPath" | "_makeLong" if !args.is_empty() => { + return Ok(Ok(Expr::PathToNamespacedPath(Box::new( + args.into_iter().next().unwrap(), + )))); } - "matchesGlob" => { - if args.len() >= 2 { - let mut iter = args.into_iter(); - let path_arg = iter.next().unwrap(); - let pattern = iter.next().unwrap(); - return Ok(Ok(Expr::PathMatchesGlob( - Box::new(path_arg), - Box::new(pattern), - ))); - } + "matchesGlob" if args.len() >= 2 => { + let mut iter = args.into_iter(); + let path_arg = iter.next().unwrap(); + let pattern = iter.next().unwrap(); + return Ok(Ok(Expr::PathMatchesGlob( + Box::new(path_arg), + Box::new(pattern), + ))); } _ => {} // Fall through to generic handling } @@ -470,20 +419,18 @@ pub(super) fn try_module_static_methods( ))); } } - "rawJSON" => { + "rawJSON" // #2900: `JSON.rawJSON(text)` -> raw-JSON wrapper. - if !args.is_empty() { + if !args.is_empty() => { let text = args.into_iter().next().unwrap(); return Ok(Ok(Expr::JsonRawJson(Box::new(text)))); } - } - "isRawJSON" => { + "isRawJSON" // #2900: `JSON.isRawJSON(value)` -> boolean. - if !args.is_empty() { + if !args.is_empty() => { let value = args.into_iter().next().unwrap(); return Ok(Ok(Expr::JsonIsRawJson(Box::new(value)))); } - } _ => {} // Fall through to generic handling } } @@ -600,43 +547,35 @@ pub(super) fn try_module_static_methods( if let ast::MemberProp::Ident(method_ident) = &member.prop { let method_name = method_ident.sym.as_ref(); match method_name { - "validate" => { - if !args.is_empty() { - ctx.uses_webassembly = true; - return Ok(Ok(Expr::WebAssemblyValidate(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "validate" if !args.is_empty() => { + ctx.uses_webassembly = true; + return Ok(Ok(Expr::WebAssemblyValidate(Box::new( + args.into_iter().next().unwrap(), + )))); } - "compile" => { - if !args.is_empty() { - ctx.uses_webassembly = true; - return Ok(Ok(Expr::WebAssemblyCompile(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "compile" if !args.is_empty() => { + ctx.uses_webassembly = true; + return Ok(Ok(Expr::WebAssemblyCompile(Box::new( + args.into_iter().next().unwrap(), + )))); } - "instantiate" => { - if !args.is_empty() { - ctx.uses_webassembly = true; - return Ok(Ok(Expr::WebAssemblyInstantiate(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "instantiate" if !args.is_empty() => { + ctx.uses_webassembly = true; + return Ok(Ok(Expr::WebAssemblyInstantiate(Box::new( + args.into_iter().next().unwrap(), + )))); } - "callExport" => { - if args.len() >= 2 { - ctx.uses_webassembly = true; - let mut it = args.into_iter(); - let instance = it.next().unwrap(); - let name = it.next().unwrap(); - let rest: Vec = it.collect(); - return Ok(Ok(Expr::WebAssemblyCallExport { - instance: Box::new(instance), - name: Box::new(name), - args: rest, - })); - } + "callExport" if args.len() >= 2 => { + ctx.uses_webassembly = true; + let mut it = args.into_iter(); + let instance = it.next().unwrap(); + let name = it.next().unwrap(); + let rest: Vec = it.collect(); + return Ok(Ok(Expr::WebAssemblyCallExport { + instance: Box::new(instance), + name: Box::new(name), + args: rest, + })); } _ => {} } @@ -653,83 +592,61 @@ pub(super) fn try_module_static_methods( if let ast::MemberProp::Ident(method_ident) = &member.prop { let method_name = method_ident.sym.as_ref(); match method_name { - "floor" => { - if !args.is_empty() { - return Ok(Ok(Expr::MathFloor(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "floor" if !args.is_empty() => { + return Ok(Ok(Expr::MathFloor(Box::new( + args.into_iter().next().unwrap(), + )))); } - "ceil" => { - if !args.is_empty() { - return Ok(Ok(Expr::MathCeil(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "ceil" if !args.is_empty() => { + return Ok(Ok(Expr::MathCeil(Box::new( + args.into_iter().next().unwrap(), + )))); } - "round" => { - if !args.is_empty() { - return Ok(Ok(Expr::MathRound(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "round" if !args.is_empty() => { + return Ok(Ok(Expr::MathRound(Box::new( + args.into_iter().next().unwrap(), + )))); } - "trunc" => { - if !args.is_empty() { - return Ok(Ok(Expr::MathTrunc(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "trunc" if !args.is_empty() => { + return Ok(Ok(Expr::MathTrunc(Box::new( + args.into_iter().next().unwrap(), + )))); } - "sign" => { - if !args.is_empty() { - return Ok(Ok(Expr::MathSign(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "sign" if !args.is_empty() => { + return Ok(Ok(Expr::MathSign(Box::new( + args.into_iter().next().unwrap(), + )))); } - "abs" => { - if !args.is_empty() { - return Ok(Ok(Expr::MathAbs(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "abs" if !args.is_empty() => { + return Ok(Ok(Expr::MathAbs(Box::new( + args.into_iter().next().unwrap(), + )))); } - "sqrt" => { - if !args.is_empty() { - return Ok(Ok(Expr::MathSqrt(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "sqrt" if !args.is_empty() => { + return Ok(Ok(Expr::MathSqrt(Box::new( + args.into_iter().next().unwrap(), + )))); } - "log" => { - if !args.is_empty() { - return Ok(Ok(Expr::MathLog(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "log" if !args.is_empty() => { + return Ok(Ok(Expr::MathLog(Box::new( + args.into_iter().next().unwrap(), + )))); } - "log2" => { - if !args.is_empty() { - return Ok(Ok(Expr::MathLog2(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "log2" if !args.is_empty() => { + return Ok(Ok(Expr::MathLog2(Box::new( + args.into_iter().next().unwrap(), + )))); } - "log10" => { - if !args.is_empty() { - return Ok(Ok(Expr::MathLog10(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "log10" if !args.is_empty() => { + return Ok(Ok(Expr::MathLog10(Box::new( + args.into_iter().next().unwrap(), + )))); } - "pow" => { - if args.len() >= 2 { - let mut args_iter = args.into_iter(); - let base = args_iter.next().unwrap(); - let exp = args_iter.next().unwrap(); - return Ok(Ok(Expr::MathPow(Box::new(base), Box::new(exp)))); - } + "pow" if args.len() >= 2 => { + let mut args_iter = args.into_iter(); + let base = args_iter.next().unwrap(); + let exp = args_iter.next().unwrap(); + return Ok(Ok(Expr::MathPow(Box::new(base), Box::new(exp)))); } "min" => { if has_spread && args.len() == 1 { @@ -750,157 +667,115 @@ pub(super) fn try_module_static_methods( "random" => { return Ok(Ok(Expr::MathRandom)); } - "imul" => { - if args.len() >= 2 { - let mut args_iter = args.into_iter(); - let a = args_iter.next().unwrap(); - let b = args_iter.next().unwrap(); - return Ok(Ok(Expr::MathImul(Box::new(a), Box::new(b)))); - } + "imul" if args.len() >= 2 => { + let mut args_iter = args.into_iter(); + let a = args_iter.next().unwrap(); + let b = args_iter.next().unwrap(); + return Ok(Ok(Expr::MathImul(Box::new(a), Box::new(b)))); } - "sin" => { - if !args.is_empty() { - return Ok(Ok(Expr::MathSin(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "sin" if !args.is_empty() => { + return Ok(Ok(Expr::MathSin(Box::new( + args.into_iter().next().unwrap(), + )))); } - "cos" => { - if !args.is_empty() { - return Ok(Ok(Expr::MathCos(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "cos" if !args.is_empty() => { + return Ok(Ok(Expr::MathCos(Box::new( + args.into_iter().next().unwrap(), + )))); } - "tan" => { - if !args.is_empty() { - return Ok(Ok(Expr::MathTan(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "tan" if !args.is_empty() => { + return Ok(Ok(Expr::MathTan(Box::new( + args.into_iter().next().unwrap(), + )))); } - "asin" => { - if !args.is_empty() { - return Ok(Ok(Expr::MathAsin(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "asin" if !args.is_empty() => { + return Ok(Ok(Expr::MathAsin(Box::new( + args.into_iter().next().unwrap(), + )))); } - "acos" => { - if !args.is_empty() { - return Ok(Ok(Expr::MathAcos(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "acos" if !args.is_empty() => { + return Ok(Ok(Expr::MathAcos(Box::new( + args.into_iter().next().unwrap(), + )))); } - "atan" => { - if !args.is_empty() { - return Ok(Ok(Expr::MathAtan(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "atan" if !args.is_empty() => { + return Ok(Ok(Expr::MathAtan(Box::new( + args.into_iter().next().unwrap(), + )))); } - "atan2" => { - if args.len() >= 2 { - let mut args_iter = args.into_iter(); - let y = args_iter.next().unwrap(); - let x = args_iter.next().unwrap(); - return Ok(Ok(Expr::MathAtan2(Box::new(y), Box::new(x)))); - } + "atan2" if args.len() >= 2 => { + let mut args_iter = args.into_iter(); + let y = args_iter.next().unwrap(); + let x = args_iter.next().unwrap(); + return Ok(Ok(Expr::MathAtan2(Box::new(y), Box::new(x)))); } - "cbrt" => { - if !args.is_empty() { - return Ok(Ok(Expr::MathCbrt(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "cbrt" if !args.is_empty() => { + return Ok(Ok(Expr::MathCbrt(Box::new( + args.into_iter().next().unwrap(), + )))); } "hypot" => { return Ok(Ok(Expr::MathHypot(args))); } - "fround" => { - if !args.is_empty() { - return Ok(Ok(Expr::MathFround(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "fround" if !args.is_empty() => { + return Ok(Ok(Expr::MathFround(Box::new( + args.into_iter().next().unwrap(), + )))); } - "f16round" => { - if !args.is_empty() { - return Ok(Ok(Expr::MathF16round(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "f16round" if !args.is_empty() => { + return Ok(Ok(Expr::MathF16round(Box::new( + args.into_iter().next().unwrap(), + )))); } - "clz32" => { - if !args.is_empty() { - return Ok(Ok(Expr::MathClz32(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "clz32" if !args.is_empty() => { + return Ok(Ok(Expr::MathClz32(Box::new( + args.into_iter().next().unwrap(), + )))); } - "expm1" => { - if !args.is_empty() { - return Ok(Ok(Expr::MathExpm1(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "expm1" if !args.is_empty() => { + return Ok(Ok(Expr::MathExpm1(Box::new( + args.into_iter().next().unwrap(), + )))); } - "log1p" => { - if !args.is_empty() { - return Ok(Ok(Expr::MathLog1p(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "log1p" if !args.is_empty() => { + return Ok(Ok(Expr::MathLog1p(Box::new( + args.into_iter().next().unwrap(), + )))); } - "sinh" => { - if !args.is_empty() { - return Ok(Ok(Expr::MathSinh(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "sinh" if !args.is_empty() => { + return Ok(Ok(Expr::MathSinh(Box::new( + args.into_iter().next().unwrap(), + )))); } - "cosh" => { - if !args.is_empty() { - return Ok(Ok(Expr::MathCosh(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "cosh" if !args.is_empty() => { + return Ok(Ok(Expr::MathCosh(Box::new( + args.into_iter().next().unwrap(), + )))); } - "tanh" => { - if !args.is_empty() { - return Ok(Ok(Expr::MathTanh(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "tanh" if !args.is_empty() => { + return Ok(Ok(Expr::MathTanh(Box::new( + args.into_iter().next().unwrap(), + )))); } - "asinh" => { - if !args.is_empty() { - return Ok(Ok(Expr::MathAsinh(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "asinh" if !args.is_empty() => { + return Ok(Ok(Expr::MathAsinh(Box::new( + args.into_iter().next().unwrap(), + )))); } - "acosh" => { - if !args.is_empty() { - return Ok(Ok(Expr::MathAcosh(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "acosh" if !args.is_empty() => { + return Ok(Ok(Expr::MathAcosh(Box::new( + args.into_iter().next().unwrap(), + )))); } - "atanh" => { - if !args.is_empty() { - return Ok(Ok(Expr::MathAtanh(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "atanh" if !args.is_empty() => { + return Ok(Ok(Expr::MathAtanh(Box::new( + args.into_iter().next().unwrap(), + )))); } - "exp" => { - if !args.is_empty() { - return Ok(Ok(Expr::MathExp(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "exp" if !args.is_empty() => { + return Ok(Ok(Expr::MathExp(Box::new( + args.into_iter().next().unwrap(), + )))); } _ => {} // Fall through to generic handling } @@ -1103,19 +978,15 @@ pub(super) fn try_module_static_methods( } } match method_name { - "sha256" => { - if !args.is_empty() { - return Ok(Ok(Expr::CryptoSha256(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "sha256" if !args.is_empty() => { + return Ok(Ok(Expr::CryptoSha256(Box::new( + args.into_iter().next().unwrap(), + )))); } - "md5" => { - if !args.is_empty() { - return Ok(Ok(Expr::CryptoMd5(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "md5" if !args.is_empty() => { + return Ok(Ok(Expr::CryptoMd5(Box::new( + args.into_iter().next().unwrap(), + )))); } // `crypto.getRandomValues(buf)` fills the buffer // in-place with random bytes and returns it. @@ -1123,19 +994,17 @@ pub(super) fn try_module_static_methods( // the runtime buffer dispatcher (added in // perry-runtime/src/object.rs) handles it via // `js_buffer_fill_random`. - "getRandomValues" => { - if !args.is_empty() { - let buf_arg = args.into_iter().next().unwrap(); - return Ok(Ok(Expr::Call { - callee: Box::new(Expr::PropertyGet { - object: Box::new(buf_arg), - property: "$$cryptoFillRandom".to_string(), - }), - args: vec![], - type_args: vec![], - byte_offset: 0, - })); - } + "getRandomValues" if !args.is_empty() => { + let buf_arg = args.into_iter().next().unwrap(); + return Ok(Ok(Expr::Call { + callee: Box::new(Expr::PropertyGet { + object: Box::new(buf_arg), + property: "$$cryptoFillRandom".to_string(), + }), + args: vec![], + type_args: vec![], + byte_offset: 0, + })); } // `crypto.randomBytes` / `randomUUID` / // `randomFillSync` are handled by the shared @@ -1226,7 +1095,7 @@ pub(super) fn try_module_static_methods( // first Buffer site above). let is_buffer_ref = obj_name == "Buffer" || matches!( - ctx.lookup_native_module(&obj_name), + ctx.lookup_native_module(obj_name), Some(("buffer", Some("Buffer"))) ); if is_buffer_ref { @@ -1254,38 +1123,32 @@ pub(super) fn try_module_static_methods( encoding, })); } - "alloc" => { - if !args.is_empty() { - let mut args_iter = args.into_iter(); - let size = args_iter.next().unwrap(); - let fill = args_iter.next().map(Box::new); - let encoding = args_iter.next().map(Box::new); - return Ok(Ok(Expr::BufferAlloc { - size: Box::new(size), - fill, - encoding, - })); - } + "alloc" if !args.is_empty() => { + let mut args_iter = args.into_iter(); + let size = args_iter.next().unwrap(); + let fill = args_iter.next().map(Box::new); + let encoding = args_iter.next().map(Box::new); + return Ok(Ok(Expr::BufferAlloc { + size: Box::new(size), + fill, + encoding, + })); } - "allocUnsafe" | "allocUnsafeSlow" => { - if !args.is_empty() { - return Ok(Ok(Expr::BufferAllocUnsafe(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "allocUnsafe" | "allocUnsafeSlow" if !args.is_empty() => { + return Ok(Ok(Expr::BufferAllocUnsafe(Box::new( + args.into_iter().next().unwrap(), + )))); } - "concat" => { - if !args.is_empty() { - let mut args_iter = args.into_iter(); - let list = args_iter.next().unwrap(); - if let Some(total_length) = args_iter.next() { - return Ok(Ok(Expr::BufferConcatWithLength { - list: Box::new(list), - total_length: Box::new(total_length), - })); - } - return Ok(Ok(Expr::BufferConcat(Box::new(list)))); + "concat" if !args.is_empty() => { + let mut args_iter = args.into_iter(); + let list = args_iter.next().unwrap(); + if let Some(total_length) = args_iter.next() { + return Ok(Ok(Expr::BufferConcatWithLength { + list: Box::new(list), + total_length: Box::new(total_length), + })); } + return Ok(Ok(Expr::BufferConcat(Box::new(list)))); } "copyBytesFrom" => { return Ok(Ok(Expr::NativeMethodCall { @@ -1302,51 +1165,43 @@ pub(super) fn try_module_static_methods( encoding: None, })); } - "isBuffer" => { - if !args.is_empty() { - return Ok(Ok(Expr::BufferIsBuffer(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "isBuffer" if !args.is_empty() => { + return Ok(Ok(Expr::BufferIsBuffer(Box::new( + args.into_iter().next().unwrap(), + )))); } - "isEncoding" => { - if !args.is_empty() { - return Ok(Ok(Expr::BufferIsEncoding(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "isEncoding" if !args.is_empty() => { + return Ok(Ok(Expr::BufferIsEncoding(Box::new( + args.into_iter().next().unwrap(), + )))); } - "byteLength" => { - if !args.is_empty() { - let mut it = args.into_iter(); - let data = it.next().unwrap(); - let encoding = it.next().map(Box::new); - return Ok(Ok(Expr::BufferByteLength { - data: Box::new(data), - encoding, - })); - } + "byteLength" if !args.is_empty() => { + let mut it = args.into_iter(); + let data = it.next().unwrap(); + let encoding = it.next().map(Box::new); + return Ok(Ok(Expr::BufferByteLength { + data: Box::new(data), + encoding, + })); } // `Buffer.compare(a, b)` returns -1/0/1. The runtime // dispatch already handles `a.compare(b)` as an // instance method routing through `js_buffer_compare`. // Synthesize that form so we don't need a dedicated // HIR variant or runtime entry point. - "compare" => { - if args.len() >= 2 { - let mut iter = args.into_iter(); - let a = iter.next().unwrap(); - let b = iter.next().unwrap(); - return Ok(Ok(Expr::Call { - callee: Box::new(Expr::PropertyGet { - object: Box::new(a), - property: "compare".to_string(), - }), - args: vec![b], - type_args: vec![], - byte_offset: 0, - })); - } + "compare" if args.len() >= 2 => { + let mut iter = args.into_iter(); + let a = iter.next().unwrap(); + let b = iter.next().unwrap(); + return Ok(Ok(Expr::Call { + callee: Box::new(Expr::PropertyGet { + object: Box::new(a), + property: "compare".to_string(), + }), + args: vec![b], + type_args: vec![], + byte_offset: 0, + })); } _ => {} // Fall through to generic handling } @@ -1381,11 +1236,11 @@ pub(super) fn try_module_static_methods( // (no mapFn). This intentionally only fires when the receiver name // is a real global typed-array constructor (not shadowed by a // local/import/class binding). - if let Some(kind) = crate::ir::typed_array_kind_for_name(&obj_name) { - let shadowed = ctx.lookup_local(&obj_name).is_some() - || ctx.lookup_func(&obj_name).is_some() - || ctx.lookup_imported_func(&obj_name).is_some() - || ctx.lookup_class(&obj_name).is_some(); + if let Some(kind) = crate::ir::typed_array_kind_for_name(obj_name) { + let shadowed = ctx.lookup_local(obj_name).is_some() + || ctx.lookup_func(obj_name).is_some() + || ctx.lookup_imported_func(obj_name).is_some() + || ctx.lookup_class(obj_name).is_some(); if !shadowed && obj_name != "Uint8Array" { if let ast::MemberProp::Ident(method_ident) = &member.prop { let method_name = method_ident.sym.as_ref(); @@ -1417,125 +1272,105 @@ pub(super) fn try_module_static_methods( if let ast::MemberProp::Ident(method_ident) = &member.prop { let method_name = method_ident.sym.as_ref(); match method_name { - "execSync" => { - if !args.is_empty() { - let mut args_iter = args.into_iter(); - let command = args_iter.next().unwrap(); - let options = args_iter.next().map(Box::new); - return Ok(Ok(Expr::ChildProcessExecSync { - command: Box::new(command), - options, - })); - } + "execSync" if !args.is_empty() => { + let mut args_iter = args.into_iter(); + let command = args_iter.next().unwrap(); + let options = args_iter.next().map(Box::new); + return Ok(Ok(Expr::ChildProcessExecSync { + command: Box::new(command), + options, + })); } - "spawnSync" => { - if !args.is_empty() { - let mut args_iter = args.into_iter(); - let command = args_iter.next().unwrap(); - let spawn_args = args_iter.next().map(Box::new); - let options = args_iter.next().map(Box::new); - return Ok(Ok(Expr::ChildProcessSpawnSync { - command: Box::new(command), - args: spawn_args, - options, - })); - } + "spawnSync" if !args.is_empty() => { + let mut args_iter = args.into_iter(); + let command = args_iter.next().unwrap(); + let spawn_args = args_iter.next().map(Box::new); + let options = args_iter.next().map(Box::new); + return Ok(Ok(Expr::ChildProcessSpawnSync { + command: Box::new(command), + args: spawn_args, + options, + })); } - "spawn" => { - if !args.is_empty() { - let mut args_iter = args.into_iter(); - let command = args_iter.next().unwrap(); - let spawn_args = args_iter.next().map(Box::new); - let options = args_iter.next().map(Box::new); - return Ok(Ok(Expr::ChildProcessSpawn { - command: Box::new(command), - args: spawn_args, - options, - })); - } + "spawn" if !args.is_empty() => { + let mut args_iter = args.into_iter(); + let command = args_iter.next().unwrap(); + let spawn_args = args_iter.next().map(Box::new); + let options = args_iter.next().map(Box::new); + return Ok(Ok(Expr::ChildProcessSpawn { + command: Box::new(command), + args: spawn_args, + options, + })); } - "fork" => { - if !args.is_empty() { - let mut args_iter = args.into_iter(); - let module = args_iter.next().unwrap(); - let fork_args = args_iter.next().map(Box::new); - let options = args_iter.next().map(Box::new); - return Ok(Ok(Expr::ChildProcessFork { - module: Box::new(module), - args: fork_args, - options, - })); - } + "fork" if !args.is_empty() => { + let mut args_iter = args.into_iter(); + let module = args_iter.next().unwrap(); + let fork_args = args_iter.next().map(Box::new); + let options = args_iter.next().map(Box::new); + return Ok(Ok(Expr::ChildProcessFork { + module: Box::new(module), + args: fork_args, + options, + })); } - "exec" => { - if !args.is_empty() { - let mut args_iter = args.into_iter(); - let command = args_iter.next().unwrap(); - let options = args_iter.next().map(Box::new); - let callback = args_iter.next().map(Box::new); - return Ok(Ok(Expr::ChildProcessExec { - command: Box::new(command), - options, - callback, - })); - } + "exec" if !args.is_empty() => { + let mut args_iter = args.into_iter(); + let command = args_iter.next().unwrap(); + let options = args_iter.next().map(Box::new); + let callback = args_iter.next().map(Box::new); + return Ok(Ok(Expr::ChildProcessExec { + command: Box::new(command), + options, + callback, + })); } - "execFile" => { - if !args.is_empty() { - let mut args_iter = args.into_iter(); - let file = args_iter.next().unwrap(); - let file_args = args_iter.next().map(Box::new); - let options = args_iter.next().map(Box::new); - let callback = args_iter.next().map(Box::new); - return Ok(Ok(Expr::ChildProcessExecFile { - file: Box::new(file), - args: file_args, - options, - callback, - })); - } + "execFile" if !args.is_empty() => { + let mut args_iter = args.into_iter(); + let file = args_iter.next().unwrap(); + let file_args = args_iter.next().map(Box::new); + let options = args_iter.next().map(Box::new); + let callback = args_iter.next().map(Box::new); + return Ok(Ok(Expr::ChildProcessExecFile { + file: Box::new(file), + args: file_args, + options, + callback, + })); } - "execFileSync" => { - if !args.is_empty() { - let mut args_iter = args.into_iter(); - let file = args_iter.next().unwrap(); - let file_args = args_iter.next().map(Box::new); - let options = args_iter.next().map(Box::new); - return Ok(Ok(Expr::ChildProcessExecFileSync { - file: Box::new(file), - args: file_args, - options, - })); - } + "execFileSync" if !args.is_empty() => { + let mut args_iter = args.into_iter(); + let file = args_iter.next().unwrap(); + let file_args = args_iter.next().map(Box::new); + let options = args_iter.next().map(Box::new); + return Ok(Ok(Expr::ChildProcessExecFileSync { + file: Box::new(file), + args: file_args, + options, + })); } - "spawnBackground" => { - if args.len() >= 3 { - let mut args_iter = args.into_iter(); - let command = args_iter.next().unwrap(); - let spawn_args = args_iter.next().map(Box::new); - let log_file = args_iter.next().unwrap(); - let env_json = args_iter.next().map(Box::new); - return Ok(Ok(Expr::ChildProcessSpawnBackground { - command: Box::new(command), - args: spawn_args, - log_file: Box::new(log_file), - env_json, - })); - } + "spawnBackground" if args.len() >= 3 => { + let mut args_iter = args.into_iter(); + let command = args_iter.next().unwrap(); + let spawn_args = args_iter.next().map(Box::new); + let log_file = args_iter.next().unwrap(); + let env_json = args_iter.next().map(Box::new); + return Ok(Ok(Expr::ChildProcessSpawnBackground { + command: Box::new(command), + args: spawn_args, + log_file: Box::new(log_file), + env_json, + })); } - "getProcessStatus" => { - if !args.is_empty() { - return Ok(Ok(Expr::ChildProcessGetProcessStatus(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "getProcessStatus" if !args.is_empty() => { + return Ok(Ok(Expr::ChildProcessGetProcessStatus(Box::new( + args.into_iter().next().unwrap(), + )))); } - "killProcess" => { - if !args.is_empty() { - return Ok(Ok(Expr::ChildProcessKillProcess(Box::new( - args.into_iter().next().unwrap(), - )))); - } + "killProcess" if !args.is_empty() => { + return Ok(Ok(Expr::ChildProcessKillProcess(Box::new( + args.into_iter().next().unwrap(), + )))); } _ => {} // Fall through to generic handling } diff --git a/crates/perry-hir/src/lower/expr_call/native_module.rs b/crates/perry-hir/src/lower/expr_call/native_module.rs index b8abb210e..0ee005160 100644 --- a/crates/perry-hir/src/lower/expr_call/native_module.rs +++ b/crates/perry-hir/src/lower/expr_call/native_module.rs @@ -2,20 +2,15 @@ //! //! Extracted from `expr_call/mod.rs` as a mechanical move. -use anyhow::{anyhow, Result}; -use perry_types::{LocalId, Type}; +use anyhow::Result; +use perry_types::Type; use swc_ecma_ast as ast; use super::super::unimpl_hints; -use super::object_static::build_object_static_method_call; use super::reflect_args::{take_reflect_ktp_args, take_reflect_kvtp_args, take_reflect_tp_args}; use crate::ir::*; -use crate::lower_types::extract_ts_type_with_ctx; -use super::super::{ - extract_typed_parse_source_order, is_generator_call_expr, is_widget_modifier_name, lower_expr, - resolve_typed_parse_ty, LoweringContext, -}; +use super::super::{is_generator_call_expr, lower_expr, LoweringContext}; use super::os::user_info_expr_for_call; fn path_submodule_name(module_name: &str) -> Option<&'static str> { @@ -747,21 +742,19 @@ pub(super) fn try_native_module_methods( } // `Buffer.compare(a, b)` → `a.compare(b)` instance call // (handled by runtime buffer dispatch). - "compare" => { - if args.len() >= 2 { - let mut iter = args.into_iter(); - let a = iter.next().unwrap(); - let b = iter.next().unwrap(); - return Ok(Ok(Expr::Call { - callee: Box::new(Expr::PropertyGet { - object: Box::new(a), - property: "compare".to_string(), - }), - args: vec![b], - type_args: vec![], - byte_offset: 0, - })); - } + "compare" if args.len() >= 2 => { + let mut iter = args.into_iter(); + let a = iter.next().unwrap(); + let b = iter.next().unwrap(); + return Ok(Ok(Expr::Call { + callee: Box::new(Expr::PropertyGet { + object: Box::new(a), + property: "compare".to_string(), + }), + args: vec![b], + type_args: vec![], + byte_offset: 0, + })); } _ => {} // Fall through to generic handling } @@ -854,9 +847,9 @@ pub(super) fn try_native_module_methods( let entries = args.into_iter().next().unwrap_or(Expr::Undefined); return Ok(Ok(Expr::ObjectFromEntries(Box::new(entries)))); } - "groupBy" => { + "groupBy" // Object.groupBy(items, keyFn) — Node 22+ static method - if args.len() >= 2 { + if args.len() >= 2 => { let mut iter = args.into_iter(); let items = iter.next().unwrap(); let key_fn = iter.next().unwrap(); @@ -866,7 +859,6 @@ pub(super) fn try_native_module_methods( key_fn: Box::new(key_fn), })); } - } "is" => { let mut iter = args.into_iter(); let a = iter.next().unwrap_or(Expr::Undefined); diff --git a/crates/perry-hir/src/lower/expr_call/nested_namespace.rs b/crates/perry-hir/src/lower/expr_call/nested_namespace.rs index 626f47a5b..c77733cd0 100644 --- a/crates/perry-hir/src/lower/expr_call/nested_namespace.rs +++ b/crates/perry-hir/src/lower/expr_call/nested_namespace.rs @@ -689,10 +689,8 @@ pub(super) fn try_path_subnamespace( if let ast::MemberProp::Ident(sub_prop) = &inner_member.prop { let sub = sub_prop.sym.as_ref(); let root_name = root_ident.sym.as_ref(); - if is_path_root(ctx, root_name) { - if sub == "posix" || sub == "win32" { - return dispatch_path_subnamespace(sub, method, args); - } + if is_path_root(ctx, root_name) && (sub == "posix" || sub == "win32") { + return dispatch_path_subnamespace(sub, method, args); } if let Some((module_name, _)) = ctx.lookup_native_module(root_name) { if let Some(root_sub) = path_submodule_name( diff --git a/crates/perry-hir/src/lower/expr_call/regex_string.rs b/crates/perry-hir/src/lower/expr_call/regex_string.rs index 6058a02af..85bb1e356 100644 --- a/crates/perry-hir/src/lower/expr_call/regex_string.rs +++ b/crates/perry-hir/src/lower/expr_call/regex_string.rs @@ -2,17 +2,13 @@ //! //! Extracted from `expr_call/mod.rs` as a mechanical move. -use anyhow::{anyhow, Result}; -use perry_types::{LocalId, Type}; +use anyhow::Result; +use perry_types::Type; use swc_ecma_ast as ast; use crate::ir::*; -use crate::lower_types::extract_ts_type_with_ctx; -use super::super::{ - extract_typed_parse_source_order, is_generator_call_expr, is_widget_modifier_name, lower_expr, - resolve_typed_parse_ty, LoweringContext, -}; +use super::super::{lower_expr, LoweringContext}; pub(super) fn try_regex_string_methods( ctx: &mut LoweringContext, diff --git a/crates/perry-hir/src/lower/expr_call/static_and_instance.rs b/crates/perry-hir/src/lower/expr_call/static_and_instance.rs index 62e983880..5581f939f 100644 --- a/crates/perry-hir/src/lower/expr_call/static_and_instance.rs +++ b/crates/perry-hir/src/lower/expr_call/static_and_instance.rs @@ -3,19 +3,14 @@ //! Extracted from `expr_call/mod.rs` as a mechanical move. use anyhow::{anyhow, Result}; -use perry_types::{LocalId, Type}; use swc_common::Spanned; use swc_ecma_ast as ast; use super::stream::is_stream_api_method; use crate::ir::*; use crate::lower_patterns::detect_native_instance_expr; -use crate::lower_types::extract_ts_type_with_ctx; -use super::super::{ - extract_typed_parse_source_order, is_generator_call_expr, is_widget_modifier_name, lower_expr, - resolve_typed_parse_ty, LoweringContext, -}; +use super::super::{is_widget_modifier_name, lower_expr, LoweringContext}; fn unwrap_ts_wrappers(e: &ast::Expr) -> &ast::Expr { let mut cur = e; diff --git a/crates/perry-hir/src/lower/expr_call/textencoder.rs b/crates/perry-hir/src/lower/expr_call/textencoder.rs index b25e60a08..c5a0f19ed 100644 --- a/crates/perry-hir/src/lower/expr_call/textencoder.rs +++ b/crates/perry-hir/src/lower/expr_call/textencoder.rs @@ -2,17 +2,13 @@ //! //! Extracted from `expr_call/mod.rs` as a mechanical move. -use anyhow::{anyhow, Result}; -use perry_types::{LocalId, Type}; +use anyhow::Result; +use perry_types::Type; use swc_ecma_ast as ast; use crate::ir::*; -use crate::lower_types::extract_ts_type_with_ctx; -use super::super::{ - extract_typed_parse_source_order, is_generator_call_expr, is_widget_modifier_name, lower_expr, - resolve_typed_parse_ty, LoweringContext, -}; +use super::super::{lower_expr, LoweringContext}; fn text_encoder_encode_into(args: Vec) -> Expr { let mut args = args.into_iter(); diff --git a/crates/perry-hir/src/lower/expr_call/url_date_instance.rs b/crates/perry-hir/src/lower/expr_call/url_date_instance.rs index 6755a3fbf..d73336fd1 100644 --- a/crates/perry-hir/src/lower/expr_call/url_date_instance.rs +++ b/crates/perry-hir/src/lower/expr_call/url_date_instance.rs @@ -2,19 +2,15 @@ //! //! Extracted from `expr_call/mod.rs` as a mechanical move. -use anyhow::{anyhow, Result}; -use perry_types::{LocalId, Type}; +use anyhow::Result; +use perry_types::Type; use swc_ecma_ast as ast; use super::static_receiver::static_receiver_class; use super::url_search_params::build_url_search_params_method_call; use crate::ir::*; -use crate::lower_types::extract_ts_type_with_ctx; -use super::super::{ - extract_typed_parse_source_order, is_generator_call_expr, is_widget_modifier_name, lower_expr, - resolve_typed_parse_ty, LoweringContext, -}; +use super::super::{lower_expr, LoweringContext}; fn new_callee_name(ctx: &LoweringContext, new_expr: &ast::NewExpr) -> Option { match new_expr.callee.as_ref() { diff --git a/crates/perry-hir/src/lower/expr_call/wasm_exports.rs b/crates/perry-hir/src/lower/expr_call/wasm_exports.rs index 15bf88991..1677ff51a 100644 --- a/crates/perry-hir/src/lower/expr_call/wasm_exports.rs +++ b/crates/perry-hir/src/lower/expr_call/wasm_exports.rs @@ -2,17 +2,12 @@ //! //! Extracted from `expr_call/mod.rs` as a mechanical move. -use anyhow::{anyhow, Result}; -use perry_types::{LocalId, Type}; +use anyhow::Result; use swc_ecma_ast as ast; use crate::ir::*; -use crate::lower_types::extract_ts_type_with_ctx; -use super::super::{ - extract_typed_parse_source_order, is_generator_call_expr, is_widget_modifier_name, lower_expr, - resolve_typed_parse_ty, LoweringContext, -}; +use super::super::{lower_expr, LoweringContext}; pub(super) fn try_wasm_instance_exports( ctx: &mut LoweringContext, diff --git a/crates/perry-hir/src/lower/expr_member.rs b/crates/perry-hir/src/lower/expr_member.rs index e6b417f3b..0786acd21 100644 --- a/crates/perry-hir/src/lower/expr_member.rs +++ b/crates/perry-hir/src/lower/expr_member.rs @@ -1090,10 +1090,8 @@ fn lower_member_inner(ctx: &mut LoweringContext, member: &ast::MemberExpr) -> Re } else { None } - } else if let Some(func_id) = ctx.lookup_func(&fn_name) { - Some(Expr::FuncRef(func_id)) } else { - None + ctx.lookup_func(&fn_name).map(Expr::FuncRef) }; if let Some(func_expr) = func_expr { return Ok(Expr::GetFunctionPrototypeMethod { diff --git a/crates/perry-hir/src/lower/expr_new.rs b/crates/perry-hir/src/lower/expr_new.rs index 5b8b26d10..34a0d43f1 100644 --- a/crates/perry-hir/src/lower/expr_new.rs +++ b/crates/perry-hir/src/lower/expr_new.rs @@ -367,8 +367,7 @@ pub(super) fn lower_new(ctx: &mut LoweringContext, new_expr: &ast::NewExpr) -> R let is_module_constructor = ctx .lookup_native_module(callee_ident.sym.as_ref()) .map(|(module_name, method)| { - module_name == "module" - && matches!(method.as_deref(), Some("Module") | Some("default")) + module_name == "module" && matches!(method, Some("Module") | Some("default")) }) .unwrap_or(false); if is_module_constructor { @@ -404,8 +403,7 @@ pub(super) fn lower_new(ctx: &mut LoweringContext, new_expr: &ast::NewExpr) -> R let is_events_module_value = ctx .lookup_native_module(callee_ident.sym.as_ref()) .map(|(module_name, method)| { - module_name == "events" - && (method.is_none() || method.as_deref() == Some("default")) + module_name == "events" && (method.is_none() || method == Some("default")) }) .unwrap_or(false) || ctx.lookup_builtin_module_alias(callee_ident.sym.as_ref()) == Some("events"); @@ -586,7 +584,7 @@ pub(super) fn lower_new(ctx: &mut LoweringContext, new_expr: &ast::NewExpr) -> R ctx.lookup_native_module(obj_name) .and_then(|(module_name, method)| { if matches!(module_name, "dns" | "dns/promises") - && (method.is_none() || method.as_deref() == Some("default")) + && (method.is_none() || method == Some("default")) { Some(module_name.to_string()) } else { @@ -645,8 +643,7 @@ pub(super) fn lower_new(ctx: &mut LoweringContext, new_expr: &ast::NewExpr) -> R || ctx .lookup_native_module(obj_name) .map(|(module_name, method)| { - module_name == "vm" - && (method.is_none() || method.as_deref() == Some("default")) + module_name == "vm" && (method.is_none() || method == Some("default")) }) .unwrap_or(false); if is_vm_module diff --git a/crates/perry-hir/src/lower/lower_expr.rs b/crates/perry-hir/src/lower/lower_expr.rs index 3a1bc5d68..e2f541dcf 100644 --- a/crates/perry-hir/src/lower/lower_expr.rs +++ b/crates/perry-hir/src/lower/lower_expr.rs @@ -555,7 +555,7 @@ pub(crate) mod relower_trace { SPANS.with(|m| { *m.borrow_mut().entry((lo, hi)).or_insert(0) += 1; }); - if n % 5_000_000 == 0 { + if n.is_multiple_of(5_000_000) { dump(&format!("periodic@{n}")); } } diff --git a/crates/perry-hir/src/lower/mod.rs b/crates/perry-hir/src/lower/mod.rs index 4f6d28f6e..b4baea83a 100644 --- a/crates/perry-hir/src/lower/mod.rs +++ b/crates/perry-hir/src/lower/mod.rs @@ -38,24 +38,22 @@ mod context; pub(crate) mod expr_assign; mod expr_call; mod expr_function; -pub(crate) use expr_function::{capture_function_source, lower_fn_expr}; +pub(crate) use expr_function::capture_function_source; mod expr_member; -pub(crate) use expr_member::{wrap_private_guard, PRIV_OP_READ, PRIV_OP_WRITE}; +pub(crate) use expr_member::{wrap_private_guard, PRIV_OP_WRITE}; mod expr_misc; mod expr_new; mod expr_new_builtins; mod expr_object; -mod unimpl_hints; -pub(crate) use context::*; mod stmt; +mod unimpl_hints; pub(crate) use stmt::*; mod for_head; -pub(crate) use for_head::{for_head_binding_stmts, predefine_for_head, ForHeadBinding}; +pub(crate) use for_head::{for_head_binding_stmts, predefine_for_head}; mod stmt_loops; pub(crate) use stmt_loops::{ - insert_iterator_close_on_abrupt, iterator_close_guarded_stmt, iterator_next_call, - lazy_iter_for_stmt, lazy_or_index_elem, lower_stmt_for_in, lower_stmt_for_of, - wrap_lazy_for_of_body_close_on_throw, + insert_iterator_close_on_abrupt, lazy_iter_for_stmt, lazy_or_index_elem, lower_stmt_for_in, + lower_stmt_for_of, wrap_lazy_for_of_body_close_on_throw, }; mod module_decl; pub(crate) use module_decl::*; @@ -94,11 +92,8 @@ pub(crate) use typed_parse::{extract_typed_parse_source_order, resolve_typed_par mod array_fold; pub(crate) use array_fold::{ - is_known_array_prototype_method, is_known_array_static_method, is_known_json_static_method, - is_known_math_static_method, is_known_namespace_static_function, is_known_number_static_method, - is_known_object_prototype_method, is_known_object_static_method, - is_known_promise_static_method, is_known_string_prototype_method, - is_known_string_static_method, try_fold_array_method_call, + is_known_array_prototype_method, is_known_namespace_static_function, + is_known_object_prototype_method, is_known_string_prototype_method, try_fold_array_method_call, }; mod lower_module_fn; diff --git a/crates/perry-hir/src/lower/module_decl.rs b/crates/perry-hir/src/lower/module_decl.rs index 0d145c027..074a8d5aa 100644 --- a/crates/perry-hir/src/lower/module_decl.rs +++ b/crates/perry-hir/src/lower/module_decl.rs @@ -1320,9 +1320,9 @@ pub(crate) fn lower_module_decl( exported: alias_name, }); } - ast::Decl::TsModule(ts_module) => { + ast::Decl::TsModule(ts_module) // export namespace X { ... } — lower as a synthetic class with static members - if !ts_module.declare { + if !ts_module.declare => { if let Some(ref body) = ts_module.body { let ns_name = match &ts_module.id { ast::TsModuleName::Ident(ident) => ident.sym.to_string(), @@ -1340,7 +1340,6 @@ pub(crate) fn lower_module_decl( }); } } - } _ => {} } } @@ -1955,9 +1954,7 @@ pub(crate) fn lower_module_decl( /// body. `namespace A.B {}` (dotted form) and bodiless `declare` modules return /// `None`. fn nested_namespace_name(ts_module: &ast::TsModuleDecl) -> Option { - if ts_module.body.is_none() { - return None; - } + ts_module.body.as_ref()?; match &ts_module.id { ast::TsModuleName::Ident(ident) => Some(ident.sym.to_string()), ast::TsModuleName::Str(_) => None, @@ -2077,15 +2074,13 @@ pub(crate) fn lower_namespace_as_class( match item { ast::ModuleItem::ModuleDecl(ast::ModuleDecl::ExportDecl(export)) => { match &export.decl { - ast::Decl::Fn(fn_decl) => { - if fn_decl.function.body.is_some() { - let name = fn_decl.ident.sym.to_string(); - static_method_names.push(name.clone()); - // Pre-register exported functions so other namespace members can call them - if ctx.lookup_func(&name).is_none() { - let id = ctx.fresh_func(); - ctx.register_func(name, id); - } + ast::Decl::Fn(fn_decl) if fn_decl.function.body.is_some() => { + let name = fn_decl.ident.sym.to_string(); + static_method_names.push(name.clone()); + // Pre-register exported functions so other namespace members can call them + if ctx.lookup_func(&name).is_none() { + let id = ctx.fresh_func(); + ctx.register_func(name, id); } } ast::Decl::Var(var_decl) => { @@ -2104,32 +2099,30 @@ pub(crate) fn lower_namespace_as_class( } } // #5130: nested `export namespace Inner { ... }`. - ast::Decl::TsModule(ts_module) => { - if !ts_module.declare { - if let Some(name) = nested_namespace_name(ts_module) { - nested_ns_names.push(name); - } + ast::Decl::TsModule(ts_module) if !ts_module.declare => { + if let Some(name) = nested_namespace_name(ts_module) { + nested_ns_names.push(name); } } _ => {} } } // #5130: nested non-exported `namespace Inner { ... }`. - ast::ModuleItem::Stmt(ast::Stmt::Decl(ast::Decl::TsModule(ts_module))) => { - if !ts_module.declare { - if let Some(name) = nested_namespace_name(ts_module) { - nested_ns_names.push(name); - } + ast::ModuleItem::Stmt(ast::Stmt::Decl(ast::Decl::TsModule(ts_module))) + if !ts_module.declare => + { + if let Some(name) = nested_namespace_name(ts_module) { + nested_ns_names.push(name); } } // Pre-register non-exported functions (hoisted like JS) - ast::ModuleItem::Stmt(ast::Stmt::Decl(ast::Decl::Fn(fn_decl))) => { - if fn_decl.function.body.is_some() { - let name = fn_decl.ident.sym.to_string(); - if ctx.lookup_func(&name).is_none() { - let id = ctx.fresh_func(); - ctx.register_func(name, id); - } + ast::ModuleItem::Stmt(ast::Stmt::Decl(ast::Decl::Fn(fn_decl))) + if fn_decl.function.body.is_some() => + { + let name = fn_decl.ident.sym.to_string(); + if ctx.lookup_func(&name).is_none() { + let id = ctx.fresh_func(); + ctx.register_func(name, id); } } // Pre-register non-exported variables diff --git a/crates/perry-hir/src/lower/stmt.rs b/crates/perry-hir/src/lower/stmt.rs index 4c7734928..b7c282989 100644 --- a/crates/perry-hir/src/lower/stmt.rs +++ b/crates/perry-hir/src/lower/stmt.rs @@ -88,13 +88,11 @@ pub(crate) fn collect_for_of_pattern_leaves( out.push((name, id)); } ast::Pat::Array(arr_pat) => { - for elem in &arr_pat.elems { - if let Some(ep) = elem { - if let ast::Pat::Rest(rest) = ep { - collect_for_of_pattern_leaves(ctx, &rest.arg, out); - } else { - collect_for_of_pattern_leaves(ctx, ep, out); - } + for ep in arr_pat.elems.iter().flatten() { + if let ast::Pat::Rest(rest) = ep { + collect_for_of_pattern_leaves(ctx, &rest.arg, out); + } else { + collect_for_of_pattern_leaves(ctx, ep, out); } } } @@ -1149,9 +1147,9 @@ pub(crate) fn lower_stmt( } } } - ast::Decl::TsModule(ts_module) => { + ast::Decl::TsModule(ts_module) // namespace X { ... } — lower as a synthetic class with static members - if !ts_module.declare { + if !ts_module.declare => { if let Some(ref body) = ts_module.body { let ns_name = match &ts_module.id { ast::TsModuleName::Ident(ident) => ident.sym.to_string(), @@ -1164,7 +1162,6 @@ pub(crate) fn lower_stmt( push_class_dedup(module, class); } } - } // #853: `ast::Decl` is `#[non_exhaustive]` upstream — keep // this catch-all so a future SWC variant is dropped silently // (the supported variants above each have explicit handling). diff --git a/crates/perry-hir/src/lower_decl/block.rs b/crates/perry-hir/src/lower_decl/block.rs index e4463d86e..74e0d03f5 100644 --- a/crates/perry-hir/src/lower_decl/block.rs +++ b/crates/perry-hir/src/lower_decl/block.rs @@ -1,15 +1,11 @@ -use anyhow::{anyhow, bail, Result}; +use anyhow::{bail, Result}; use perry_types::{LocalId, Type}; use swc_ecma_ast as ast; use crate::analysis::*; use crate::destructuring::*; use crate::ir::*; -use crate::lower::{ - collect_for_of_pattern_leaves, emit_for_of_pattern_binding, lower_expr, LoweringContext, -}; -use crate::lower_patterns::*; -use crate::lower_types::*; +use crate::lower::LoweringContext; use super::*; @@ -272,10 +268,8 @@ fn cic_class(c: &ast::Class, in_cl: bool, out: &mut std::collections::HashSet) { use ast::Expr::*; match e { - Ident(i) => { - if in_cl { - out.insert(i.sym.to_string()); - } + Ident(i) if in_cl => { + out.insert(i.sym.to_string()); } Arrow(a) => { for p in &a.params { @@ -440,10 +434,8 @@ fn cic_assign_target( ) { if let ast::AssignTarget::Simple(s) = t { match s { - ast::SimpleAssignTarget::Ident(i) => { - if in_cl { - out.insert(i.id.sym.to_string()); - } + ast::SimpleAssignTarget::Ident(i) if in_cl => { + out.insert(i.id.sym.to_string()); } ast::SimpleAssignTarget::Member(m) => { cic_expr(&m.obj, in_cl, out); diff --git a/crates/perry-hir/src/lower_decl/body_stmt.rs b/crates/perry-hir/src/lower_decl/body_stmt.rs index a18257c86..4e3243432 100644 --- a/crates/perry-hir/src/lower_decl/body_stmt.rs +++ b/crates/perry-hir/src/lower_decl/body_stmt.rs @@ -1,4 +1,4 @@ -use anyhow::{anyhow, bail, Result}; +use anyhow::{anyhow, Result}; use perry_types::{LocalId, Type}; use swc_ecma_ast as ast; @@ -11,7 +11,6 @@ use crate::lower::{ wrap_lazy_for_of_body_close_on_throw, LoweringContext, }; use crate::lower_patterns::*; -use crate::lower_types::*; use super::class_computed::{ class_computed_member_registration_expr, push_deduped_class_computed_keys, diff --git a/crates/perry-hir/src/lower_decl/class_captures.rs b/crates/perry-hir/src/lower_decl/class_captures.rs index ac633fab5..80aa3aee6 100644 --- a/crates/perry-hir/src/lower_decl/class_captures.rs +++ b/crates/perry-hir/src/lower_decl/class_captures.rs @@ -1,25 +1,9 @@ -use anyhow::{anyhow, bail, Result}; use perry_types::{LocalId, Type}; -use swc_ecma_ast as ast; -use crate::analysis::*; -use crate::destructuring::*; use crate::ir::*; -use crate::lower::{ - collect_for_of_pattern_leaves, emit_for_of_pattern_binding, lower_expr, LoweringContext, -}; -use crate::lower_patterns::*; -use crate::lower_types::*; +use crate::lower::LoweringContext; use super::class_members::collect_method_captures; -use super::class_validation::*; -use super::enum_decl::*; -use super::fn_decl::*; -use super::helpers::*; -use super::interface_decl::*; -use super::private_members::*; -use super::type_alias::*; -use super::*; pub fn synthesize_class_captures( ctx: &mut LoweringContext, diff --git a/crates/perry-hir/src/lower_decl/class_decl.rs b/crates/perry-hir/src/lower_decl/class_decl.rs index baa013af0..cc1fea540 100644 --- a/crates/perry-hir/src/lower_decl/class_decl.rs +++ b/crates/perry-hir/src/lower_decl/class_decl.rs @@ -1,13 +1,9 @@ -use anyhow::{anyhow, bail, Result}; -use perry_types::{FuncId, LocalId, Type}; +use anyhow::Result; +use perry_types::{FuncId, Type}; use swc_ecma_ast as ast; -use crate::analysis::*; -use crate::destructuring::*; use crate::ir::*; -use crate::lower::{ - collect_for_of_pattern_leaves, emit_for_of_pattern_binding, lower_expr, LoweringContext, -}; +use crate::lower::{lower_expr, LoweringContext}; use crate::lower_patterns::*; use crate::lower_types::*; @@ -764,7 +760,7 @@ pub fn lower_class_decl( is_rest: false, arguments_object: None, }); - new_params.extend(getter.params.into_iter()); + new_params.extend(getter.params); let mut body = getter.body; crate::analysis::replace_this_in_stmts(&mut body, this_id); let top_fn = Function { diff --git a/crates/perry-hir/src/lower_decl/class_members.rs b/crates/perry-hir/src/lower_decl/class_members.rs index 67f117e49..6ada92826 100644 --- a/crates/perry-hir/src/lower_decl/class_members.rs +++ b/crates/perry-hir/src/lower_decl/class_members.rs @@ -1,13 +1,9 @@ -use anyhow::{anyhow, bail, Result}; +use anyhow::{anyhow, Result}; use perry_types::{LocalId, Type}; use swc_ecma_ast as ast; -use crate::analysis::*; -use crate::destructuring::*; use crate::ir::*; -use crate::lower::{ - collect_for_of_pattern_leaves, emit_for_of_pattern_binding, lower_expr, LoweringContext, -}; +use crate::lower::{lower_expr, LoweringContext}; use crate::lower_patterns::*; use crate::lower_types::*; diff --git a/crates/perry-hir/src/lower_decl/class_validation.rs b/crates/perry-hir/src/lower_decl/class_validation.rs index bd82b6c10..69d3c179c 100644 --- a/crates/perry-hir/src/lower_decl/class_validation.rs +++ b/crates/perry-hir/src/lower_decl/class_validation.rs @@ -1,18 +1,6 @@ -use anyhow::{anyhow, bail, Result}; -use perry_types::{LocalId, Type}; +use anyhow::{bail, Result}; use swc_ecma_ast as ast; -use crate::analysis::*; -use crate::destructuring::*; -use crate::ir::*; -use crate::lower::{ - collect_for_of_pattern_leaves, emit_for_of_pattern_binding, lower_expr, LoweringContext, -}; -use crate::lower_patterns::*; -use crate::lower_types::*; - -use super::*; - pub fn validate_legacy_decorator_surface(class: &ast::Class, class_name: &str) -> Result<()> { for member in &class.body { match member { @@ -91,10 +79,8 @@ pub fn validate_class_element_early_errors(class: &ast::Class, class_name: &str) // are type-only declarations, not constructors — only the // implementation (the one with a body) counts (#4872, rxjs's // `Notification` has 3 overload signatures + 1 implementation). - ast::ClassMember::Constructor(c) => { - if c.body.is_some() { - constructor_count += 1; - } + ast::ClassMember::Constructor(c) if c.body.is_some() => { + constructor_count += 1; } ast::ClassMember::Method(m) => { let Some(name) = static_prop_name(&m.key) else { diff --git a/crates/perry-hir/src/lower_decl/enum_decl.rs b/crates/perry-hir/src/lower_decl/enum_decl.rs index 09b48e924..44e3ea720 100644 --- a/crates/perry-hir/src/lower_decl/enum_decl.rs +++ b/crates/perry-hir/src/lower_decl/enum_decl.rs @@ -1,17 +1,8 @@ -use anyhow::{anyhow, bail, Result}; -use perry_types::{LocalId, Type}; +use anyhow::Result; use swc_ecma_ast as ast; -use crate::analysis::*; -use crate::destructuring::*; use crate::ir::*; -use crate::lower::{ - collect_for_of_pattern_leaves, emit_for_of_pattern_binding, lower_expr, LoweringContext, -}; -use crate::lower_patterns::*; -use crate::lower_types::*; - -use super::*; +use crate::lower::LoweringContext; pub fn lower_enum_decl( ctx: &mut LoweringContext, diff --git a/crates/perry-hir/src/lower_decl/fn_decl.rs b/crates/perry-hir/src/lower_decl/fn_decl.rs index 3ac01da98..fa5e6021e 100644 --- a/crates/perry-hir/src/lower_decl/fn_decl.rs +++ b/crates/perry-hir/src/lower_decl/fn_decl.rs @@ -1,14 +1,9 @@ -use anyhow::{anyhow, bail, Result}; +use anyhow::Result; use perry_types::{LocalId, Type}; use swc_ecma_ast as ast; -use crate::analysis::*; -use crate::destructuring::*; use crate::ir::*; -use crate::lower::{ - capture_function_source, collect_for_of_pattern_leaves, emit_for_of_pattern_binding, - lower_expr, LoweringContext, -}; +use crate::lower::{capture_function_source, LoweringContext}; use crate::lower_patterns::*; use crate::lower_types::*; diff --git a/crates/perry-hir/src/lower_decl/helpers.rs b/crates/perry-hir/src/lower_decl/helpers.rs index d7ecc428a..44af6ac74 100644 --- a/crates/perry-hir/src/lower_decl/helpers.rs +++ b/crates/perry-hir/src/lower_decl/helpers.rs @@ -4,18 +4,11 @@ //! enum declarations, interface declarations, type alias declarations, //! constructors, class methods, getters, setters, and class properties. -use anyhow::{anyhow, bail, Result}; use perry_types::{LocalId, Type}; use swc_ecma_ast as ast; -use crate::analysis::*; -use crate::destructuring::*; use crate::ir::*; -use crate::lower::{ - collect_for_of_pattern_leaves, emit_for_of_pattern_binding, lower_expr, - throw_reference_error_expr, LoweringContext, -}; -use crate::lower_patterns::*; +use crate::lower::{throw_reference_error_expr, LoweringContext}; use crate::lower_types::*; use crate::walker::walk_expr_children_mut; diff --git a/crates/perry-hir/src/lower_decl/interface_decl.rs b/crates/perry-hir/src/lower_decl/interface_decl.rs index 0cb6f88e1..83c797f9e 100644 --- a/crates/perry-hir/src/lower_decl/interface_decl.rs +++ b/crates/perry-hir/src/lower_decl/interface_decl.rs @@ -1,18 +1,11 @@ -use anyhow::{anyhow, bail, Result}; -use perry_types::{LocalId, Type}; +use anyhow::Result; +use perry_types::Type; use swc_ecma_ast as ast; -use crate::analysis::*; -use crate::destructuring::*; use crate::ir::*; -use crate::lower::{ - collect_for_of_pattern_leaves, emit_for_of_pattern_binding, lower_expr, LoweringContext, -}; -use crate::lower_patterns::*; +use crate::lower::LoweringContext; use crate::lower_types::*; -use super::*; - pub fn lower_interface_decl( ctx: &mut LoweringContext, iface_decl: &ast::TsInterfaceDecl, diff --git a/crates/perry-hir/src/lower_decl/mod.rs b/crates/perry-hir/src/lower_decl/mod.rs index 8e50207b0..ccbbce0ed 100644 --- a/crates/perry-hir/src/lower_decl/mod.rs +++ b/crates/perry-hir/src/lower_decl/mod.rs @@ -29,7 +29,6 @@ mod typeof_narrow; // this list in sync with each sibling's `pub fn` declarations. pub(crate) use block::{ collect_annexb_block_fn_decl_names, collect_lexical_decl_names, - collect_refs_in_closure_bodies_stmt, collect_top_level_let_ids_stmt, collect_var_binding_names_from_stmt, compute_prealloc_for_hoisted_closures, lower_block_stmt, lower_block_stmt_scoped, lower_fn_body_block_stmt, lower_stmts_using_aware, pre_register_forward_captured_lets, diff --git a/crates/perry-hir/src/lower_decl/private_members.rs b/crates/perry-hir/src/lower_decl/private_members.rs index bae5b0883..2138364c2 100644 --- a/crates/perry-hir/src/lower_decl/private_members.rs +++ b/crates/perry-hir/src/lower_decl/private_members.rs @@ -1,13 +1,9 @@ -use anyhow::{anyhow, bail, Result}; +use anyhow::Result; use perry_types::{LocalId, Type}; use swc_ecma_ast as ast; -use crate::analysis::*; -use crate::destructuring::*; use crate::ir::*; -use crate::lower::{ - collect_for_of_pattern_leaves, emit_for_of_pattern_binding, lower_expr, LoweringContext, -}; +use crate::lower::{lower_expr, LoweringContext}; use crate::lower_patterns::*; use crate::lower_types::*; diff --git a/crates/perry-hir/src/lower_decl/type_alias.rs b/crates/perry-hir/src/lower_decl/type_alias.rs index 72980db4d..d837bc8c2 100644 --- a/crates/perry-hir/src/lower_decl/type_alias.rs +++ b/crates/perry-hir/src/lower_decl/type_alias.rs @@ -1,18 +1,10 @@ -use anyhow::{anyhow, bail, Result}; -use perry_types::{LocalId, Type}; +use anyhow::Result; use swc_ecma_ast as ast; -use crate::analysis::*; -use crate::destructuring::*; use crate::ir::*; -use crate::lower::{ - collect_for_of_pattern_leaves, emit_for_of_pattern_binding, lower_expr, LoweringContext, -}; -use crate::lower_patterns::*; +use crate::lower::LoweringContext; use crate::lower_types::*; -use super::*; - pub fn lower_type_alias_decl( ctx: &mut LoweringContext, alias_decl: &ast::TsTypeAliasDecl, diff --git a/crates/perry-hir/src/monomorph/mod.rs b/crates/perry-hir/src/monomorph/mod.rs index 3ba0ce803..bc9b97ec1 100644 --- a/crates/perry-hir/src/monomorph/mod.rs +++ b/crates/perry-hir/src/monomorph/mod.rs @@ -46,6 +46,8 @@ pub(crate) use infer::{ unify_rest_param_types, unify_types, }; pub(crate) use inference_lookup::{ClassInfo, FuncInfo, InferenceLookup}; -pub(crate) use mangle::{generate_specialized_name, mangle_type, mangle_type_args}; +#[cfg(test)] +pub(crate) use mangle::mangle_type; +pub(crate) use mangle::{generate_specialized_name, mangle_type_args}; pub(crate) use substitute_expr::{substitute_expr, substitute_stmts}; pub(crate) use update_call_sites::update_call_sites;