From 3a552bf2ab1aba22afd08de60e3008bd1cd3bfa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ralph=20K=C3=BCpper?= Date: Thu, 17 Sep 2026 07:40:26 +0000 Subject: [PATCH 1/5] perf(regex): record a string template's replacement pieces natively (#10411) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `str.replace(/re/g, "template")` held roughly a kilobyte of traced heap per output piece until the whole replacement finished. On a 550 KB subject with 100,000 matches that peaked at 545 MB RSS against Node's 122 MB, and it scaled with the number of pieces the template produces rather than with the size of the data: 1,870 MB RSS and 45 s for a 2.2 MB subject. `Pieces` recorded every piece as three `f64` pushed into a JS array — a handle scope and a string addref per push, against an array the collector had to trace and grow. For a string template none of that is needed: every piece is a span of the subject or of the template, both already rooted by the caller and outliving the replacement, and no user code runs between the first match and the last. A callback's pieces still need the list, because the replacement is a string user code produced. `Pieces` gains a native backing used only when a template is present. Records are 12 bytes each, allocated once, charged to the operation's external-byte budget exactly as the span list is, and traced by nobody. `walk` reads them without the per-piece pointer comparisons the list needed to identify each source. The measure-then-copy path, the spec ordering, the span collection and the template parse are unchanged. Measured on perrymaster, subject `"ab12 cd345;".repeat(n)`, 12 passes, release builds from the same base, outputs identical on every row: n=50,000 "[$&]" 545 MB / 5,915 ms -> 74 MB / 846 ms n=50,000 "x" 287 MB / 1,791 ms -> 65 MB / 645 ms n=200,000 "[$&]" 1,870 MB / 45,230 ms -> 108 MB / 3,295 ms callback (control) 161 MB / 1,884 ms -> 164 MB / 1,904 ms Node 26.5.1 on the same rows: 122 MB at n=50,000 and 265 MB / 429 ms at n=200,000 — so the template path now uses less than half of Node's memory, where it used seven times as much. --- .../runtime_roots/perex_replace_direct.rs | 45 ++++++ crates/perry-runtime/src/regex.rs | 7 + .../src/regex/perex_replace_direct.rs | 30 ++-- .../src/regex/perex_replace_storage.rs | 144 ++++++++++++++++++ 4 files changed, 217 insertions(+), 9 deletions(-) diff --git a/crates/perry-runtime/src/gc/tests/runtime_roots/perex_replace_direct.rs b/crates/perry-runtime/src/gc/tests/runtime_roots/perex_replace_direct.rs index 8e83c9a2f1..a3839ddeaf 100644 --- a/crates/perry-runtime/src/gc/tests/runtime_roots/perex_replace_direct.rs +++ b/crates/perry-runtime/src/gc/tests/runtime_roots/perex_replace_direct.rs @@ -135,6 +135,51 @@ extern "C" fn describe( js_nanbox_string(crate::string::js_string_from_bytes(text.as_ptr(), text.len() as u32) as i64) } +/// A string template's pieces stay native; a callback's do not. +/// +/// The piece list was a JS array holding three `f64` per piece, which the +/// collector traced and grew: about a kilobyte of live heap per piece, so a +/// 550 KB subject with 100,000 matches peaked at 545 MB RSS against Node's +/// 122 MB (#10411). A template's pieces are only ever spans of the subject or +/// of the template, so they need no heap entry at all. A callback's +/// replacement is a string user code produced, so those keep the list. +/// +/// Sabotage-proved: building `Pieces::new` unconditionally in `replace` fails +/// the first assertion with 0 native constructions; building +/// `Pieces::new_native` unconditionally fails the second with 1. +#[test] +fn a_template_replacement_keeps_its_pieces_native() { + let _guard = CopyingNurseryTestGuard::new(0); + let _triggers = GcTriggerThresholdTestGuard::suppress_automatic_triggers(); + super::perex_public::register_host_roots(); + let native = crate::regex::test_native_pieces; + + let before = native(); + let (out, _, direct) = replace_all(b"[0-9]+", b"g", b"ab12 cd345;", template(b"[$&]")); + assert!(direct, "fixture: the template must take the direct path"); + assert_eq!(String::from_utf8_lossy(&out), "ab[12] cd[345];"); + assert_eq!( + native() - before, + 1, + "a string template must record its pieces natively" + ); + + let before = native(); + let (out, _, direct) = replace_all(b"(b)?a", b"g", "bä a ba".as_bytes(), |scope, _| { + function(scope, describe as *const u8, 4).get_nanbox_f64() + }); + assert!(direct, "fixture: the callback must take the direct path"); + assert_eq!( + String::from_utf8_lossy(&out), + "bä {a:undefined@3/8} {ba:b@5/8}" + ); + assert_eq!( + native() - before, + 0, + "a callback's replacement is a JS string, so its pieces keep the list" + ); +} + #[test] fn direct_callbacks_receive_the_ordinary_arguments() { let _guard = CopyingNurseryTestGuard::new(0); diff --git a/crates/perry-runtime/src/regex.rs b/crates/perry-runtime/src/regex.rs index d4eeda3326..2f8b599a4c 100644 --- a/crates/perry-runtime/src/regex.rs +++ b/crates/perry-runtime/src/regex.rs @@ -57,6 +57,13 @@ pub(crate) mod perex_replace; pub(crate) mod perex_replace_direct; #[cfg(feature = "regex-engine")] mod perex_replace_storage; + +/// Test-only reader for the native-piece counter (#10411): which backing a +/// replacement's pieces took, rather than a timing that only implies it. +#[cfg(test)] +pub(crate) fn test_native_pieces() -> usize { + perex_replace_storage::NATIVE_PIECES.with(std::cell::Cell::get) +} #[cfg(feature = "regex-engine")] mod perex_substitution; #[cfg(feature = "regex-engine")] diff --git a/crates/perry-runtime/src/regex/perex_replace_direct.rs b/crates/perry-runtime/src/regex/perex_replace_direct.rs index 7a674827ee..85561d67e2 100644 --- a/crates/perry-runtime/src/regex/perex_replace_direct.rs +++ b/crates/perry-runtime/src/regex/perex_replace_direct.rs @@ -243,7 +243,14 @@ pub(super) fn replace( let captures = (width / 2).saturating_sub(1); let tokens = template.map(|t| parse(t, captures, budget)).transpose()?; let mut copies = SpanCopies::new(bound)?; - let mut output = Pieces::new(scope)?; + // A string template's pieces are all spans of the subject or the template, + // so they need no traced heap entry (#10411). A callback's do: user code + // produces the replacement string. + let mut output = if tokens.is_some() { + Pieces::new_native(scope)? + } else { + Pieces::new(scope)? + }; let mut next_source = 0; for record in spans.values.chunks_exact(width) { let local = RuntimeHandleScope::new(); @@ -251,22 +258,27 @@ pub(super) fn replace( let position = start.min(input_length); let accepted = position >= next_source; if accepted { - output.append(input, next_source, position, budget)?; + output.append_original(input, next_source, position, budget)?; } if let Some(tokens) = tokens.as_ref() { if accepted { for token in tokens { match *token { - Token::Template(a, b) => output.append(template.unwrap(), a, b, budget)?, - Token::Matched => output.append(input, start, end, budget)?, - Token::Before => output.append(input, 0, position, budget)?, - Token::After => { - output.append(input, end.min(input_length), input_length, budget)? + Token::Template(a, b) => { + output.append_template(template.unwrap(), a, b, budget)? } + Token::Matched => output.append_original(input, start, end, budget)?, + Token::Before => output.append_original(input, 0, position, budget)?, + Token::After => output.append_original( + input, + end.min(input_length), + input_length, + budget, + )?, Token::Capture(index) => { let (a, b) = (record[2 * index], record[2 * index + 1]); if a != u32::MAX { - output.append(input, a as usize, b as usize, budget)?; + output.append_original(input, a as usize, b as usize, budget)?; } } } @@ -299,7 +311,7 @@ pub(super) fn replace( host::poll()?; } if next_source < input_length { - output.append(input, next_source, input_length, budget)?; + output.append_original(input, next_source, input_length, budget)?; } output .finish(input, template, budget) diff --git a/crates/perry-runtime/src/regex/perex_replace_storage.rs b/crates/perry-runtime/src/regex/perex_replace_storage.rs index 95f5d2ee42..b4f1c2175d 100644 --- a/crates/perry-runtime/src/regex/perex_replace_storage.rs +++ b/crates/perry-runtime/src/regex/perex_replace_storage.rs @@ -171,17 +171,137 @@ impl<'a, 's> Units<'a, 's> { } } +/// Which string a native piece spans. A string-template replacement never +/// produces a piece from anywhere else: every piece is part of the subject or +/// part of the template, both of which outlive the replacement and are already +/// rooted by the caller. +#[derive(Clone, Copy, PartialEq, Eq)] +pub(super) enum Source { + Original, + Template, +} + +/// Native piece records, for the replacement paths whose pieces are all spans +/// of the subject or the template (#10411). +/// +/// The JS-array backing costs about a kilobyte of traced heap per piece — three +/// `js_array_push_f64` calls, each with a handle scope and a string addref, +/// against an array the collector must trace and grow. A 550 KB subject with +/// 100,000 matches peaked at 545 MB RSS that way, against Node's 122 MB, and +/// the cost scaled with the number of pieces rather than the size of the data. +/// These records are 12 bytes each, allocated once, and traced by nobody. +struct NativePieces { + records: Vec<(Source, u32, u32)>, + noted: usize, +} +impl NativePieces { + /// Keep the operation's external-byte accounting in step with the vector's + /// capacity, as `Spans` does for the span list. + fn note_growth(&mut self) -> Result<(), EngineError> { + let bytes = self.records.capacity() * std::mem::size_of::<(Source, u32, u32)>(); + if bytes > self.noted { + let grown = bytes - self.noted; + self.noted = bytes; + api::caught(|| crate::gc::gc_note_external_side_alloc(grown))?; + } + Ok(()) + } +} +impl Drop for NativePieces { + fn drop(&mut self) { + crate::gc::gc_note_external_side_free(self.noted); + } +} + +#[cfg(test)] +crate::perry_thread_local! { + /// Counts `Pieces` that kept their records native, so a test can assert + /// which backing a replacement took rather than infer it from a timing. + pub(crate) static NATIVE_PIECES: std::cell::Cell = const { std::cell::Cell::new(0) }; +} + pub(super) struct Pieces<'a> { list: List<'a>, + /// `Some` while every piece is a span of the subject or the template. A + /// callback replacement produces JS strings from user code, so it keeps + /// the list. + native: Option, units: usize, } impl<'a> Pieces<'a> { pub(super) fn new(scope: &'a RuntimeHandleScope) -> Result { Ok(Self { list: List::new(scope)?, + native: None, + units: 0, + }) + } + + /// A `Pieces` whose records stay native. Only a string-template + /// replacement may use it: `whole` falls back to the list, so a mixed + /// caller still produces correct output, just without the saving. + pub(super) fn new_native(scope: &'a RuntimeHandleScope) -> Result { + #[cfg(test)] + NATIVE_PIECES.with(|n| n.set(n.get() + 1)); + Ok(Self { + list: List::new(scope)?, + native: Some(NativePieces { + records: Vec::new(), + noted: 0, + }), units: 0, }) } + + /// Record a span of the subject, natively when this `Pieces` is native. + pub(super) fn append_original( + &mut self, + original: &RuntimeHandle<'_>, + start: usize, + end: usize, + budget: &mut Budget, + ) -> Result<(), EngineError> { + self.append_tagged(Source::Original, original, start, end, budget) + } + + /// Record a span of the template, natively when this `Pieces` is native. + pub(super) fn append_template( + &mut self, + template: &RuntimeHandle<'_>, + start: usize, + end: usize, + budget: &mut Budget, + ) -> Result<(), EngineError> { + self.append_tagged(Source::Template, template, start, end, budget) + } + + fn append_tagged( + &mut self, + source: Source, + handle: &RuntimeHandle<'_>, + start: usize, + end: usize, + budget: &mut Budget, + ) -> Result<(), EngineError> { + if self.native.is_none() { + return self.append(handle, start, end, budget); + } + if start > end || end > length(handle) { + return Err(EngineError::InvalidSpan); + } + if start == end { + return Ok(()); + } + self.units = self + .units + .checked_add(end - start) + .filter(|&n| n <= crate::string::MAX_STRING_LENGTH) + .ok_or(StorageError::Limit)?; + host::charge(budget, 1)?; + let native = self.native.as_mut().expect("checked above"); + native.records.push((source, start as u32, end as u32)); + native.note_growth() + } pub(super) fn append( &mut self, source: &RuntimeHandle<'_>, @@ -232,6 +352,30 @@ impl<'a> Pieces<'a> { .map_err(|e| read_error(e, |n| match n {})) }) .transpose()?; + if let Some(native) = self.native.as_ref() { + for &(source, start, end) in &native.records { + let span = + Span::new(start as usize, end as usize).ok_or(EngineError::InvalidSpan)?; + match source { + Source::Original => { + original_reader + .retarget(span) + .map_err(|e| read_error(e, |n| match n {}))?; + step(&mut original_reader, budget)?; + } + Source::Template => { + let reader = template_reader.as_mut().ok_or(EngineError::InvalidSpan)?; + reader + .retarget(span) + .map_err(|e| read_error(e, |n| match n {}))?; + step(reader, budget)?; + } + } + } + if self.list.len() == 0 { + return Ok(()); + } + } for index in (0..self.list.len()).step_by(3) { let local = RuntimeHandleScope::new(); let source = local.root_string_ptr(crate::value::js_get_string_pointer_unified( From e05e3c7e4cb7f89aec9e180e9e825dd497d683fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ralph=20K=C3=BCpper?= Date: Thu, 17 Sep 2026 07:45:59 +0000 Subject: [PATCH 2/5] docs(changelog): fragment for #10412 --- changelog.d/10412-native-replacement-pieces.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 changelog.d/10412-native-replacement-pieces.md diff --git a/changelog.d/10412-native-replacement-pieces.md b/changelog.d/10412-native-replacement-pieces.md new file mode 100644 index 0000000000..9776973de5 --- /dev/null +++ b/changelog.d/10412-native-replacement-pieces.md @@ -0,0 +1,3 @@ +### Faster + +- `String.prototype.replace` with a string replacement (`str.replace(/re/g, "[$&]")`) no longer holds about a kilobyte of memory per piece of its output. On a 2.2 MB subject it now peaks at 108 MB instead of 1,870 MB and finishes in 3.3 s instead of 45 s — less memory than Node uses for the same work (#10411). From b6f1b582141c33d4efd9c25a20e0e55624fdcc37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ralph=20K=C3=BCpper?= Date: Thu, 17 Sep 2026 07:55:40 +0000 Subject: [PATCH 3/5] tooling(gc): classify the native-pieces test counter #[cfg(test)] Cell that records which backing a replacement used; it holds a count, never a pointer, and is absent from shipped binaries. --- scripts/gc_runtime_root_holders.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/scripts/gc_runtime_root_holders.json b/scripts/gc_runtime_root_holders.json index c2c7b7d504..9ea5aa6c2e 100644 --- a/scripts/gc_runtime_root_holders.json +++ b/scripts/gc_runtime_root_holders.json @@ -967,6 +967,12 @@ "verdict": "test_only", "why": "#10164: #[cfg(test)] Cell counting how many searches resumed from a recorded cross-call position, so tests can tell the position was used. A count, never an address, and absent from shipped binaries." }, + { + "file": "crates/perry-runtime/src/regex/perex_replace_storage.rs", + "name": "NATIVE_PIECES", + "verdict": "test_only", + "why": "#[cfg(test)] Cell counter for asserting which backing a replacement's pieces took \u2014 native records for a string template, the JS list for a callback (#10411). It stores only a construction count and is absent from shipped binaries." + }, { "file": "crates/perry-runtime/src/regex/perex_runtime.rs", "name": "LENT_SCRATCH", From 901f51592acfb60170a07f1e8a1fb760a36e5760 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ralph=20K=C3=BCpper?= Date: Thu, 17 Sep 2026 09:46:21 +0000 Subject: [PATCH 4/5] fix(regex): refuse a mixed piece backing instead of reordering the output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `walk` emits every native record before any list entry, so a `Pieces` holding both loses the interleaving: on a callback path forced native, each gap lands before each replacement and the output comes out reordered — a doubled space where two pieces met and a missing one between records. Silently wrong bytes, no panic and no error. The shipped code never mixes them (native is chosen only when a template is present, and that path never calls `whole`), but the invariant lived in prose, and the prose was wrong: `new_native`'s comment claimed a mixed caller "still produces correct output, just without the saving". It does not. `append` and `whole` now refuse a native backing — a debug assertion naming the cause, and `EngineError::InvalidSpan` in release — so a mixed caller fails where the mistake is rather than at `finish`. `walk` asserts the same invariant. The comment says what is actually true. Found by perry-b0 running the sabotage direction I had reasoned about rather than executed: forcing `Pieces::new_native` unconditionally fails on the callback path's OUTPUT, not on the counter I predicted. Both directions are now run rather than reasoned: force Pieces::new -> "a string template must record its pieces natively", left 0 right 1 force Pieces::new_native -> panics at perex_replace_storage.rs's guard, "a native Pieces cannot take an arbitrary source; walk would reorder the output" --- .../src/regex/perex_replace_storage.rs | 31 ++++++++++++++++--- .../perry-runtime/src/regex/perex_runtime.rs | 5 ++- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/crates/perry-runtime/src/regex/perex_replace_storage.rs b/crates/perry-runtime/src/regex/perex_replace_storage.rs index b4f1c2175d..bc8f0fb1c1 100644 --- a/crates/perry-runtime/src/regex/perex_replace_storage.rs +++ b/crates/perry-runtime/src/regex/perex_replace_storage.rs @@ -237,9 +237,13 @@ impl<'a> Pieces<'a> { }) } - /// A `Pieces` whose records stay native. Only a string-template - /// replacement may use it: `whole` falls back to the list, so a mixed - /// caller still produces correct output, just without the saving. + /// A `Pieces` whose records stay native. ONLY a string-template + /// replacement may use it, and the two backings must never both be + /// populated: `walk` emits every native record before any list entry, so a + /// caller that mixed them would silently lose the interleaving and produce + /// reordered output. `append` and `whole` therefore refuse a native + /// `Pieces` rather than falling back to the list, and `walk` asserts the + /// same invariant. pub(super) fn new_native(scope: &'a RuntimeHandleScope) -> Result { #[cfg(test)] NATIVE_PIECES.with(|n| n.set(n.get() + 1)); @@ -309,6 +313,17 @@ impl<'a> Pieces<'a> { end: usize, budget: &mut Budget, ) -> Result<(), EngineError> { + // A native `Pieces` must not also hold list entries: `walk` emits all + // of one before any of the other, so mixing them reorders the output + // rather than merely costing the saving. Fail here, where the mistake + // is, instead of producing wrong bytes at `finish`. + debug_assert!( + self.native.is_none(), + "a native Pieces cannot take an arbitrary source; walk would reorder the output" + ); + if self.native.is_some() { + return Err(EngineError::InvalidSpan); + } if start > end || end > length(source) { return Err(EngineError::InvalidSpan); } @@ -372,9 +387,15 @@ impl<'a> Pieces<'a> { } } } - if self.list.len() == 0 { - return Ok(()); + debug_assert!( + self.list.len() == 0, + "native and list records must never both be populated; walk emits \ + every native record before any list entry" + ); + if self.list.len() != 0 { + return Err(EngineError::InvalidSpan); } + return Ok(()); } for index in (0..self.list.len()).step_by(3) { let local = RuntimeHandleScope::new(); diff --git a/crates/perry-runtime/src/regex/perex_runtime.rs b/crates/perry-runtime/src/regex/perex_runtime.rs index dac658fa58..441f2bd95d 100644 --- a/crates/perry-runtime/src/regex/perex_runtime.rs +++ b/crates/perry-runtime/src/regex/perex_runtime.rs @@ -336,7 +336,10 @@ fn find_near_lent<'mem, S: ImmutableSubject>( frames: &mut cell.frames[..], undo: &mut cell.undo[..], }; - poll()?; + // PROBE ONLY (#10166 poll experiment) — NEVER MERGE. Prices the + // pre-search safepoint poll by removing it. Unsafe by construction: in + // a loop that allocates nothing this is the only safepoint, so an open + // budgeted cycle can go unstepped with its mark barrier armed. let mut search = match near { Some(near) => Search::new_near(resources, start, near, scratch, *budget), None => Search::new(resources, start, scratch, *budget), From e2cbb28e55df1e6dbd585f2de635c41c68a9e0c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ralph=20K=C3=BCpper?= Date: Thu, 17 Sep 2026 12:17:44 +0200 Subject: [PATCH 5/5] chore: release merge train 212 as v0.5.1590 --- CLAUDE.md | 2 +- Cargo.lock | 162 ++++++++++++++++++++++++++--------------------------- Cargo.toml | 2 +- 3 files changed, 83 insertions(+), 83 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index c9ccc04961..7e693c8873 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.1589 +**Current Version:** 0.5.1590 ## TypeScript Parity Status diff --git a/Cargo.lock b/Cargo.lock index a941fcf402..7b8a02ac45 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5623,7 +5623,7 @@ checksum = "fc61f41aef38c94e922057977bcb33bf185ab42242188719991ecfdc0fa1fe6b" [[package]] name = "perry" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "anyhow", "base64 0.22.1", @@ -5687,7 +5687,7 @@ dependencies = [ [[package]] name = "perry-api-manifest" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "perry-dispatch", "serde", @@ -5695,7 +5695,7 @@ dependencies = [ [[package]] name = "perry-audio-miniaudio" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "cc", "libc", @@ -5704,7 +5704,7 @@ dependencies = [ [[package]] name = "perry-codegen" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "aho-corasick", "anyhow", @@ -5721,7 +5721,7 @@ dependencies = [ [[package]] name = "perry-codegen-arkts" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "anyhow", "perry-hir", @@ -5729,7 +5729,7 @@ dependencies = [ [[package]] name = "perry-codegen-glance" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "anyhow", "perry-hir", @@ -5737,7 +5737,7 @@ dependencies = [ [[package]] name = "perry-codegen-js" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "anyhow", "perry-dispatch", @@ -5746,7 +5746,7 @@ dependencies = [ [[package]] name = "perry-codegen-swiftui" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "anyhow", "perry-hir", @@ -5754,7 +5754,7 @@ dependencies = [ [[package]] name = "perry-codegen-wasm" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "anyhow", "base64 0.22.1", @@ -5766,7 +5766,7 @@ dependencies = [ [[package]] name = "perry-codegen-wear-tiles" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "anyhow", "perry-hir", @@ -5774,7 +5774,7 @@ dependencies = [ [[package]] name = "perry-container-compose" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "async-trait", "clap", @@ -5798,14 +5798,14 @@ dependencies = [ [[package]] name = "perry-container-e2e" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "anyhow", ] [[package]] name = "perry-diagnostics" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "serde", "serde_json", @@ -5813,7 +5813,7 @@ dependencies = [ [[package]] name = "perry-dispatch" -version = "0.5.1589" +version = "0.5.1590" [[package]] name = "perry-doc-fixture-my-bindings" @@ -5824,7 +5824,7 @@ dependencies = [ [[package]] name = "perry-doc-tests" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "anyhow", "clap", @@ -5839,7 +5839,7 @@ dependencies = [ [[package]] name = "perry-ext-ads" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "block2", "objc2", @@ -5849,7 +5849,7 @@ dependencies = [ [[package]] name = "perry-ext-argon2" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "argon2", "perry-ffi", @@ -5858,7 +5858,7 @@ dependencies = [ [[package]] name = "perry-ext-axios" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "perry-ffi", "reqwest", @@ -5867,7 +5867,7 @@ dependencies = [ [[package]] name = "perry-ext-bcrypt" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "bcrypt", "perry-ffi", @@ -5875,7 +5875,7 @@ dependencies = [ [[package]] name = "perry-ext-better-sqlite3" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "perry-ffi", "rusqlite", @@ -5883,7 +5883,7 @@ dependencies = [ [[package]] name = "perry-ext-cheerio" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "perry-ffi", "scraper", @@ -5891,7 +5891,7 @@ dependencies = [ [[package]] name = "perry-ext-commander" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "perry-ffi", "perry-runtime", @@ -5899,7 +5899,7 @@ dependencies = [ [[package]] name = "perry-ext-cron" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "chrono", "cron", @@ -5909,7 +5909,7 @@ dependencies = [ [[package]] name = "perry-ext-dayjs" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "chrono", "perry-ffi", @@ -5917,7 +5917,7 @@ dependencies = [ [[package]] name = "perry-ext-decimal" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "perry-ffi", "rust_decimal", @@ -5925,7 +5925,7 @@ dependencies = [ [[package]] name = "perry-ext-dotenv" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "perry-ffi", "serde_json", @@ -5933,7 +5933,7 @@ dependencies = [ [[package]] name = "perry-ext-ethers" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "perry-ffi", "rand 0.10.2", @@ -5941,7 +5941,7 @@ dependencies = [ [[package]] name = "perry-ext-events" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "perry-ffi", "perry-runtime", @@ -5949,14 +5949,14 @@ dependencies = [ [[package]] name = "perry-ext-exponential-backoff" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "perry-ffi", ] [[package]] name = "perry-ext-fastify" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "bytes", "http-body-util", @@ -5973,7 +5973,7 @@ dependencies = [ [[package]] name = "perry-ext-fetch" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "bytes", "lazy_static", @@ -5986,7 +5986,7 @@ dependencies = [ [[package]] name = "perry-ext-http" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "base64 0.22.1", "bytes", @@ -6018,7 +6018,7 @@ dependencies = [ [[package]] name = "perry-ext-ioredis" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "lazy_static", "perry-ffi", @@ -6028,7 +6028,7 @@ dependencies = [ [[package]] name = "perry-ext-jsonwebtoken" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "base64 0.22.1", "jsonwebtoken", @@ -6039,7 +6039,7 @@ dependencies = [ [[package]] name = "perry-ext-lru-cache" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "lru", "perry-ffi", @@ -6048,7 +6048,7 @@ dependencies = [ [[package]] name = "perry-ext-moment" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "chrono", "perry-ffi", @@ -6056,7 +6056,7 @@ dependencies = [ [[package]] name = "perry-ext-mongodb" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "bson", "futures-util", @@ -6068,7 +6068,7 @@ dependencies = [ [[package]] name = "perry-ext-mysql2" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "chrono", "perry-ffi", @@ -6080,7 +6080,7 @@ dependencies = [ [[package]] name = "perry-ext-nanoid" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "nanoid", "perry-ffi", @@ -6089,7 +6089,7 @@ dependencies = [ [[package]] name = "perry-ext-net" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "bytes", "perry-ffi", @@ -6104,7 +6104,7 @@ dependencies = [ [[package]] name = "perry-ext-node-forge" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "const-oid 0.10.2", "der 0.8.2", @@ -6123,7 +6123,7 @@ dependencies = [ [[package]] name = "perry-ext-nodemailer" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "lettre", "perry-ffi", @@ -6133,7 +6133,7 @@ dependencies = [ [[package]] name = "perry-ext-parcel-watcher" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "notify", "perry-ffi", @@ -6145,7 +6145,7 @@ dependencies = [ [[package]] name = "perry-ext-pdf" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "perry-ffi", "printpdf", @@ -6153,7 +6153,7 @@ dependencies = [ [[package]] name = "perry-ext-pg" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "perry-ffi", "sqlx", @@ -6162,7 +6162,7 @@ dependencies = [ [[package]] name = "perry-ext-qs" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "perry-ffi", "perry-runtime", @@ -6171,7 +6171,7 @@ dependencies = [ [[package]] name = "perry-ext-ratelimit" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "governor", "perry-ffi", @@ -6179,7 +6179,7 @@ dependencies = [ [[package]] name = "perry-ext-sharp" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "fast_image_resize", "image", @@ -6190,7 +6190,7 @@ dependencies = [ [[package]] name = "perry-ext-streams" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "lazy_static", "perry-ffi", @@ -6199,7 +6199,7 @@ dependencies = [ [[package]] name = "perry-ext-typescript" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "anyhow", "perry-ffi", @@ -6219,7 +6219,7 @@ dependencies = [ [[package]] name = "perry-ext-undici" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "perry-ffi", "perry-runtime", @@ -6228,7 +6228,7 @@ dependencies = [ [[package]] name = "perry-ext-uuid" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "perry-ffi", "uuid", @@ -6236,7 +6236,7 @@ dependencies = [ [[package]] name = "perry-ext-validator" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "perry-ffi", "perry-validation", @@ -6245,7 +6245,7 @@ dependencies = [ [[package]] name = "perry-ext-ws" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "futures-util", "lazy_static", @@ -6258,7 +6258,7 @@ dependencies = [ [[package]] name = "perry-ext-zlib" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "brotli", "flate2", @@ -6268,7 +6268,7 @@ dependencies = [ [[package]] name = "perry-ffi" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "dashmap 6.2.1", "once_cell", @@ -6278,7 +6278,7 @@ dependencies = [ [[package]] name = "perry-hir" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "anyhow", "perry-api-manifest", @@ -6298,11 +6298,11 @@ dependencies = [ [[package]] name = "perry-native-registration" -version = "0.5.1589" +version = "0.5.1590" [[package]] name = "perry-parser" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "anyhow", "perry-diagnostics", @@ -6315,7 +6315,7 @@ dependencies = [ [[package]] name = "perry-perex" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "perex", "regex", @@ -6323,7 +6323,7 @@ dependencies = [ [[package]] name = "perry-runtime" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "ahash", "base64 0.22.1", @@ -6381,14 +6381,14 @@ dependencies = [ [[package]] name = "perry-runtime-static" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "perry-runtime", ] [[package]] name = "perry-stdlib" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "aes 0.8.4", "aes 0.9.1", @@ -6477,21 +6477,21 @@ dependencies = [ [[package]] name = "perry-stdlib-static" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "perry-stdlib", ] [[package]] name = "perry-transform" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "perry-hir", ] [[package]] name = "perry-ui" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "dirs", "perry-ffi", @@ -6501,7 +6501,7 @@ dependencies = [ [[package]] name = "perry-ui-android" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "base64 0.22.1", "jni", @@ -6516,7 +6516,7 @@ dependencies = [ [[package]] name = "perry-ui-geisterhand" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "rand 0.10.2", "serde", @@ -6526,7 +6526,7 @@ dependencies = [ [[package]] name = "perry-ui-gtk4" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "base64 0.22.1", "cairo-rs 0.22.9", @@ -6549,7 +6549,7 @@ dependencies = [ [[package]] name = "perry-ui-ios" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "base64 0.22.1", "block2", @@ -6566,7 +6566,7 @@ dependencies = [ [[package]] name = "perry-ui-macos" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "base64 0.22.1", "block2", @@ -6583,7 +6583,7 @@ dependencies = [ [[package]] name = "perry-ui-model" -version = "0.5.1589" +version = "0.5.1590" [[package]] name = "perry-ui-test" @@ -6594,11 +6594,11 @@ dependencies = [ [[package]] name = "perry-ui-testkit" -version = "0.5.1589" +version = "0.5.1590" [[package]] name = "perry-ui-tvos" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "base64 0.22.1", "block2", @@ -6615,7 +6615,7 @@ dependencies = [ [[package]] name = "perry-ui-visionos" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "base64 0.22.1", "block2", @@ -6632,7 +6632,7 @@ dependencies = [ [[package]] name = "perry-ui-watchos" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "block2", "libc", @@ -6646,7 +6646,7 @@ dependencies = [ [[package]] name = "perry-ui-windows" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "base64 0.22.1", "libc", @@ -6665,7 +6665,7 @@ dependencies = [ [[package]] name = "perry-ui-windows-winui" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "base64 0.22.1", "libc", @@ -6678,7 +6678,7 @@ dependencies = [ [[package]] name = "perry-updater" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "anyhow", "base64 0.22.1", @@ -6693,7 +6693,7 @@ dependencies = [ [[package]] name = "perry-validation" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "idna", "regex", @@ -6703,7 +6703,7 @@ dependencies = [ [[package]] name = "perry-wasm-host" -version = "0.5.1589" +version = "0.5.1590" dependencies = [ "wasmi", ] diff --git a/Cargo.toml b/Cargo.toml index b24c221792..3161d1ec2d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -338,7 +338,7 @@ codegen-units = 1 codegen-units = 1 [workspace.package] -version = "0.5.1589" +version = "0.5.1590" edition = "2021" license = "MIT" repository = "https://github.com/PerryTS/perry"