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:
@@ -13,6 +13,23 @@ fn to_str(vm: &Vm, val: JsValue) -> String {
|
||||
vm.lookup_str(val).unwrap_or_default()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn regexp_survives_gc_and_still_matches() {
|
||||
// 回归:正则存入全局对象触发晋升/GC 搬移后,native_fn 槽的已编译 Box
|
||||
// 必须深拷贝到新对象(而非共享指针),否则 epoch 释放与 teardown 双重释放。
|
||||
let mut vm = Vm::new();
|
||||
let result = eval(&mut vm, "var r = /ab+c/g; globalThis.r = r; r.test('xxabbcx')").unwrap();
|
||||
assert!(result.as_bool());
|
||||
|
||||
// 触发完整收集:存活正则克隆进新 arena,旧 Box 由 sweep 释放。
|
||||
vm.reset();
|
||||
|
||||
let result = eval(&mut vm, "globalThis.r.test('xxabbcx')").unwrap();
|
||||
assert!(result.as_bool(), "GC 后正则应仍可匹配");
|
||||
let result = eval(&mut vm, "globalThis.r.exec('xabbbcx')[0]").unwrap();
|
||||
assert_eq!(to_str(&vm, result), "abbbc");
|
||||
}
|
||||
|
||||
// --- RegExp constructor ---
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -696,6 +696,25 @@ fn string_match_all_next_exhausted() {
|
||||
assert!(done);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn string_match_all_empty_match_advances() {
|
||||
// 回归:空匹配(range.start == range.end)后游标不前进会在同位置反复
|
||||
// 产出空匹配死循环;每位置应恰好一个空匹配后在有限步内耗尽。
|
||||
let mut vm = Vm::new();
|
||||
let result =
|
||||
eval(&mut vm, "var it = 'abc'.matchAll(/(?:)/g); var c = 0; while (!it.next().done) { c++; } c").unwrap();
|
||||
assert_num_eq(result, 4.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn string_match_all_star_empty_advances() {
|
||||
// /a*/g 在 'baaab' 上:空匹配(首尾)+ 长匹配混合,须在有限步内耗尽。
|
||||
let mut vm = Vm::new();
|
||||
let result =
|
||||
eval(&mut vm, "var it = 'baaab'.matchAll(/a*/g); var c = 0; while (!it.next().done) { c++; } c").unwrap();
|
||||
assert_num_eq(result, 4.0);
|
||||
}
|
||||
|
||||
// ── substring 测试 ──
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user