fix: string.search 无参调用越界 panic,参数读取守卫前置返回 -1
This commit is contained in:
@@ -1245,7 +1245,9 @@ pub fn string_match_fn<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
/// `String.prototype.search(pattern)`:返回首个匹配位置,无匹配返回 -1。
|
/// `String.prototype.search(pattern)`:返回首个匹配位置,无匹配返回 -1。
|
||||||
pub fn string_search<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn string_search<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
builtins_debug!("String.prototype.search called with {} args", args.len());
|
builtins_debug!("String.prototype.search called with {} args", args.len());
|
||||||
let pattern_val = vm.reg(args[1]);
|
// 参数读取守卫先行:无参调用缺省 searchString 为 undefined(args 仅含 this 槽)。
|
||||||
|
let pattern_val = if args.len() >= 2 { vm.reg(args[1]) } else { JsValue::undefined() };
|
||||||
|
|
||||||
// 正则判定与参数转换先行(&mut 路径),后借 this 扫描。
|
// 正则判定与参数转换先行(&mut 路径),后借 this 扫描。
|
||||||
let is_re = args.len() >= 2 && is_regexp_obj(pattern_val, vm);
|
let is_re = args.len() >= 2 && is_regexp_obj(pattern_val, vm);
|
||||||
let pattern = if args.len() >= 2 && !is_re {
|
let pattern = if args.len() >= 2 && !is_re {
|
||||||
|
|||||||
@@ -196,6 +196,47 @@ fn string_search_not_found() {
|
|||||||
assert_eq!(result.as_int(), -1);
|
assert_eq!(result.as_int(), -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn string_search_no_args_returns_minus_one() {
|
||||||
|
// 无参调用缺省 searchString:args 仅含 this 槽,守卫返回 -1,不越界 panic。
|
||||||
|
let mut vm = Vm::new();
|
||||||
|
let result = eval(&mut vm, "'abc'.search()").unwrap();
|
||||||
|
assert_eq!(result.as_int(), -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn string_search_undefined_arg_returns_minus_one() {
|
||||||
|
// 显式 undefined 参数:ToString(undefined)="undefined",在 "abc" 中无匹配返回 -1。
|
||||||
|
let mut vm = Vm::new();
|
||||||
|
let result = eval(&mut vm, "'abc'.search(undefined)").unwrap();
|
||||||
|
assert_eq!(result.as_int(), -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn string_search_empty_pattern_returns_zero() {
|
||||||
|
// 空串 pattern:find("") 命中串头,返回 0。
|
||||||
|
let mut vm = Vm::new();
|
||||||
|
let result = eval(&mut vm, "'abc'.search('')").unwrap();
|
||||||
|
assert_eq!(result.as_int(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn string_no_arg_guard_family_consistent() {
|
||||||
|
// 家族无参守卫对照:search/indexOf 返回 -1,includes/startsWith/endsWith 返回 false,
|
||||||
|
// charAt 取首字符——search 与同批方法守卫位置一致、行为家族化。
|
||||||
|
let mut vm = Vm::new();
|
||||||
|
let result = eval(&mut vm, "'abc'.search()").unwrap();
|
||||||
|
assert_eq!(result.as_int(), -1);
|
||||||
|
let result = eval(&mut vm, "'abc'.indexOf()").unwrap();
|
||||||
|
assert_eq!(result.as_int(), -1);
|
||||||
|
let result = eval(&mut vm, "'abc'.includes()").unwrap();
|
||||||
|
assert!(!result.as_bool());
|
||||||
|
let result = eval(&mut vm, "'abc'.startsWith()").unwrap();
|
||||||
|
assert!(!result.as_bool());
|
||||||
|
let result = eval(&mut vm, "'abc'.endsWith()").unwrap();
|
||||||
|
assert!(!result.as_bool());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn string_trim_start() {
|
fn string_trim_start() {
|
||||||
let mut vm = Vm::new();
|
let mut vm = Vm::new();
|
||||||
|
|||||||
Reference in New Issue
Block a user