fix: matchAll 空匹配推进至少一个字符,RegExp 补 GC 搬移深拷贝

matchAll 迭代器在空匹配(range.start == range.end)后把游标停在原位置,
同一位置反复空匹配导致死循环;改为按 UTF-8 字符边界推进(与 regress
find_iter 的 next_right_pos 一致),串尾空匹配把游标推到串长之后保证下轮
耗尽。

另修 RegExp 在 GC sweep 与 epoch 晋升中的指针别名:克隆只复制 native_fn 槽
的 Box 指针,源对象释放后克隆持悬垂指针,teardown 双重释放(heap 损坏)。
新增 clone_regexp_native 深拷贝已编译正则,sweep/promote 两处挂接,与
drop 配对保证单次释放。
This commit is contained in:
2026-08-15 20:31:51 +08:00
parent 1c70d0343d
commit f4e790978d
6 changed files with 75 additions and 2 deletions
+12 -1
View File
@@ -1613,7 +1613,18 @@ pub fn string_match_all_next<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult
None => parts.push(String::new()),
}
}
idx = range.end;
// 空匹配(range.start == range.end)必须推进至少一个 UTF-8 字符,否则同一
// 位置反复空匹配死循环;空匹配落在串尾时把游标推到串尾之后,保证下一轮
// 直接耗尽(与 regress find_iter 的 next_right_pos 推进语义一致)。
idx = if range.end > range.start {
range.end
} else {
range.end
+ input_str
.get(range.end..)
.and_then(|s| s.chars().next())
.map_or(1, char::len_utf8)
};
vm.set_or_create_prop_value(wrapper, index_si, JsValue::int(idx as i32));
let arr_val = make_string_array(vm, parts);
make_match_done_result(vm, arr_val)