Scripts: flattening a rope keeps it rooted while its copy is reserved

flat_charged and the property-key path now root the rope itself, so a string held only by
native code (a getter's result for ++o.x, a valueOf result, a toString key) still counts
what it holds when the reservation collects. The per-call roots for these cases are removed.
This commit is contained in:
dotCooCoo
2026-11-11 23:02:45 -08:00
parent c2c560eeaa
commit 49c8a380a1
4 changed files with 12 additions and 14 deletions
+3 -2
View File
@@ -109,10 +109,11 @@ fn push_held<T>(interp: &mut Interp, held: &mut HeldBytes, list: &mut Vec<T>, it
}
/// The code units of `s`. Flattening a rope makes a copy of its units, so for a rope that copy's
/// bytes are reserved and added to the heap, and its units charged as fuel, first.
/// bytes are reserved and added to the heap, and its units charged as fuel, first. The rope stays
/// rooted while the copy is reserved, so what it holds is still counted.
pub(crate) fn flat_charged(interp: &mut Interp, s: &Str) -> JsResult<Rc<[u16]>> {
if s.is_rope() {
reserve_units(interp, s.len())?;
interp.rooted(&[Value::String(s.clone())], |interp| reserve_units(interp, s.len()))?;
}
Ok(s.flat())
}