Skip to content
CAI
Software that uses CAICheck a score

PerryTS/perry

54.2

Weak · 30 September 2026

2044.6k

lines of production code

Rust

with TypeScript, Python

1

measurement over time

CAI band scale
CAI lens gauges

What this system is

This system is a JavaScript/TypeScript runtime and compiler toolchain, likely named Perry, focused on high-performance execution and bundling. Recent development has centered on optimizing the runtime's garbage collection, object handling, and array operations, while simultaneously refining the code generator to prune unused exports and improve static analysis. The platform also supports cross-compilation targets including WASM and ArkTS, and provides native UI capabilities for Windows via WinUI. The system is currently undergoing significant maintenance to address a large regression in security findings and to stabilize core module resolution and CommonJS compatibility.

Narrated so far: 2026-09-14 – 2026-09-30; 13 days pending; history before 2026-09-14 not narrated yet.

How it got here

Week 38 of 2026 (14 Sep – 20 Sep) — not summarised yet

  • Added regexp-construction benchmark suite — The \benchmarks/regexp-construction\ directory now includes a comprehensive benchmarking harness to measure and compare the performance of repeated regular expression construction. This suite provides Python scripts (\prepare.py\, \measure.py\, \compare.py\) and configuration files (\app-samples.json\, \controls-samples.json\) to run performance tests on various regex operations (such as \test-ascii\, \test-emoji\, \stripAnsi\, and \regex\_replace\) against a pinned Node.js oracle, allowing developers to track regressions or improvements in regex compilation and execution speed. (benchmarks/regexp-construction)
  • Fixes re-entrant host access in the WASM runtime — The WASM host runtime now correctly handles re-entrant calls from JavaScript imports (such as Emscripten's \invoke\\\ or \dynCall\ trampolines) by routing nested store access through the active import's \Caller\ instead of attempting to reborrow the shared thread-local store. This prevents runtime errors when a JavaScript import callback triggers further WebAssembly execution, ensuring that operations like global access, memory management, and function calls remain stable during nested invocations. The change also adds tests to verify that import callbacks can successfully call other exports or table functions without crashing. (crates/perry-wasm-host)
  • Added test cases for CJS getter re-export bindings — Added test files to verify the handling of CommonJS getter re-exports, specifically covering live binding preservation, Babel markers (\_\_esModule), and dynamic namespace updates. _(test-files/cjs\_getter\reexport)
  • Persist desktop window frame state across sessions — Windows WinUI applications now automatically restore the previous position, size, and maximized/fullscreen state of named desktop windows when they are reopened. This is achieved by introducing a frame persistence mechanism that saves window state upon closure and reinstates it on launch, ensuring a consistent user experience across application restarts. _(crates/perry-ui-windows-winui, third\party/windows-winui/windows-reactor)
  • Native property Get benchmark harness and evidence — Added a new benchmark suite in \benchmarks/native\_property\_get\ to measure the performance of the native-side property Get optimization. The directory includes a README with build and measurement instructions, a detailed REPORT.md documenting instruction counts and correctness validation, and an \evidence/\ folder containing baseline and candidate build artifacts, performance metrics, GC stress test results, and fault injection logs. _(benchmarks/native\_property\get)
  • Added regression tests for purity inference and forwarding barrel pruning — Added a new test suite in \crates/perry/tests/source\_graph\_export\_regressions/issue\_10180/purity.rs\ that verifies the compiler's purity inference and forwarding barrel pruning logic. The tests ensure that pure and mixed forwarding barrels correctly prune unused siblings, preserve lexical paths during purity inference, handle ESM ordering for effectful siblings, respect explicit contracts, and properly defer initialization for dynamic targets. _(crates/perry/tests/source\_graph\_export\_regressions/issue\10180)
  • Catch-frame benchmark harness and evidence added — This change adds the \benchmarks/catch\_frames\ directory, which includes a comprehensive README documenting the design and performance impact of grouping catch-frame savepoints and inlining capture providers, along with a Python script (\count\_frames.py\) for measuring try-frame pushes via perf uprobes. It also introduces a large set of baseline and candidate evidence files (instruction counts, frame counts, GC comparisons, fault-injection results, and constructor-identity debugging logs) to validate the optimization's correctness and performance gains. _(benchmarks/catch\frames)
  • Add support for responsive max-width on widgets — Users can now set a maximum width for widgets, enabling responsive layouts that constrain size on larger screens while remaining flexible on smaller ones. This change introduces the \widgetSetMaxWidth\ method in the UI dispatch table, maps it to the \perry\_ui\_widget\_set\_max\_width\ runtime function for JavaScript/Web (which applies CSS constraints like \max-width\, \width: 100%\, and auto margins), and adds corresponding code generation for ArkTS and JS. Note that on HarmonyOS, this feature currently degrades to a no-op. (crates/perry-codegen-arkts, crates/perry-codegen-js, crates/perry-dispatch)
  • Desktop windows now persist their position and size across launches — On macOS, Windows, and GTK4, desktop windows now remember their last position, size, and state (normal, maximized, or fullscreen) and restore them on the next launch. This replaces the previous behavior where windows would re-center or reset to default dimensions every time the app started. Mobile and tablet platforms (iOS, tvOS, visionOS, watchOS) continue to ignore this feature as it only applies to repositionable desktop windows. ((repo-wide))
  • New max-width control and refined width behavior for UI widgets — Users can now explicitly set a maximum width for widgets via the new \widgetSetMaxWidth\ method, which applies a responsive centered layout using flexbox and border-box sizing. Additionally, the existing \widgetSetWidth\ behavior has been updated to enforce a fixed width by synchronizing minimum and maximum width constraints and disabling flex shrinking, ensuring the widget maintains its specified dimensions without growing or shrinking. (crates/perry-codegen-wasm)
  • Added test coverage for CommonJS getter re-exports, RegExp caching, array descriptor forwarding, and event-loop timing — This change adds a suite of new test fixtures to verify specific runtime behaviors. It includes tests for preserving live getter re-export bindings in CommonJS modules, caching compiled RegExp programs to speed up test/replace operations, and ensuring array descriptor owner identity is preserved across growth aliases. Additionally, it covers generic function overhead, JSON record loop cloning with IEEE edge cases, native property Get observability, and correct event-loop timing for beforeExit and exit jobs. (test-files)
  • Added regression tests for CommonJS getter re-exports, unused re-export pruning, and constructor arity forwarding — Added test coverage in the source graph export regression suite to verify that CommonJS accessor re-exports remain live value bindings through barrels and dynamic namespaces, that unused re-export subgraphs are correctly pruned while preserving side-effect order and transitive sibling pruning, and that constructor arity is correctly forwarded across modules for classes with runtime parents and various heritage forms. _(crates/perry/tests/source\_graph\_export\regressions)
  • Added tests for window frame autosave and widget max-width code generation — The test suite in crates/perry-codegen/tests was updated to verify new code-generation behaviors. A new test ensures that the \frameAutosaveName\ window option correctly emits the \perry\_ui\_app\_set\_frame\_autosave\_name\ FFI call and that this call is ordered after window state setup but before the application run. Additionally, a new test file validates that the \widgetSetMaxWidth\ native method correctly lowers to the \perry\_ui\_widget\_set\_max\_width\ ABI call. Several existing tests were also updated to include the new \constructor\_param\_counts\ field in their compile options. (crates/perry-codegen/tests)
  • Reduced instruction overhead for local variable copies and global stores — The compiler now removes unnecessary local variable aliases and dead inert assignments before code generation, significantly lowering the static instruction count for simple functions. This optimization, implemented in the new \local\_copies\ transform pass, rewrites transitive aliases to point directly to their source and eliminates unused declarations, resulting in smaller generated code. Additionally, stores to known global constants are optimized to use fewer instructions, while complex scenarios like captures, control flow, and async functions remain unaffected to preserve correctness. (benchmarks/generic-overhead, crates/perry-transform)
  • Compiler prunes unused re-exports to reduce bundle size — The compiler now analyzes the module graph to identify and remove re-exports that are not imported by the final application, provided the re-exported modules are side-effect-free. This optimization is enabled by default but can be disabled via the PERRY\_NO\_REEXPORT\_PRUNE environment variable. The build output now reports the number of modules pruned as unreferenced side-effect-free re-exports. Additionally, CommonJS wrapping now correctly handles accessor-based re-exports (e.g., Object.defineProperty) by exposing them as live getters rather than static snapshots, and the build cache has been updated to detect changes in configuration inputs that might affect pruning decisions. (crates/perry/src)
  • Faster compilation of large static record literals via static descriptors — The compiler now detects large constant object literals and lowers them to a static shape descriptor and a shared runtime materializer instead of generating massive LLVM bodies. This change significantly reduces compilation time and memory usage for code containing large JSON-like structures (e.g., the 3,200-record benchmark drops from \~95 seconds to \~0.6 seconds), while maintaining identical runtime behavior and object layout for property reads. _(benchmarks/large\_json\literals, crates/perry-hir)
  • Added tests for class prototype symbol properties, proxied Headers, and record literal compilation — Added integration tests in \crates/perry/tests\ to verify that symbol-keyed properties written to declared class prototypes are visible on instances and subclass instances, that the \Headers\ constructor correctly accepts and iterates Proxy-wrapped record initializers (including handling enumerable descriptors and non-enumerable keys), and that mid-size record literals compile using shape-based optimization rather than falling back to \JsonParse\. (crates/perry/tests)
  • Fix Headers constructor to correctly handle Proxy objects and improve error diagnostics — The Headers constructor now correctly accepts a Proxy object as an initialization record, reading its keys and values through the Proxy's traps (ownKeys, get, and property descriptors) rather than failing with an "init is not iterable" error. This ensures that enumerable Proxy record descriptors are honored according to the Web IDL spec. Additionally, when a rejected init is passed, the resulting type error message now explicitly names the input type (e.g., "Proxy", "string", "array") instead of providing a generic error, aiding in debugging. (crates/perry-stdlib)
  • Runtime performance optimizations and memory policy support — The runtime now supports an opt-in small-process memory policy and introduces several performance improvements: the young-generation occupancy check is cached to avoid O(blocks) walks, promoted page runs are expanded lazily only when reshaped, sweep accounting is batched per-page, and array named properties are stored inline rather than in a side table. Additionally, the build system now compiles a C memory profile helper on Linux 64-bit when the mimalloc feature is enabled, and a new example demonstrates instruction-count probing for exception handling. (crates/perry-runtime)
  • Workspace version bump to 0.5.1571 and dependency cleanup — The workspace version has been updated from 0.5.1564 to 0.5.1571. This release includes the removal of unused Rust dependency declarations across multiple crates (such as \thiserror\, \anyhow\, \itoa\, \ryu\, \clap\, and \tokio-cron-scheduler\) and the addition of \dirs\ and \tempfile\ to the \perry-ui\ crate for desktop platforms. Additionally, the \perry-runtime\ feature \prebuilt-core\ now includes the \global-math\ profile to support conservative console analysis. ((dependencies))
  • Build scripts now compile a feature-trimmed core runtime and include it in Linux builds — A new \scripts/build\_core\_runtime.sh\ script builds a feature-trimmed version of the core runtime library (using the \perry-runtime/prebuilt-core\ feature) into a separate target directory. The existing Linux build scripts (\build\_linux\_glibc\_2\_31.sh\ and \build\_linux\_musl.sh\) have been updated to invoke this new script, ensuring that the core runtime artifact is built alongside the standard runtime during these Linux build processes. (scripts)
  • Fixes to CJS live exports, constructor arity resolution, and event-loop beforeExit handling — This update resolves several runtime and compilation issues. CJS wrapper exports now use live value getters instead of static snapshots, preventing freezes when exports are assigned after initialization. Constructor parameter counts are resolved once across the source graph to ensure consistent ABIs for inherited classes, fixing mismatches in synthesized forwarding constructors. The event loop's beforeExit handling now correctly resumes work queued by listeners before finalizing, and literal record construction is optimized to use data-driven descriptors, reducing LLVM body size. (crates/perry-codegen/src)
  • Fix Symbol.iterator resolution on Array proxies — Resolved an issue where accessing Symbol.iterator on array proxies returned incorrect values, causing iteration checks to fail. The fix now retrieves the iterator directly from the Array prototype, ensuring that proxy-based arrays correctly expose their iterator method for standard iteration protocols. (crates/perry-runtime/src/symbol)
  • Fix CommonJS require cycles by exposing current exports — The module registry now publishes the CommonJS module record before executing the wrapper body, allowing the exports adapter to unwrap current \.exports\ on each read. This ensures that recursive loads (require cycles) can observe the correct, up-to-date exports state, preventing issues where modules fail to see partial exports during circular dependencies. _(crates/perry-runtime/src/module\require)
  • Fixes for Bun platform resolution, CommonJS cycle handling, and embedded asset performance — When compiling for the Bun platform (--platform bun), the resolver now prioritizes the 'bun' export condition over 'node', ensuring packages with platform-specific entries resolve to the correct backend. CommonJS circular dependencies are handled more robustly: the CJS wrapper now publishes the current module.exports value (rather than an initial empty object) to support cases where esbuild replaces exports before peer requirements, and warnings for non-existent properties are suppressed if the property already exists on the replacement object. Additionally, zstd-compressed embedded assets are now decoded lazily on first read instead of at registration time, improving startup performance. Finally, imported variables in the compiler are keyed by their local name to prevent identifier collisions during minification. (crates/perry/src)
  • Optimized object key-array sharing for descriptor-bearing receivers — The runtime now allows objects that receive property definitions via \Object.defineProperty\ to share internal key arrays and shape transitions, rather than each creating a private copy. This change aligns the behavior of \Object.defineProperty\ with ordinary property assignment (\\[\[Set\]\]\), enabling repeated receivers (such as instances created by schema libraries like Zod) to reuse cached structural edges. The implementation includes safety checks to ensure that shared transitions only apply when the target object's inline slot capacity fits the receiver, preventing memory safety issues during garbage collection. _(crates/perry-runtime/src/object/object\ops)
  • Refinements to codegen guards, compression testing, and thread-local tracking — This update refines the code generation pipeline by enforcing stricter checks on the class-field inline guard's header comparisons and adjusting the truthiness logic for boolean parameters based on tag identity. It also updates the embedded compression test to verify the use of lazy zstd decoding for large assets and adjusts the thread-local cold allowlist to account for new declarations in the regex module. (scripts)
  • Object store fast paths now use per-key descriptor tracking — The runtime's object store fast paths have been optimized to check for own-property descriptors on a per-key basis rather than rejecting the entire receiver when any descriptor is present. This change introduces per-key summary tracking (including a fast-path hash for single-descriptor objects) and per-key prototype interception checks, allowing objects with descriptors to continue using fast paths for keys that are not intercepted. Additionally, data-descriptor installs now share shape generations across receivers that perform identical installs, reducing shape fragmentation and improving cache reuse. (crates/perry-runtime/src/object)
  • Runtime performance optimizations in garbage collection and module initialization — The runtime now skips unnecessary write barriers for scalar (non-pointer) child values during store operations, reducing overhead in hot paths. Additionally, the garbage collector's newborn barrier logic has been refined to avoid work for pointer-free births and closure allocations when no incremental cycle is active. Module initialization is also improved by ensuring that importing modules' shape IDs are correctly pointed to the defining module's typed ID, regardless of initialization order, which prevents performance penalties from missed field-store guards. (crates/perry-runtime/src/gc)
  • Optimized number-to-string conversion to use stack buffers — The runtime's string concatenation and \Number.toString\ paths now format numbers directly into stack buffers instead of allocating heap strings. This change replaces intermediate
    \format!\ calls and heap-allocated \String\ objects with efficient, stack-based routines (\fast\_itoa\_i64\ and \format\_ryu\_js\_into\), reducing memory allocation overhead while maintaining identical ECMAScript-compliant output for all numeric values. (crates/perry-runtime/src/string)
  • Test coverage for regex factory catch stack integration — Added tests for the regex subsystem's integration with the exception handling system, specifically verifying the behavior of the \CatchStack\ used to manage active factory sites within the \SITE\_TEST\_HEADERS\ and \ACTIVE\_FACTORY\_SITES\ thread-local storage. (crates/perry-runtime/src/regex)
  • Optimized exception savepoint capture by skipping unused subsystems — The runtime now skips capturing savepoints for subsystems that have never been used on a thread, avoiding unnecessary thread-local reads during exception handling. This is achieved by tracking which subsystems have held non-idle state via a process-wide atomic flag; if a subsystem has never been touched, its savepoint is restored to a known idle constant instead of reading the current thread-local depth. This optimization reduces overhead in programs that do not throw exceptions in all subsystems, while ensuring correctness by verifying that idle constants match fresh-thread captures. (crates/perry-runtime/src/exception)
  • Improved Array performance and Proxy compatibility — The runtime now optimizes array operations by bypassing receiver resolution for plain arrays during push operations and skipping unnecessary layout notes when storing scalar values into pointer-free arrays. Additionally, Array.from and array spread operations now correctly handle Proxy objects, ensuring that @@iterator traps and indexed property access are properly observed rather than skipped. (crates/perry-runtime/src/array)
  • Optimized typed entry dispatch and array literal generation — The code generator now uses a two-tier dispatch for typed public entries (functions, closures, and methods), allowing plain doubles to pass through a fast path without runtime guard calls, while int32 boxes are converted only when necessary. This replaces previous single-tier logic that forced every call to pay for the rare int32 case. Additionally, array literals composed entirely of plain doubles are now generated with a pointer-free raw-f64 layout directly, skipping the runtime marking walk and per-slot notes. Imported class shape slots are also registered early to ensure correct typed ShapeId resolution across module initialization boundaries. (crates/perry-codegen/src)
  • Runtime performance and correctness improvements — This update introduces several performance optimizations and bug fixes to the runtime. Embedded zstd assets are now decoded lazily on first read rather than eagerly at startup, reducing initialization time and memory usage for applications that do not access all assets. CommonJS module exports are now exposed during require cycles, ensuring that partial exports are visible to recursive loads. Proxy array materialization and dynamic Request headers are fixed to handle edge cases correctly. Additionally, fast paths for descriptor-bearing receivers and inline typed-array length reads improve execution speed, while exception savepoints are optimized to skip unused subsystems. (crates/perry-runtime/src)
  • Fixes incorrect TypedArray writes for non-numeric values — The runtime now correctly rejects NaN-boxed values (such as booleans, null, undefined, strings, and int32s) in the fast TypedArray index setter. Previously, these values were written directly into the buffer, corrupting data (e.g., writing \true\ into a Float64Array). The change ensures these values fall back to the slow setter, which applies the necessary ToNumber conversion, while still allowing valid floating-point numbers (including negative values and NaN) to use the fast path. (crates/perry-runtime/src/typedarray)
  • Updated codegen regression tests for inline typed-entry guards and typed array access — The test suite in \crates/perry-codegen/tests\ has been updated to reflect recent changes in the code generator's IR output. Assertions in \native\_proof\_regressions.rs\ now verify that typed-entry guards and unboxes are inlined using specific IR patterns (such as \icmp\ and \sitofp\ operations) rather than relying on calls to runtime helpers like \js\typed\\*\_arg\_guard\. Additionally, \typed\_array\_rmw\_8692.rs\ has been adjusted to accept a new code path for declared typed-array reads with unproven indexes, which now utilizes an inline guarded arm (\js\_packed\_arraylike\_index\_get\) alongside the existing dynamic fallback. (crates/perry-codegen/tests)
  • Added tests for cross-module class shape identity, CJS require cycles, and runtime performance optimizations — This change adds a suite of new test files to verify specific runtime behaviors and performance optimizations. It includes tests for cross-module class shape identity, ensuring that instances of pointer-bearing classes maintain consistent layout and identity across module boundaries, including in import cycles and lazy-loaded modules. It also adds tests for CommonJS require cycles to verify that exports are correctly exposed during circular dependencies. Additionally, the diff introduces tests for various runtime optimizations: array push receiver resolution, array element store with runtime indices, number formatting into stack buffers, numeric array literal layout, runtime scalar store barriers, try-savepoint subsystems, typed array dynamic index access, and typed array length inline reads. (test-files)
  • Added regression tests for proxy, import, and runtime behaviors — Added comprehensive test coverage in \crates/perry/tests\ for several previously failing or edge-case scenarios: descriptor-bearing receivers and prototype vetting (\descriptor\_store\_fast\_paths.rs\), Proxy handling in \Array.from\ and \Headers\ (\issue\_10270\, \issue\_10274\), dynamic import cycle initialization (\issue\_10278\), platform-specific condition resolution (\issue\_10281\), import alias collisions (\issue\_10286\), indirect \bun:sqlite\ method dispatch (\issue\_10290\), \dlopen\ of embedded assets (\issue\_10302\), and \global\ alias member reads (\issue\_10303\). These tests pin expected outputs against Node/Bun behavior and ensure the compiler and runtime handle these specific patterns correctly. (crates/perry/tests)
  • Fix loading of embedded shared libraries via virtual paths — The runtime now correctly loads shared libraries embedded in the binary (such as OpenTUI's renderer) that are referenced via virtual \$perryfs/...\ paths. Previously, the dynamic loader failed because it could not resolve these virtual paths. The fix materializes the embedded bytes into a temporary file with secure permissions (0700 on Unix) and caches the result to avoid repeated writes. File names are now unique per virtual path using a hash digest to prevent collisions between libraries with identical basenames in different directories. _(crates/perry-runtime/src/bun\ffi)
  • Optimized array destructuring and fixed global property access — Array destructuring patterns containing only holes, plain identifiers, or a rest identifier no longer wrap the binding body in a try/catch block, reducing runtime overhead by avoiding unnecessary savepoint captures while still ensuring IteratorClose runs on normal completion. Additionally, accessing properties on \global\ (e.g., \global.window\) now correctly preserves the reified receiver instead of collapsing to a static intrinsic, fixing issues where user-defined properties on \global\ were previously lost or caused errors. (crates/perry-hir)
  • Fixes for SQLite method dispatch and Headers proxy handling — This update resolves two issues in the standard library. First, it fixes \bun:sqlite\ database methods (\query\, \run\, \transaction\) that were silently returning \undefined\ when the database object was accessed through indirections (such as fields, interface-typed parameters, or driver objects) by ensuring these methods reach the correct dispatcher. Second, it corrects how \Headers\ are materialized from iterables, ensuring that only genuine array types bypass the iterable conversion path, which prevents errors when passing proxy arrays or object-backed Array subclasses. Additionally, a new internal helper \js\_headers\_from\_value\ optimizes Request construction by reusing existing Headers handles instead of creating redundant intermediate stores. (crates/perry-stdlib)
  • Version bump to 0.5.1578 — The workspace version has been updated from 0.5.1571 to 0.5.1578, and the Cargo.lock file reflects this change across all workspace members (e.g., perry, perry-api-manifest, perry-audio-miniaudio). ((dependencies))
  • **Expose LRU subclass module and adjust node\stream visibility* — The runtime now exposes the \lru\_subclass\ module publicly, enabling support for JavaScript classes that extend \LRUCache\. Additionally, the \dispatch\ module and several helper functions within \node\_stream\ have been changed from \pub(super)\ to \pub(crate)\, broadening their visibility within the crate to support these internal implementation details. (crates/perry-runtime/src)
  • Fix subclassing LRUCache and cross-module EventEmitter initialization — The codegen now correctly handles classes that extend native bases without their own constructors. Specifically, extending \LRUCache\ (a compile-time pattern) no longer throws "Class extends value is not a constructor"; the generated code installs the cache surface on \this\ and forwards options. Additionally, cross-module subclasses of \EventEmitter\ (and similar native bases) now correctly inherit methods like \on\ because the synthesized standalone constructor explicitly initializes the native instance base, fixing "is not a function" errors when importing and instantiating such classes from other modules. (crates/perry-codegen)
  • Fixes to object builder folding, ambient declaration handling, and GC type inference — This update addresses three distinct correctness issues in the HIR lowering and analysis pipeline. First, the object builder fold optimization (builder\fold.rs) now allows a gap of up to 64 hoistable statements between an empty object literal and its subsequent property assignments, significantly improving performance for common initialization patterns by avoiding dynamic shape transitions. Second, a new ambient declaration module (ambient.rs) ensures that TypeScript \declare const/let/var\ statements do not create local bindings or exports, correctly resolving references to the global object instead, while preserving special handling for compile-time constants like \\\platform\\_\. Third, the anonymous shape field type inference (expr\_object.rs) and type widening pass (type\_widening.rs) now correctly handle variables initialized to \null\ that are later assigned objects; instead of minting an unscannable \Null\ field type that causes garbage collection errors, the system now widens the type to \Any\ when the assigned value is certainly not nullish, ensuring the GC mask accurately reflects pointer-bearing slots. (crates/perry-hir)
  • GC slot visitor borrows shape records to avoid iterator copies — The garbage collector's slot visitor now borrows the resolved shape record instead of moving the \HeapChildSlotIterator\, eliminating a per-object memory copy during GC walks. This change also updates the internal representation from \ShapeDescriptor\ to \ShapeRecordRef\ to support the borrowing approach. Additionally, a test update confirms that the regex engine's \v\ grammar now successfully compiles set operators (such as difference), whereas previously they were unsupported. (crates/perry-runtime/src/gc)
  • Regex search performance improved via thread-local scratch reuse — The regex engine now reuses a thread-local scratch buffer for searches instead of allocating new buffers for every call. This change eliminates repeated memory allocations and \memcpy\ overhead, significantly speeding up repeated regex operations. The implementation uses a \RefCell\-protected thread-local cell to store registers, frames, and undo entries, falling back to the previous owned-buffer path if the search requires more resources than the lent cell can provide. (crates/perry-runtime/src/regex)
  • Added tests for Map.groupBy JSON serialization and SuppressedError prototype chain — Added test coverage for Map.groupBy to verify that grouped arrays serialize correctly via JSON.stringify across various element types (strings, booleans, objects, mixed, numbers), and added assertions for the SuppressedError prototype chain to ensure instanceof checks and toString behavior align with the ECMAScript specification. (test-files)
  • Fix array iteration and layout correctness when prototypes are patched — The runtime now correctly handles cases where built-in iterator prototypes (such as \%ArrayIteratorPrototype%\, \%SetIteratorPrototype%\, \%MapIteratorPrototype%\, or \%StringIteratorPrototype%\) have been modified or escaped to user code. Previously, operations like spread syntax (\\[...iterable\]\) and \Array.from\ could silently bypass the custom iterator logic by copying raw backing store data, leading to incorrect results. This fix widens the safety checks to detect any non-pristine iteration state, ensuring the actual iterator protocol is invoked in these scenarios. Additionally, a new internal helper \reclassify\_array\_numeric\_layout\_from\_slots\ repairs a bug where arrays containing non-numeric data were incorrectly marked as numeric, which previously caused \JSON.stringify\ to serialize string elements as \null\. (crates/perry-runtime/src/array)
  • Performance and correctness improvements in object property handling and iteration — This change optimizes the store-plan cache by evaluating eligibility per-key rather than per-receiver, allowing objects with own descriptors (like those used by Zod) to still benefit from fast paths for unintercepted keys. It also widens the check for modified iterator prototypes to include Map, Set, and String iterators, ensuring that spread operations and array conversions correctly respect patched \.next\ methods. Additionally, the garbage collector now borrows shape records directly instead of copying them, reducing memory pressure and improving traversal efficiency, while \SuppressedError\ is added to the list of native error subclasses to fix \instanceof\ checks. (crates/perry-runtime/src/object)
  • Fixes for compiler shadowing, GC scanning, and test coverage — The compiler no longer allows unimported exports to shadow global intrinsics like \Request\, ensuring that \new Request(...)\ correctly uses the global fetch API instead of a user-defined class from a dependency module. Additionally, the garbage collector now correctly scans record fields that were initialized with \null\, preventing memory corruption in linked-list-like structures. The entry also includes new tests verifying that builder folding preserves evaluation order, that cross-module instantiation of native base classes works correctly, and that store-plan caching respects own-accessor descriptors. (crates/perry)
  • Version bump to 0.5.1584 and perex dependency update — The project version has been incremented from 0.5.1578 to 0.5.1584 across the workspace and all dependent crates. Additionally, the \perex\ dependency has been updated from version 0.1.4 to 0.1.7. ((dependencies))
  • Optimized array index access by hoisting receiver handle calculation — The code generation for packed loop index access now reuses a hoisted receiver handle instead of recalculating the array pointer mask for every element. This change moves the handle derivation outside the loop body, allowing the compiler's loop-invariant code motion to optimize the subsequent size and capacity calculations, resulting in more efficient generated code for array indexing operations. _(crates/perry-codegen/src/expr/index\get)
  • Support for adopting pre-built arrays in the codegen rooting system — The code generation system now supports adopting arrays that were constructed inline (such as rest bundles) by explicitly rooting them in the temporary root stack. This ensures that operands and arrays allocated via this inline path are correctly tracked and released together, preventing potential memory management issues during code generation. (crates/perry-codegen/src/rooting)
  • Optimized string concatenation by removing redundant type coercions — The code generator now skips unnecessary \StringCoerce\ wrappers for string concatenation parts that are already guaranteed to be strings or plain numbers. This optimization reduces runtime overhead by avoiding intermediate heap string allocations during the formatting of these specific value types, while preserving the coercion for objects to maintain correct JavaScript \toString\ behavior. (crates/perry-codegen/src)
  • Fix WinUI widget child reordering logic — The WinUI widget backend now correctly handles reordering child elements via the new \reorder\_child\ function. This change ensures that when Fluent rendering is active, children are moved within the parent's list without altering native window or layout metadata, while mirroring the safety guards (such as out-of-range checks and no-op conditions) of the Win32 backend. It also prevents invalid reordering by rejecting non-positive parent handles, addressing a potential issue where handle 0 could incorrectly map to node 0. (crates/perry-ui-windows-winui)
  • Added Bun platform marker and optimized \in\ operator cache — The code generator now declares the \js\_set\_bun\_platform\ function, enabling the \--platform bun\ marker to properly configure the runtime environment. Additionally, it introduces \js\_in\_operator\_presence\_ic\, an inline cache for the \in\ operator with constant keys, to improve performance during property lookups. _(crates/perry-codegen/src/runtime\decls)
  • Fix Response validation, optimize CJS preamble, and correct
    builder folding — This update addresses three distinct areas. First, it fixes the \Response\ constructor and \Response.json\ to share a single validation path, ensuring that a body with a null-body status (204/205/304) throws a TypeError in Node mode but is accepted in Bun mode (\--platform bun\). Second, it optimizes the CommonJS wrapper preamble by folding the module record into a single object literal, sharing a single \createRequire\ instance across all modules, and replacing a large switch statement for builtin detection with \node:module\'s \isBuiltin\ (while maintaining compatibility with both \node:\ and bare spellings), significantly reducing startup cost. Third, it fixes a bug where implicit conversions in folded builder values could observe user code out of order, ensuring that conversions like \+obj\ or template literals see the allocated object correctly. (crates/perry)
  • Array push now throws on non-extensible objects and runtime performance improves — The runtime now correctly throws a TypeError when pushing to a non-extensible array (e.g., after \Object.preventExtensions\), matching standard behavior instead of silently failing. Performance is improved by eliminating redundant pointer resolution and header checks in array push and iteration paths, and by conditionally flushing store plans only when a packed-numeric proof is actually retired. (crates/perry-runtime)
  • Fixes to bitwise operator typing, global constructor shadowing, and \in\ operator performance — This update corrects several codegen behaviors: bitwise operations (\&\, \\|\, \^\, \\<\<\, \\>\>\, \\>\>\>\) now correctly produce BigInt results when operands are not proven to be Numbers, preventing incorrect int32 truncation and missing type coercions; \new globalThis.X()\ now properly falls back to a runtime property read when a module binding shadows the global name, ensuring the correct constructor is invoked; and constant-key \in\ expressions now use a presence inline cache to significantly reduce overhead for repeated property checks. Additionally, the array literal builder was refactored to share logic with rest bundles, and the packed loop counter read is now correctly identified as non-pointer to avoid unnecessary GC root shading. (crates/perry-codegen/src/expr)
  • Fix generator suspension in nested loop headers — Resolves an issue where yields inside loop headers (conditions, updates, or initializers) were not properly suspended when nested inside other control structures like if/try/switch. This previously caused generators to yield nothing in minified code (e.g., lru-cache iterators). The fix ensures that yields in while/do-while conditions, for conditions/updates/init, and nested loop headers are correctly detected and split into resume states. (crates/perry-transform)
  • Remove 16-argument ceiling on dynamic closure calls and fix global intrinsic construction — Dynamic calls through function values (e.g., via \apply\, \call\, or spread) no longer fail or truncate arguments at 16; calls with more arguments now marshal into a stack buffer and dispatch via \js\_closure\_call\_array\, while top-level function wrappers correctly forward all declared parameters. Additionally, \new globalThis.\<name\>()\ now correctly constructs the global intrinsic even when the name is shadowed by a module class or alias, and the Bun platform initialization is seeded into module init to support platform-specific Web API behavior. _(crates/perry-codegen/src/lower\call)
  • Fix bitwise operations on BigInt-capable values to prevent incorrect int32 optimization — The codegen now correctly identifies when bitwise operators (like \&\, \\|\, \^\, \\<\<\, \\>\>\) are applied to operands that may be BigInts. Previously, these operations were always assumed to produce an int32, which could lead to incorrect optimizations if the operands were actually BigInts (since bitwise operations on BigInts return BigInts, not int32s). This change introduces a \NotBigIntFacts\ analysis to prove when bitwise results are definitely Numbers, ensuring that locals holding such results are not incorrectly treated as native i32s, which would otherwise truncate BigInt values to 0. (crates/perry-codegen/src/collectors)
  • Fix bitwise operator type inference and global constructor shadowing in HIR lowering — This update corrects two distinct issues in the HIR lowering and type analysis. First, bitwise operators (\&\, \\|\, \^\, \\<\<\, \\>\>\) now correctly infer \BigInt\ when both operands are \BigInt\, and \Any\ when operands are unknown, instead of incorrectly defaulting to \Number\ (which caused \BigInt\ results to be read as \0\ in int32 slots). Second, \new globalThis.\<name\>()\ expressions now correctly construct the global property's value even when a local binding (import, class, or function) shadows that name, preventing the code from accidentally constructing the local binding instead. (crates/perry-hir)
  • Added tests for call arity limits, BigInt bitwise typing, generator loop yields, timer ref state, array push integrity, in-operator presence, and instanceof prototype overrides — Added a suite of test files to verify specific runtime and compiler behaviors: call arity limits for functions with more than 16 arguments (\#10420), correct BigInt bitwise operator typing (\#10418), proper suspension of generators when yields appear in loop headers (\#10419), preservation of scheduled timer ref state after evicting older timers (\#10447), integrity checks for Array.prototype.push on non-extensible/sealed/frozen arrays, handling of numeric values over pointer slots in arrays, store-plan cache retirement on Array subclass pops, presence checks for the \in\ operator across various object shapes and prototypes, and correct instanceof behavior when prototype overrides are applied after hot code paths. (test-files)
  • Removes argument-count ceilings on dynamic calls and optimizes validation for numeric classes — Dynamic function calls (including closures, object-literal methods, and \apply\/\call\ targets) no longer silently drop arguments beyond a fixed limit; the codegen now generates wrappers with an arity matching the full declared parameter count, fixing issues where functions with more than 5 or 16 arguments would receive zeroed values for excess parameters. Additionally, runtime validation for classes where every field is declared as \number\ is optimized to use a nominal identity check instead of walking each field, reducing validation overhead. (crates/perry-codegen/src/codegen)

This week

  • Regression of 1,025 Security Findings — This release introduces a significant regression in the security posture, with 1,025 security findings detected. This indicates a broad increase in vulnerabilities or policy violations across the codebase that requires immediate investigation and remediation to restore the previous security baseline. ((security))

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

How this codebase got here

Score

  • CAI 28 → 54 (+26.1)
  • Rubric changed (rubric-2026.09.11 → rubric-2026.09.18) — scores are not directly comparable.

Lenses

  • Code Health 77 (new)
  • Architecture 84 (new)
  • Maturity 13 → 88 (+74.5)
  • Readiness 15 → 33 (+17.3)
  • Security 100 → 68 (-31.7)
  • Event Sourcing 100 (new)
  • Accessibility 78 (new)
  • Performance 70 (new)

Resolved (3)

  • No automated tests
  • No tests found
  • Test reliability not included

New (10497)

  • (anonymous) (cognitive 60) (crates/perry-codegen-wasm/src/wasm_runtime.js)
  • (anonymous) (cyclomatic 58) (crates/perry-codegen-wasm/src/wasm_runtime.js)
  • (anonymous)::_mapKeyToAction (cognitive 43) (crates/perry-codegen-js/src/web_runtime.js)
  • (anonymous)::_mapKeyToAction (cyclomatic 45) (crates/perry-codegen-js/src/web_runtime.js)
  • (anonymous)::_perryCodeToKey (cognitive 29) (crates/perry-codegen-js/src/web_runtime.js)
  • (anonymous)::_perryCodeToKey (cyclomatic 55) (crates/perry-codegen-js/src/web_runtime.js)
  • (anonymous)::_renderTokenizedLine (cognitive 26) (crates/perry-codegen-js/src/web_runtime.js)
  • (anonymous)::_renderTokenizedLine (cyclomatic 20) (crates/perry-codegen-js/src/web_runtime.js)
  • (anonymous)::hone_editor_render_line (cognitive 25) (crates/perry-codegen-js/src/web_runtime.js)
  • (anonymous)::hone_editor_render_line (cyclomatic 16) (crates/perry-codegen-js/src/web_runtime.js)
  • (anonymous)::hone_editor_set_viewport (cognitive 18) (crates/perry-codegen-js/src/web_runtime.js)
  • (anonymous)::perry_ui_canvas_draw_image (cognitive 20) (crates/perry-codegen-js/src/web_runtime.js)
  • (anonymous)::perry_ui_canvas_draw_image (cyclomatic 20) (crates/perry-codegen-js/src/web_runtime.js)
  • ADR not followed: 6760-merge-types-into-hir (changelog.d/6760-merge-types-into-hir.md)
  • ADR not followed: 6835-remove-stdlib-http-client (changelog.d/6835-remove-stdlib-http-client.md)
  • ADR not followed: 6941-property-key-operand-rooting (changelog.d/6941-property-key-operand-rooting.md)
  • ADR not followed: 6963-shape-keyed-typed-layout-queries (changelog.d/6963-shape-keyed-typed-layout-queries.md)
  • ADR not followed: 7039-codegen-determinism (changelog.d/7039-codegen-determinism.md)
  • ADR not followed: 7050-gc-allocation-point-trigger-outside-arena-borrow (changelog.d/7050-gc-allocation-point-trigger-outside-arena-borrow.md)
  • ADR not followed: 7164-ffi-by-index-field-count (changelog.d/7164-ffi-by-index-field-count.md)
  • …and 10477 more

Changes since last survey

  • 300 commits — 234 feature/other, 66 fixes

By area

  • crates/perry-runtime — 90 commits
  • crates/perry-codegen — 48 commits
  • crates/perry — 13 commits
  • (root) — 12 commits
  • crates/perry-stdlib — 9 commits
  • crates/perry-ext-http — 4 commits
  • crates/perry-ui-macos — 4 commits
  • test-parity/node-suite — 4 commits
  • .github/workflows — 3 commits
  • crates/perry-hir — 3 commits
  • scripts/gc_call_effects — 3 commits
  • changelog.d/11548-perex-0110-run-error.md — 2 commits
  • changelog.d/11563-auto-optimize-compile-budget.md — 2 commits
  • changelog.d/11564-ui-textfield-known-failure.md — 2 commits
  • changelog.d/11565-generated-gc-call-effects.md — 2 commits
  • changelog.d/11575-request-null-headers.md — 2 commits
  • changelog.d/11589-byte-view-element-access.md — 2 commits
  • changelog.d/11613-macos-srgb-colours.md — 2 commits
  • changelog.d/object-create-ordinary-birth.md — 2 commits
  • crates/perry-ext-net — 2 commits

Notable commits

  • fix: changelog: #11634 copying-minor fixed cost
  • fix: changelog: fix a quote in #11575's fragment
  • fix: ci(gc): gc-call-effects gate on linux/macOS/windows; shadowed-symbol demotion; test fixes
  • fix: fix(ci): run stdlib lib tests for runtime changes (#11423)
  • fix: fix(codegen): root the function across Func.prototype.x = <call> (#11635) (#11639)
  • fix: fix(codegen): root the packed-range loop's cached module-global copy (#11590)
  • fix: fix(compile): a called import of an uninstalled package is a compile error, not a link error
  • fix: fix(compile): a node:url factory enables the global-url member tables
  • fix: fix(compile): diagnose missing named exports before codegen
  • fix: fix(compile): hold TypeScript importers only to names read as values
  • fix: fix(fetch): new Request(url, { headers: null }) throws a TypeError again
  • fix: fix(fetch): read Request, Response and fetch bodies from async iterables
  • fix: fix(gc): CannotCollect helpers' registry lock never flushes a deferred GC request (#11523)
  • fix: fix(gc): make the #11523 non-collecting root guard a distinct type so its drop provably never flushes
  • fix: fix(gc): pinned objects are marked, traced and scanned as roots (use-after-free in cross-thread promises) (#11664)
  • fix: fix(gc): reclassify js_array_push_f64; add #11522 Proxy-trap evacuation test
  • fix: fix(gc): split js_array_length into a GC-leaf fast lane and a collecting call (#11522)
  • fix: fix(gc-root-dominance): a phi edge that replaces the value is not in its window
  • fix: fix(gc-root-dominance): same phi-edge rule in --stale-registers; pin budgets 39->2, 118->10
  • fix: fix(hir): a native factory's result is a tagged receiver when used directly
  • …and 280 more

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

Survey your own repository

PerryTS/perry was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.

About this page

  • The score is its most recent published measurement, taken on 30 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
  • Measured at commit d51b6f61030a1d9a01f3305fe899e1e0b1ee1f77 — the exact code this score is about.
  • Scored under rubric-2026.09.18 — the same rubric and the same method as every other entry in this index.
  • Measured by watchdog.canine.dev using codehealth-analyzer preprod-cb25ca4feafa.