diff --git a/CLAUDE.md b/CLAUDE.md index 4d80c7f41a..754ee79942 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -8,7 +8,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co Perry is a native TypeScript compiler written in Rust that compiles TypeScript source code directly to native executables. It uses SWC for TypeScript parsing and LLVM for code generation. -**Current Version:** 0.5.1515 +**Current Version:** 0.5.1516 ## TypeScript Parity Status diff --git a/Cargo.lock b/Cargo.lock index 66eccccb6d..9bdb2fefa1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5522,7 +5522,7 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "perry" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "anyhow", "base64 0.22.1", @@ -5582,7 +5582,7 @@ dependencies = [ [[package]] name = "perry-api-manifest" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "perry-dispatch", "serde", @@ -5590,7 +5590,7 @@ dependencies = [ [[package]] name = "perry-audio-miniaudio" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "cc", "libc", @@ -5599,7 +5599,7 @@ dependencies = [ [[package]] name = "perry-codegen" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "anyhow", "inkwell", @@ -5616,7 +5616,7 @@ dependencies = [ [[package]] name = "perry-codegen-arkts" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "anyhow", "perry-hir", @@ -5624,7 +5624,7 @@ dependencies = [ [[package]] name = "perry-codegen-glance" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "anyhow", "perry-hir", @@ -5632,7 +5632,7 @@ dependencies = [ [[package]] name = "perry-codegen-js" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "anyhow", "perry-dispatch", @@ -5641,7 +5641,7 @@ dependencies = [ [[package]] name = "perry-codegen-swiftui" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "anyhow", "perry-hir", @@ -5649,7 +5649,7 @@ dependencies = [ [[package]] name = "perry-codegen-wasm" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "anyhow", "base64 0.22.1", @@ -5661,7 +5661,7 @@ dependencies = [ [[package]] name = "perry-codegen-wear-tiles" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "anyhow", "perry-hir", @@ -5669,7 +5669,7 @@ dependencies = [ [[package]] name = "perry-container-compose" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "anyhow", "async-trait", @@ -5698,14 +5698,14 @@ dependencies = [ [[package]] name = "perry-container-e2e" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "anyhow", ] [[package]] name = "perry-diagnostics" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "serde", "serde_json", @@ -5713,7 +5713,7 @@ dependencies = [ [[package]] name = "perry-dispatch" -version = "0.5.1515" +version = "0.5.1516" [[package]] name = "perry-doc-fixture-my-bindings" @@ -5724,7 +5724,7 @@ dependencies = [ [[package]] name = "perry-doc-tests" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "anyhow", "clap", @@ -5739,7 +5739,7 @@ dependencies = [ [[package]] name = "perry-ext-ads" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "block2", "objc2", @@ -5749,7 +5749,7 @@ dependencies = [ [[package]] name = "perry-ext-argon2" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "argon2", "perry-ffi", @@ -5758,7 +5758,7 @@ dependencies = [ [[package]] name = "perry-ext-axios" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "perry-ffi", "reqwest", @@ -5767,7 +5767,7 @@ dependencies = [ [[package]] name = "perry-ext-bcrypt" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "bcrypt", "perry-ffi", @@ -5775,7 +5775,7 @@ dependencies = [ [[package]] name = "perry-ext-better-sqlite3" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "perry-ffi", "rusqlite", @@ -5783,7 +5783,7 @@ dependencies = [ [[package]] name = "perry-ext-cheerio" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "perry-ffi", "scraper", @@ -5791,7 +5791,7 @@ dependencies = [ [[package]] name = "perry-ext-commander" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "perry-ffi", "perry-runtime", @@ -5799,7 +5799,7 @@ dependencies = [ [[package]] name = "perry-ext-cron" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "chrono", "cron", @@ -5809,7 +5809,7 @@ dependencies = [ [[package]] name = "perry-ext-dayjs" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "chrono", "perry-ffi", @@ -5817,7 +5817,7 @@ dependencies = [ [[package]] name = "perry-ext-decimal" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "perry-ffi", "rust_decimal", @@ -5825,7 +5825,7 @@ dependencies = [ [[package]] name = "perry-ext-dotenv" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "perry-ffi", "serde_json", @@ -5833,7 +5833,7 @@ dependencies = [ [[package]] name = "perry-ext-ethers" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "perry-ffi", "rand 0.10.1", @@ -5841,7 +5841,7 @@ dependencies = [ [[package]] name = "perry-ext-events" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "perry-ffi", "perry-runtime", @@ -5849,14 +5849,14 @@ dependencies = [ [[package]] name = "perry-ext-exponential-backoff" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "perry-ffi", ] [[package]] name = "perry-ext-fastify" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "bytes", "http-body-util", @@ -5874,7 +5874,7 @@ dependencies = [ [[package]] name = "perry-ext-fetch" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "bytes", "lazy_static", @@ -5887,7 +5887,7 @@ dependencies = [ [[package]] name = "perry-ext-http" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "base64 0.22.1", "bytes", @@ -5912,7 +5912,7 @@ dependencies = [ [[package]] name = "perry-ext-ioredis" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "lazy_static", "perry-ffi", @@ -5922,7 +5922,7 @@ dependencies = [ [[package]] name = "perry-ext-jsonwebtoken" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "base64 0.22.1", "jsonwebtoken", @@ -5933,7 +5933,7 @@ dependencies = [ [[package]] name = "perry-ext-lru-cache" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "lru", "perry-ffi", @@ -5942,7 +5942,7 @@ dependencies = [ [[package]] name = "perry-ext-moment" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "chrono", "perry-ffi", @@ -5950,7 +5950,7 @@ dependencies = [ [[package]] name = "perry-ext-mongodb" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "bson", "futures-util", @@ -5962,7 +5962,7 @@ dependencies = [ [[package]] name = "perry-ext-mysql2" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "chrono", "perry-ffi", @@ -5972,7 +5972,7 @@ dependencies = [ [[package]] name = "perry-ext-nanoid" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "nanoid", "perry-ffi", @@ -5981,7 +5981,7 @@ dependencies = [ [[package]] name = "perry-ext-net" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "bytes", "perry-ffi", @@ -5994,7 +5994,7 @@ dependencies = [ [[package]] name = "perry-ext-node-forge" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "const-oid 0.9.6", "der 0.7.10", @@ -6013,7 +6013,7 @@ dependencies = [ [[package]] name = "perry-ext-nodemailer" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "lettre", "perry-ffi", @@ -6023,7 +6023,7 @@ dependencies = [ [[package]] name = "perry-ext-pdf" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "perry-ffi", "printpdf", @@ -6031,7 +6031,7 @@ dependencies = [ [[package]] name = "perry-ext-pg" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "perry-ffi", "sqlx", @@ -6040,7 +6040,7 @@ dependencies = [ [[package]] name = "perry-ext-ratelimit" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "governor", "perry-ffi", @@ -6048,7 +6048,7 @@ dependencies = [ [[package]] name = "perry-ext-sharp" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "fast_image_resize", "image", @@ -6058,14 +6058,14 @@ dependencies = [ [[package]] name = "perry-ext-slugify" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "perry-ffi", ] [[package]] name = "perry-ext-streams" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "lazy_static", "perry-ffi", @@ -6074,7 +6074,7 @@ dependencies = [ [[package]] name = "perry-ext-undici" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "perry-ffi", "perry-runtime", @@ -6083,7 +6083,7 @@ dependencies = [ [[package]] name = "perry-ext-uuid" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "perry-ffi", "uuid", @@ -6091,7 +6091,7 @@ dependencies = [ [[package]] name = "perry-ext-validator" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "perry-ffi", "regex", @@ -6101,7 +6101,7 @@ dependencies = [ [[package]] name = "perry-ext-ws" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "futures-util", "lazy_static", @@ -6114,7 +6114,7 @@ dependencies = [ [[package]] name = "perry-ext-zlib" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "brotli", "flate2", @@ -6124,7 +6124,7 @@ dependencies = [ [[package]] name = "perry-ffi" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "dashmap", "once_cell", @@ -6133,7 +6133,7 @@ dependencies = [ [[package]] name = "perry-hir" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "anyhow", "perry-api-manifest", @@ -6151,7 +6151,7 @@ dependencies = [ [[package]] name = "perry-parser" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "anyhow", "perry-diagnostics", @@ -6163,7 +6163,7 @@ dependencies = [ [[package]] name = "perry-runtime" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "anyhow", "base64 0.22.1", @@ -6205,14 +6205,14 @@ dependencies = [ [[package]] name = "perry-runtime-static" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "perry-runtime", ] [[package]] name = "perry-stdlib" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "aes 0.8.4", "aes 0.9.1", @@ -6307,14 +6307,14 @@ dependencies = [ [[package]] name = "perry-stdlib-static" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "perry-stdlib", ] [[package]] name = "perry-transform" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "anyhow", "perry-hir", @@ -6323,14 +6323,14 @@ dependencies = [ [[package]] name = "perry-ui" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "perry-ui-model", ] [[package]] name = "perry-ui-android" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "base64 0.22.1", "itoa", @@ -6348,7 +6348,7 @@ dependencies = [ [[package]] name = "perry-ui-geisterhand" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "rand 0.10.1", "serde", @@ -6358,7 +6358,7 @@ dependencies = [ [[package]] name = "perry-ui-gtk4" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "base64 0.22.1", "cairo-rs 0.22.0", @@ -6381,7 +6381,7 @@ dependencies = [ [[package]] name = "perry-ui-ios" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "base64 0.22.1", "block2", @@ -6398,7 +6398,7 @@ dependencies = [ [[package]] name = "perry-ui-macos" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "base64 0.22.1", "block2", @@ -6414,7 +6414,7 @@ dependencies = [ [[package]] name = "perry-ui-model" -version = "0.5.1515" +version = "0.5.1516" [[package]] name = "perry-ui-test" @@ -6425,11 +6425,11 @@ dependencies = [ [[package]] name = "perry-ui-testkit" -version = "0.5.1515" +version = "0.5.1516" [[package]] name = "perry-ui-tvos" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "base64 0.22.1", "block2", @@ -6446,7 +6446,7 @@ dependencies = [ [[package]] name = "perry-ui-visionos" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "base64 0.22.1", "block2", @@ -6463,7 +6463,7 @@ dependencies = [ [[package]] name = "perry-ui-watchos" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "block2", "libc", @@ -6477,7 +6477,7 @@ dependencies = [ [[package]] name = "perry-ui-windows" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "base64 0.22.1", "libc", @@ -6496,14 +6496,14 @@ dependencies = [ [[package]] name = "perry-ui-windows-winui" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "perry-ui-windows", ] [[package]] name = "perry-updater" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "anyhow", "base64 0.22.1", @@ -6519,7 +6519,7 @@ dependencies = [ [[package]] name = "perry-wasm-host" -version = "0.5.1515" +version = "0.5.1516" dependencies = [ "wasmi", ] diff --git a/Cargo.toml b/Cargo.toml index b8d1071854..4c9ba47ea5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -315,7 +315,7 @@ codegen-units = 16 codegen-units = 16 [workspace.package] -version = "0.5.1515" +version = "0.5.1516" edition = "2021" license = "MIT" repository = "https://github.com/PerryTS/perry" diff --git a/changelog.d/8548-require-stdlib-link.md b/changelog.d/8548-require-stdlib-link.md deleted file mode 100644 index 926c7d457d..0000000000 --- a/changelog.d/8548-require-stdlib-link.md +++ /dev/null @@ -1,28 +0,0 @@ -**`require('http')` linked runtime-only, so every stdlib-backed builtin reached that way returned `undefined` (#8547).** - -Same program, two import forms, opposite outcomes: - -``` -import * as http from 'node:http'; → Linking (with stdlib)... typeof createServer() === "object" -const http = require('http'); → Linking (runtime-only)... typeof createServer() === undefined -``` - -**Cause.** `ctx.native_module_imports` — which drives `needs_stdlib` and therefore the link mode — was populated only by the ESM import walk in `collect_modules.rs`. A CommonJS `require("http")` never landed in it, so the link came out runtime-only, `perry-stdlib`'s `common/dispatch/init.rs` never ran, `JS_NATIVE_HTTP_DISPATCH` stayed null, and the `("http", "createServer")` arm in `native_module_dispatch/dispatch_d_i.rs` took its documented null branch and returned `undefined`. Nothing about this was http-specific: any stdlib-backed builtin reached through `require` behaved the same way. - -**Why the obvious fix does not work.** Recovering the requirement from the lowered HIR — the way `uses_dgram` does — fails, and it is worth writing down so nobody retries it. For `require('http')` the module name never becomes a `module:` marker; the CJS shim emits a *runtime* dispatcher that switches over builtin names as string literals, and that switch contains a case for **every** builtin regardless of what the program uses. A static scan of the HIR would match the table rather than the call and link the stdlib into every CJS program. - -The fix therefore reads the literal call sites, which is exactly what `cjs_wrap::extract_require_specifiers` already extracts for CJS wrapping: any `require("")` whose specifier satisfies `perry_hir::requires_stdlib` now feeds `needs_stdlib` / `native_module_imports` alongside the import walk. - -**Scope, verified by measurement** — the change can only add stdlib linking for a program that genuinely references a stdlib-backed builtin: - -| program | link mode | binary | -|---|---|---| -| `console.log(...)` only | runtime-only (unchanged) | 7.7 MB | -| `require("path")` (runtime-only module) | runtime-only (unchanged) | 7.8 MB | -| `require("http")` | with stdlib (was runtime-only) | 14 MB | - -Dynamic `require(someVar)` remains statically undetectable and is unchanged; the generated dispatcher can reach any builtin, so whether that case should force stdlib linking is a separate product decision, noted on #8547. - -`crates/perry/tests/issue_4903_listen_callback_deferred.rs` goes 0/2 → 2/2, which clears the last sweep-tier `cargo-test` failure on `main`. - -Closes #8547. diff --git a/changelog.d/8549-revert-require-stdlib-link.md b/changelog.d/8549-revert-require-stdlib-link.md new file mode 100644 index 0000000000..7f760fe935 --- /dev/null +++ b/changelog.d/8549-revert-require-stdlib-link.md @@ -0,0 +1,19 @@ +**Revert "treat `require()` as a stdlib requirement" (#8548) — it caused a runtime-only link failure.** + +#8548 fixed a real bug (#8547: `require('http')` linked runtime-only, so every stdlib-backed builtin reached that way returned `undefined`, and `issue_4903_listen_callback_deferred` went 0/2 → 2/2). It also broke `issue_5247_property_read_source_location`, which had been passing: + +``` +compile ["--debug-symbols"] must succeed; stderr: +/usr/bin/ld: libperry_runtime.a(...): in function `js_webassembly_validate': + undefined reference to `perry_wasm_host_validate' + undefined reference to `perry_wasm_host_module_new' + … collect2: error: ld returned 1 exit status +``` + +**Attribution is solid, which is why this is a revert and not a follow-up patch.** The suite passed on `1c2326554` (the commit immediately before) and fails on `b00e261f8` (with #8548) in **both** sweep runs of that SHA — deterministic, not a flake. It does *not* reproduce locally, which is the tell for a feature-unification effect rather than a logic error: under `cargo test --workspace` cargo unifies features across the whole graph, so pulling perry-stdlib onto more compile paths changes what `target/debug/libperry_runtime.a` contains. The archive then carries `webassembly.rs`'s code, whose `extern` declarations are satisfied only by the separate `perry-wasm-host` crate — which a runtime-only link line does not include. + +So the honest position is that #8548's *diagnosis* stands and its *link-mode consequence* was not thought through: making a program need the stdlib is not free, and the runtime-only link path is not prepared for everything the stdlib's feature set drags into the runtime archive. Fixing #8547 properly needs that interaction handled — either by ensuring `perry-wasm-host` is on the link line whenever the runtime archive contains wasm code, or by keeping the wasm surface out of it. + +Net effect of this revert: `issue_4903` returns to failing (2 tests, the pre-existing #8547 symptom) and `issue_5247` returns to passing (3 tests). Main is red either way; this restores the *known* red rather than a new link-level one, which is the safer state to leave a release branch in — a link regression can bite real builds, not just tests. + +Reopens #8547. diff --git a/crates/perry/src/commands/compile/cjs_wrap/mod.rs b/crates/perry/src/commands/compile/cjs_wrap/mod.rs index 184a342fdd..76face80f3 100644 --- a/crates/perry/src/commands/compile/cjs_wrap/mod.rs +++ b/crates/perry/src/commands/compile/cjs_wrap/mod.rs @@ -54,11 +54,9 @@ use extract_exports::{ extract_object_literal_exports_from_require, extract_single_module_exports_assignment, module_reexport_specs, }; -// #8547: the stdlib-link decision needs the literal `require()` specifiers. -pub(crate) use extract_requires::extract_require_specifiers; use extract_requires::{ - extract_export_star_specs, extract_require_aliases_with_ranges, function_local_specs, - identifier_is_declared_binding, identifier_is_reassigned, + extract_export_star_specs, extract_require_aliases_with_ranges, extract_require_specifiers, + function_local_specs, identifier_is_declared_binding, identifier_is_reassigned, }; use hoist_classes::{ extract_top_level_class_decls, rewrite_module_exports_class_expression, diff --git a/crates/perry/src/commands/compile/collect_modules.rs b/crates/perry/src/commands/compile/collect_modules.rs index 2b10ba7074..af32e694db 100644 --- a/crates/perry/src/commands/compile/collect_modules.rs +++ b/crates/perry/src/commands/compile/collect_modules.rs @@ -386,25 +386,6 @@ fn collect_module_one( &ctx.compile_packages, canonical.parent().unwrap_or_else(|| Path::new(".")), ); - - // #8547: a builtin reached through `require("http")` never appears in the - // ESM import walk below, so `needs_stdlib` stayed false, the link came out - // runtime-only, `perry-stdlib`'s dispatch init never ran, and every - // stdlib-backed export returned `undefined` (`http.createServer` was the - // reported case; the bug is not http-specific). The lowered body cannot - // answer this — the CJS shim resolves the name through a generated runtime - // switch that contains EVERY builtin — so recover it from the literal - // call sites, which is exactly what `extract_require_specifiers` already - // finds for CJS wrapping. Dynamic `require(someVar)` remains undetectable - // and is unchanged. - for spec in super::cjs_wrap::extract_require_specifiers(&source) { - if !perry_hir::requires_stdlib(&spec) { - continue; - } - ctx.needs_stdlib = true; - let normalized = spec.strip_prefix("node:").unwrap_or(&spec).to_string(); - ctx.native_module_imports.insert(normalized); - } if was_cjs_wrapped && ctx.debug_symbols { if let Some(prefix_lines) = cjs_wrap_body_prefix_lines { let lines_after_transform = source.bytes().filter(|&b| b == b'\n').count();