diff --git a/.github/workflows/release-packages.yml b/.github/workflows/release-packages.yml index b343c46ce3..8d67dff2a7 100644 --- a/.github/workflows/release-packages.yml +++ b/.github/workflows/release-packages.yml @@ -1685,8 +1685,15 @@ jobs: # died on the first package with "You cannot publish over the # previously published versions" — the remaining six packages could # never go out (run 27239815088). + # One platform's failure must not starve the packages after it in + # glob order (with `set -e` a single E413/transient registry error + # aborted the loop mid-way — exactly how linux/windows sat at a stale + # version for weeks while darwin kept updating). Record failures, + # keep publishing, fail the step at the end with the full list; the + # already-published skip above keeps re-runs idempotent. run: | set -e + failed="" for pkg in ./npm/perry-*; do name=$(node -p "require('$pkg/package.json').name") ver=$(node -p "require('$pkg/package.json').version") @@ -1695,8 +1702,15 @@ jobs: continue fi echo "=== publishing $pkg ===" - npm publish "$pkg" --access public --provenance + if ! npm publish "$pkg" --access public --provenance; then + echo "::error::npm publish failed for $name@$ver — continuing with remaining packages" + failed="$failed $name@$ver" + fi done + if [ -n "$failed" ]; then + echo "::error::failed platform packages:$failed" + exit 1 + fi - name: Publish wrapper (@perryts/perry) last run: | diff --git a/CHANGELOG.md b/CHANGELOG.md index a63b6b8e4d..3ee7b66fcb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## v0.5.1223 — audit-found capability-doc drift corrected; npm publish loop survives per-package failures (#5935) + +Docs: lookbehind regex WORKS (regex→fancy-regex hybrid) — removed from CLAUDE.md categorical gaps and rewritten in porting.md (section/table/scan-list); CLAUDE.md GC facts refreshed (~55 registered scanners, conservative scan production-off, module vars uniformly NaN-boxed + rooted — module_var_data_ids is long gone); limitations.md prototype section rewritten around reality (prototype-method assignment + setPrototypeOf supported; the two real gaps: `obj.__proto__ = x` assignment form, literal `{__proto__: []}` not visible to instanceof); gap-suite count 235→258. CI: release-packages.yml platform-publish loop no longer aborts on the first failure under set -e (the mechanism that left npm linux/windows stale while darwin updated) — failures are recorded, the loop continues, the step fails at the end with the full list. + ## v0.5.1222 — await/yield in loop condition/update runs per iteration (#5934, fixes #5933) The async hoist's single pre-loop hoist (its own comment: "safe-but-incomplete approximation") evaluated a loop condition's await ONCE — async drain loops (`while ((v = await q.next()) !== undefined)`) never re-awaited (truthy first value spun forever on stale state, falsy never entered), `do…while` evaluated the condition before the first body run, and generators had the sibling defect at the linearize layer (`while (yield …)` cloned the condition into the cond state where residual yields lower to `0.0`). Restructured instead of hoisting out, preserving break/continue: `while (C)` → `while(true){ let t = C; if (!t) break; body }` (continue re-enters at the condition eval, per spec); `do B while (C)` → first-iteration flag + `while (first || C)` (body precedes first cond eval; continue falls through to the eval); `for (init; C; U)` keeps the For — awaited C moves to a body-top check with the condition slot emptied, awaited U moves to body end with every loop-level continue prefixed by it (new shared `prefix_loop_continues`). Linearize gains the three guarded yield-twin arms for direct generators. Review hardening: the update move bails to the previous lowering when a `continue` sits inside `try{}finally{}` (abrupt completion — the finally must run before the update and may override it), including the linearize arm guard so a fully-bailed For can't re-match its own desugar. e2e: `issue_5933_loop_condition_await.rs` (8 scenarios byte-for-byte vs node). diff --git a/CLAUDE.md b/CLAUDE.md index be46e6d3db..e215b42ea6 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -8,12 +8,12 @@ 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.1222 +**Current Version:** 0.5.1223 ## TypeScript Parity Status -Tracked via the gap test suite (`test-files/test_gap_*.ts`, 235 tests). Compared byte-for-byte against `node --experimental-strip-types`. Run via `./scripts/run_gap_tests.sh` (a thin wrapper over `run_parity_tests.sh --filter test_gap_` that builds the compiler itself and gates on no new untriaged failures). +Tracked via the gap test suite (`test-files/test_gap_*.ts`, 258 tests). Compared byte-for-byte against `node --experimental-strip-types`. Run via `./scripts/run_gap_tests.sh` (a thin wrapper over `run_parity_tests.sh --filter test_gap_` that builds the compiler itself and gates on no new untriaged failures). **Last full sweep:** run `./run_parity_tests.sh` for the current snapshot. The umbrella tracker is #793 (Node.js + TypeScript compatibility roadmap); the previously-cited #447–#452 batch closed on 2026-05-04. Currently-open trackers worth knowing about: @@ -23,7 +23,7 @@ Tracked via the gap test suite (`test-files/test_gap_*.ts`, 235 tests). Compared - **Test/CI mechanics** — `#794` (per-category parity thresholds), `#796` (gap-suite output truncation + O(n²) `normalize_output`), `#812` (42-module behavioral matrix), `#806/#807/#808` (test harnesses for mixins / async context / ≥300-init scale). - **Skip-list audit** — `#797` covers `test-parity/known_failures.json` provenance (issue # + date per entry). -**Known categorical gaps**: lookbehind regex (Rust `regex` crate), `console.dir`/`console.group*` formatting, lone surrogate handling (WTF-8). +**Known categorical gaps**: `console.dir`/`console.group*` formatting, lone surrogate handling (WTF-8). (Lookbehind regex is NOT a gap anymore: `perry-runtime/src/regex.rs` falls back from the `regex` crate to `fancy-regex` for lookbehind/backreferences, with capture-group translation and replacement expansion.) ## Workflow Requirements @@ -101,11 +101,11 @@ TAG_TRUE = 0x7FFC_0000_0000_0004 STRING_TAG = 0x7FFF (lower 48 = ptr) Key functions: `js_nanbox_string/pointer/bigint`, `js_nanbox_get_pointer`, `js_get_string_pointer_unified`, `js_jsvalue_to_string`, `js_is_truthy` -**Module-level variables**: Strings stored as F64 (NaN-boxed), Arrays/Objects as I64 (raw pointers). Access via `module_var_data_ids`. +**Module-level variables**: uniform NaN-boxed doubles in `@perry_global___` LLVM globals, all registered as GC roots before module init (marked AND rewritten on evacuation). The old F64-strings/raw-I64-arrays split and `module_var_data_ids` no longer exist (a stale comment survives in `perry-transform/src/inline/mod.rs`). ## Garbage Collection -Generational mark-sweep GC in `crates/perry-runtime/src/gc.rs` (default since v0.5.237 / Phase D). Two regions in the per-thread arena: nursery (`ARENA`, fills with new allocations, swept on minor GC) and old-gen (`OLD_ARENA`, holds tenured/evacuated objects). Conservative stack scan + precise shadow-stack roots + 9 registered scanners. Write barriers populate a remembered set so minor GC can avoid retracing the old-gen. Two-bit aging (`HAS_SURVIVED` / `TENURED`) promotes nursery survivors after 2 minor cycles; the C4b evacuation policy moves non-pinned tenured objects into old-gen with full reference rewriting only when generated write barriers are active and nursery/RSS pressure plus measured movable candidates justify the work. Idle nursery blocks observed empty for 2 GC cycles are `dealloc`'d back to the OS (C4b-δ, v0.5.235), and the next-trigger calc is hard-capped at the initial threshold (64 MB) so >90%-freed step-doubling can't blow up peak occupancy (C4b-δ-tune, v0.5.236). Triggers on arena block allocation (1 MB blocks since v0.5.196), malloc count threshold, or explicit `gc()` call. 8-byte GcHeader per allocation. +Generational mark-sweep GC in `crates/perry-runtime/src/gc.rs` (default since v0.5.237 / Phase D). Two regions in the per-thread arena: nursery (`ARENA`, fills with new allocations, swept on minor GC) and old-gen (`OLD_ARENA`, holds tenured/evacuated objects). Precise shadow-stack roots + ~55 registered side-table scanners (`gc/mod.rs:298+`); a conservative stack scan exists but production mode resolves to SkipDisabled, so liveness rests on codegen shadow-stack spilling plus `RuntimeHandleScope` in runtime helpers. Write barriers populate a remembered set so minor GC can avoid retracing the old-gen. Two-bit aging (`HAS_SURVIVED` / `TENURED`) promotes nursery survivors after 2 minor cycles; the C4b evacuation policy moves non-pinned tenured objects into old-gen with full reference rewriting only when generated write barriers are active and nursery/RSS pressure plus measured movable candidates justify the work. Idle nursery blocks observed empty for 2 GC cycles are `dealloc`'d back to the OS (C4b-δ, v0.5.235), and the next-trigger calc is hard-capped at the initial threshold (64 MB) so >90%-freed step-doubling can't blow up peak occupancy (C4b-δ-tune, v0.5.236). Triggers on arena block allocation (1 MB blocks since v0.5.196), malloc count threshold, or explicit `gc()` call. 8-byte GcHeader per allocation. **Escape hatches**: `PERRY_GEN_GC=0`/`off`/`false` reverts to full mark-sweep (bisection only). `PERRY_GEN_GC_EVACUATE=0`/`off`/`false` disables policy evacuation; `=1`/`on`/`true` is accepted as auto-policy allowed, not unconditional evacuation. `PERRY_GC_FORCE_EVACUATE=1` stress-copies every marked non-pinned nursery object only when generated write barriers are active and policy evacuation is allowed. `PERRY_GC_VERIFY_EVACUATION=1` panics if any mutable live slot still points at a forwarded nursery object after an evacuation/rewrite cycle. `PERRY_WRITE_BARRIERS=0`/`off`/`false` disables codegen-emitted write barriers at compile time and runtime exact helper barriers at runtime for benchmark/debug bisection; unset, `=1`/`on`/`true` keep barriers enabled. `PERRY_GC_DIAG=1` prints per-cycle diagnostics, including evacuation-policy decisions for considered cycles and `barriers_inactive` skips. diff --git a/Cargo.lock b/Cargo.lock index a4b7523861..09e3d15f77 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5338,7 +5338,7 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "perry" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "anyhow", "base64", @@ -5395,14 +5395,14 @@ dependencies = [ [[package]] name = "perry-api-manifest" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "serde", ] [[package]] name = "perry-audio-miniaudio" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "cc", "libc", @@ -5410,7 +5410,7 @@ dependencies = [ [[package]] name = "perry-codegen" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "anyhow", "log", @@ -5425,7 +5425,7 @@ dependencies = [ [[package]] name = "perry-codegen-arkts" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "anyhow", "perry-hir", @@ -5434,7 +5434,7 @@ dependencies = [ [[package]] name = "perry-codegen-glance" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "anyhow", "perry-hir", @@ -5442,7 +5442,7 @@ dependencies = [ [[package]] name = "perry-codegen-js" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "anyhow", "perry-dispatch", @@ -5452,7 +5452,7 @@ dependencies = [ [[package]] name = "perry-codegen-swiftui" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "anyhow", "perry-hir", @@ -5461,7 +5461,7 @@ dependencies = [ [[package]] name = "perry-codegen-wasm" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "anyhow", "base64", @@ -5474,7 +5474,7 @@ dependencies = [ [[package]] name = "perry-codegen-wear-tiles" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "anyhow", "perry-hir", @@ -5482,7 +5482,7 @@ dependencies = [ [[package]] name = "perry-container-compose" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "anyhow", "async-trait", @@ -5511,14 +5511,14 @@ dependencies = [ [[package]] name = "perry-container-e2e" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "anyhow", ] [[package]] name = "perry-diagnostics" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "serde", "serde_json", @@ -5526,7 +5526,7 @@ dependencies = [ [[package]] name = "perry-dispatch" -version = "0.5.1222" +version = "0.5.1223" [[package]] name = "perry-doc-fixture-my-bindings" @@ -5537,7 +5537,7 @@ dependencies = [ [[package]] name = "perry-doc-tests" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "anyhow", "clap", @@ -5552,7 +5552,7 @@ dependencies = [ [[package]] name = "perry-ext-ads" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "block2", "objc2", @@ -5562,7 +5562,7 @@ dependencies = [ [[package]] name = "perry-ext-argon2" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "argon2", "perry-ffi", @@ -5570,7 +5570,7 @@ dependencies = [ [[package]] name = "perry-ext-axios" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "perry-ffi", "reqwest", @@ -5579,7 +5579,7 @@ dependencies = [ [[package]] name = "perry-ext-bcrypt" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "bcrypt", "perry-ffi", @@ -5587,7 +5587,7 @@ dependencies = [ [[package]] name = "perry-ext-better-sqlite3" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "perry-ffi", "rusqlite", @@ -5595,7 +5595,7 @@ dependencies = [ [[package]] name = "perry-ext-cheerio" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "perry-ffi", "scraper", @@ -5603,7 +5603,7 @@ dependencies = [ [[package]] name = "perry-ext-commander" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "perry-ffi", "perry-runtime", @@ -5611,7 +5611,7 @@ dependencies = [ [[package]] name = "perry-ext-cron" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "chrono", "cron", @@ -5621,7 +5621,7 @@ dependencies = [ [[package]] name = "perry-ext-dayjs" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "chrono", "perry-ffi", @@ -5629,7 +5629,7 @@ dependencies = [ [[package]] name = "perry-ext-decimal" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "perry-ffi", "rust_decimal", @@ -5637,7 +5637,7 @@ dependencies = [ [[package]] name = "perry-ext-dotenv" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "perry-ffi", "serde_json", @@ -5645,7 +5645,7 @@ dependencies = [ [[package]] name = "perry-ext-ethers" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "perry-ffi", "rand 0.8.6", @@ -5653,7 +5653,7 @@ dependencies = [ [[package]] name = "perry-ext-events" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "perry-ffi", "perry-runtime", @@ -5661,14 +5661,14 @@ dependencies = [ [[package]] name = "perry-ext-exponential-backoff" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "perry-ffi", ] [[package]] name = "perry-ext-fastify" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "bytes", "http-body-util", @@ -5686,7 +5686,7 @@ dependencies = [ [[package]] name = "perry-ext-fetch" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "bytes", "lazy_static", @@ -5699,7 +5699,7 @@ dependencies = [ [[package]] name = "perry-ext-http" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "bytes", "lazy_static", @@ -5713,7 +5713,7 @@ dependencies = [ [[package]] name = "perry-ext-http-server" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "bytes", "h2", @@ -5736,7 +5736,7 @@ dependencies = [ [[package]] name = "perry-ext-ioredis" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "lazy_static", "perry-ffi", @@ -5746,7 +5746,7 @@ dependencies = [ [[package]] name = "perry-ext-jsonwebtoken" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "base64", "jsonwebtoken", @@ -5757,7 +5757,7 @@ dependencies = [ [[package]] name = "perry-ext-lru-cache" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "lru", "perry-ffi", @@ -5765,7 +5765,7 @@ dependencies = [ [[package]] name = "perry-ext-moment" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "chrono", "perry-ffi", @@ -5773,7 +5773,7 @@ dependencies = [ [[package]] name = "perry-ext-mongodb" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "bson", "futures-util", @@ -5785,7 +5785,7 @@ dependencies = [ [[package]] name = "perry-ext-mysql2" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "chrono", "perry-ffi", @@ -5795,7 +5795,7 @@ dependencies = [ [[package]] name = "perry-ext-nanoid" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "nanoid", "perry-ffi", @@ -5804,7 +5804,7 @@ dependencies = [ [[package]] name = "perry-ext-net" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "bytes", "perry-ffi", @@ -5817,7 +5817,7 @@ dependencies = [ [[package]] name = "perry-ext-nodemailer" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "lettre", "perry-ffi", @@ -5827,7 +5827,7 @@ dependencies = [ [[package]] name = "perry-ext-pdf" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "perry-ffi", "printpdf", @@ -5835,7 +5835,7 @@ dependencies = [ [[package]] name = "perry-ext-pg" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "perry-ffi", "sqlx", @@ -5844,7 +5844,7 @@ dependencies = [ [[package]] name = "perry-ext-ratelimit" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "governor", "perry-ffi", @@ -5852,7 +5852,7 @@ dependencies = [ [[package]] name = "perry-ext-sharp" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "fast_image_resize", "image", @@ -5862,14 +5862,14 @@ dependencies = [ [[package]] name = "perry-ext-slugify" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "perry-ffi", ] [[package]] name = "perry-ext-streams" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "lazy_static", "perry-ffi", @@ -5878,7 +5878,7 @@ dependencies = [ [[package]] name = "perry-ext-uuid" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "perry-ffi", "uuid", @@ -5886,7 +5886,7 @@ dependencies = [ [[package]] name = "perry-ext-validator" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "perry-ffi", "regex", @@ -5896,7 +5896,7 @@ dependencies = [ [[package]] name = "perry-ext-ws" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "futures-util", "lazy_static", @@ -5908,7 +5908,7 @@ dependencies = [ [[package]] name = "perry-ext-zlib" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "brotli", "flate2", @@ -5917,7 +5917,7 @@ dependencies = [ [[package]] name = "perry-ffi" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "dashmap", "once_cell", @@ -5926,7 +5926,7 @@ dependencies = [ [[package]] name = "perry-hir" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "anyhow", "perry-api-manifest", @@ -5944,7 +5944,7 @@ dependencies = [ [[package]] name = "perry-parser" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "anyhow", "perry-diagnostics", @@ -5956,7 +5956,7 @@ dependencies = [ [[package]] name = "perry-runtime" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "anyhow", "base64", @@ -5989,14 +5989,14 @@ dependencies = [ [[package]] name = "perry-runtime-static" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "perry-runtime", ] [[package]] name = "perry-stdlib" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "aes 0.8.4", "aes-gcm", @@ -6089,14 +6089,14 @@ dependencies = [ [[package]] name = "perry-stdlib-static" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "perry-stdlib", ] [[package]] name = "perry-transform" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "anyhow", "perry-hir", @@ -6106,7 +6106,7 @@ dependencies = [ [[package]] name = "perry-types" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "anyhow", "thiserror 1.0.69", @@ -6114,14 +6114,14 @@ dependencies = [ [[package]] name = "perry-ui" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "perry-ui-model", ] [[package]] name = "perry-ui-android" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "base64", "itoa", @@ -6138,7 +6138,7 @@ dependencies = [ [[package]] name = "perry-ui-geisterhand" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "rand 0.8.6", "serde", @@ -6148,7 +6148,7 @@ dependencies = [ [[package]] name = "perry-ui-gtk4" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "base64", "cairo-rs 0.22.0", @@ -6171,7 +6171,7 @@ dependencies = [ [[package]] name = "perry-ui-ios" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "base64", "block2", @@ -6187,7 +6187,7 @@ dependencies = [ [[package]] name = "perry-ui-macos" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "base64", "block2", @@ -6202,7 +6202,7 @@ dependencies = [ [[package]] name = "perry-ui-model" -version = "0.5.1222" +version = "0.5.1223" [[package]] name = "perry-ui-test" @@ -6210,11 +6210,11 @@ version = "0.1.0" [[package]] name = "perry-ui-testkit" -version = "0.5.1222" +version = "0.5.1223" [[package]] name = "perry-ui-tvos" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "base64", "block2", @@ -6230,7 +6230,7 @@ dependencies = [ [[package]] name = "perry-ui-visionos" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "base64", "block2", @@ -6246,7 +6246,7 @@ dependencies = [ [[package]] name = "perry-ui-watchos" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "block2", "libc", @@ -6259,7 +6259,7 @@ dependencies = [ [[package]] name = "perry-ui-windows" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "base64", "libc", @@ -6276,14 +6276,14 @@ dependencies = [ [[package]] name = "perry-ui-windows-winui" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "perry-ui-windows", ] [[package]] name = "perry-updater" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "base64", "ed25519-dalek", @@ -6297,7 +6297,7 @@ dependencies = [ [[package]] name = "perry-wasm-host" -version = "0.5.1222" +version = "0.5.1223" dependencies = [ "wasmi", ] diff --git a/Cargo.toml b/Cargo.toml index 19b00f492b..37e9e6b77a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -301,7 +301,7 @@ strip = false codegen-units = 16 [workspace.package] -version = "0.5.1222" +version = "0.5.1223" edition = "2021" license = "MIT" repository = "https://github.com/PerryTS/perry" diff --git a/docs/src/language/limitations.md b/docs/src/language/limitations.md index 8e4ae2b619..adfd72216d 100644 --- a/docs/src/language/limitations.md +++ b/docs/src/language/limitations.md @@ -165,20 +165,30 @@ but user-written modules should use static `import` declarations. > dynamic `require()`, etc.), but plain JavaScript projects compile and run in > most cases. -## Limited Prototype Manipulation +## Prototype Manipulation -Perry compiles classes to fixed structures. Dynamic prototype modification is not supported: +Dynamic prototype manipulation is supported for the common patterns: - -```text -// Not supported -MyClass.prototype.newMethod = function() {}; -Object.setPrototypeOf(obj, proto); +```ts +// Supported +MyClass.prototype.newMethod = function () {}; // prototype method assignment +Object.setPrototypeOf(obj, proto); // incl. chains of any length +Object.setPrototypeOf(Derived, Base); // transpiled __extends statics link +Object.getPrototypeOf(obj); // inspection ``` -`Object.getPrototypeOf(...)` and `Reflect.getPrototypeOf(...)` are supported -for class/prototype inspection patterns, but `Object.setPrototypeOf(...)` / -`Reflect.setPrototypeOf(...)` do not mutate Perry's fixed class layout. +Prototype-method assignment routes through a dedicated registry +(`CLASS_PROTOTYPE_METHODS`) and `Object.setPrototypeOf` performs a real, +cycle-checked prototype mutation (a genuine cycle still throws `TypeError`). + +Remaining known gaps: + +- the assignment form `obj.__proto__ = x` on the dynamic write path stores a + literal `"__proto__"` property instead of setting the prototype (use + `Object.setPrototypeOf`); +- an object-literal `{ __proto__: [] }` sets the prototype without throwing, + but the result is not yet visible to `instanceof` (`… instanceof Array` + reports `false`). ## Weak References Retain Their Targets diff --git a/docs/src/packages/porting.md b/docs/src/packages/porting.md index 4e41e60864..28a9fca703 100644 --- a/docs/src/packages/porting.md +++ b/docs/src/packages/porting.md @@ -11,7 +11,7 @@ Perry compiles a practical subset of TypeScript. Most pure TS/JS packages can be | Package uses Node native addons (`.node` files, `binding.gyp`, `prebuilds/`, `node-gyp`) | **Don't put it in `compilePackages`.** Find a pure JS/TS alternative, or replace the native boundary with a Perry native binding (`perry.nativeLibrary`). | | Package is pure TS/JS with only light use of dynamic features | **Good candidate.** Add to `compilePackages`, patch whatever trips the compiler. | | Package's core API is built on `Proxy` (ORMs, validation DSLs, reactive stores) | **Probably not portable.** The surface Perry-users touch is the Proxy. | -| Package is pure TS/JS but uses lookbehind regex, `Symbol`, `WeakMap`, etc. | **Patchable.** See [Common gaps](#common-gaps) below. | +| Package is pure TS/JS but uses `Symbol`, `WeakMap`, `console.dir`, etc. | **Patchable.** See [Common gaps](#common-gaps) below. | ## Native addon packages @@ -96,16 +96,11 @@ Perry's [full limitations list](../language/limitations.md) is the canonical ref ### Lookbehind regex -Perry uses Rust's `regex` crate, which doesn't support lookbehind (`(?<=…)` / `(?/. Check package.json for native addons (binding.gyp, gypfile, prebuilds/ — stop if present). 2. Scan for unsupported constructs: eval, new Function, dynamic require, - Symbol, Proxy, WeakMap, WeakRef, Reflect, decorators, lookbehind - regex (?<= / ?