avm1: Fix string methods handling of negative args (fix #4437)
* Improve string.substr handling of negative args * Add tests for more substr() combinations
This commit is contained in:
parent
b4dd64a568
commit
34d54dbc05
|
@ -345,13 +345,19 @@ fn substr<'gc>(
|
||||||
let this_val = Value::from(this);
|
let this_val = Value::from(this);
|
||||||
let this = this_val.coerce_to_string(activation)?;
|
let this = this_val.coerce_to_string(activation)?;
|
||||||
let this_len = this.encode_utf16().count();
|
let this_len = this.encode_utf16().count();
|
||||||
let start_index_raw = args.get(0).unwrap().coerce_to_i32(activation)?;
|
let start_index = string_wrapping_index(
|
||||||
let start_index = string_wrapping_index(start_index_raw, this_len);
|
args.get(0)
|
||||||
|
.unwrap_or(&Value::Undefined)
|
||||||
|
.coerce_to_i32(activation)?,
|
||||||
|
this_len,
|
||||||
|
);
|
||||||
|
|
||||||
let len = match args.get(1) {
|
let len = match args.get(1) {
|
||||||
None | Some(Value::Undefined) => this_len,
|
None | Some(Value::Undefined) => this_len as i32,
|
||||||
Some(n) => string_index_substr(start_index_raw, n.coerce_to_i32(activation)?, this_len),
|
Some(n) => n.coerce_to_i32(activation)?,
|
||||||
};
|
};
|
||||||
|
let end_index = string_wrapping_index((start_index as i32) + len, this_len);
|
||||||
|
let len = end_index.saturating_sub(start_index);
|
||||||
|
|
||||||
let ret = string_utils::utf16_iter_to_string(this.encode_utf16().skip(start_index).take(len));
|
let ret = string_utils::utf16_iter_to_string(this.encode_utf16().skip(start_index).take(len));
|
||||||
Ok(AvmString::new(activation.context.gc_context, ret).into())
|
Ok(AvmString::new(activation.context.gc_context, ret).into())
|
||||||
|
@ -441,15 +447,10 @@ fn to_upper_case<'gc>(
|
||||||
/// Normalizes an index parameter used in `String` functions such as `substring`.
|
/// Normalizes an index parameter used in `String` functions such as `substring`.
|
||||||
/// The returned index will be within the range of `[0, len]`.
|
/// The returned index will be within the range of `[0, len]`.
|
||||||
fn string_index(i: i32, len: usize) -> usize {
|
fn string_index(i: i32, len: usize) -> usize {
|
||||||
if i > 0 {
|
if i < 0 {
|
||||||
let i = i as usize;
|
|
||||||
if i < len {
|
|
||||||
i
|
|
||||||
} else {
|
|
||||||
len
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
0
|
0
|
||||||
|
} else {
|
||||||
|
(i as usize).min(len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -457,41 +458,10 @@ fn string_index(i: i32, len: usize) -> usize {
|
||||||
/// Negative values will count backwards from `len`.
|
/// Negative values will count backwards from `len`.
|
||||||
/// The returned index will be within the range of `[0, len]`.
|
/// The returned index will be within the range of `[0, len]`.
|
||||||
fn string_wrapping_index(i: i32, len: usize) -> usize {
|
fn string_wrapping_index(i: i32, len: usize) -> usize {
|
||||||
if i >= 0 {
|
if i < 0 {
|
||||||
let i = i as usize;
|
let offset = i as isize;
|
||||||
if i < len {
|
len.saturating_sub((-offset) as usize)
|
||||||
i
|
|
||||||
} else {
|
} else {
|
||||||
len
|
(i as usize).min(len)
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let i = (-i) as usize;
|
|
||||||
if i <= len {
|
|
||||||
len - i
|
|
||||||
} else {
|
|
||||||
len
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Normalizes an index parameter used in substr.
|
|
||||||
/// If start + length is not less than zero, the parameter is zero,
|
|
||||||
/// otherwise negative values will count backwards from `len`.
|
|
||||||
/// The returned index will be within the range of `[0, len]`.
|
|
||||||
fn string_index_substr(s: i32, e: i32, len: usize) -> usize {
|
|
||||||
if e >= 0 {
|
|
||||||
string_index(e, len)
|
|
||||||
} else {
|
|
||||||
let t = s + e;
|
|
||||||
if t >= 0 {
|
|
||||||
0
|
|
||||||
} else {
|
|
||||||
let e = (-e) as usize;
|
|
||||||
if e <= len {
|
|
||||||
len - e
|
|
||||||
} else {
|
|
||||||
len
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -182,8 +182,8 @@ swf_tests! {
|
||||||
(slash_syntax, "avm1/slash_syntax", 2),
|
(slash_syntax, "avm1/slash_syntax", 2),
|
||||||
(strictequals_swf6, "avm1/strictequals_swf6", 1),
|
(strictequals_swf6, "avm1/strictequals_swf6", 1),
|
||||||
(string_methods, "avm1/string_methods", 1),
|
(string_methods, "avm1/string_methods", 1),
|
||||||
|
(string_methods_negative_args, "avm1/string_methods_negative_args", 1),
|
||||||
(string_ops_swf6, "avm1/string_ops_swf6", 1),
|
(string_ops_swf6, "avm1/string_ops_swf6", 1),
|
||||||
(substr_negative, "avm1/substr_negative", 1),
|
|
||||||
(path_string, "avm1/path_string", 1),
|
(path_string, "avm1/path_string", 1),
|
||||||
(global_is_bare, "avm1/global_is_bare", 1),
|
(global_is_bare, "avm1/global_is_bare", 1),
|
||||||
(primitive_type_globals, "avm1/primitive_type_globals", 1),
|
(primitive_type_globals, "avm1/primitive_type_globals", 1),
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
// Compile with:
|
||||||
|
// mtasc -main -header 200:150:30 Test.as -swf test.swf
|
||||||
|
class Test {
|
||||||
|
static function main(current) {
|
||||||
|
|
||||||
|
trace("// var str = hello world");
|
||||||
|
var str = "hello world";
|
||||||
|
trace("// str.substr(0, -1)");
|
||||||
|
trace(str.substr(0,-1));
|
||||||
|
trace("// str.substr(0, -4)");
|
||||||
|
trace(str.substr(0,-4));
|
||||||
|
trace("// str.substr(8, -4)");
|
||||||
|
trace(str.substr(8,-4));
|
||||||
|
trace("// str.substr(3, -3)");
|
||||||
|
trace(str.substr(3,-3));
|
||||||
|
trace("// str.substr(3, -4)");
|
||||||
|
trace(str.substr(3,-4));
|
||||||
|
trace("// str.substr(3, -5)");
|
||||||
|
trace(str.substr(3,-5));
|
||||||
|
trace("// str.substr(4, -4)");
|
||||||
|
trace(str.substr(4,-4));
|
||||||
|
trace("// str.substr(4, -5)");
|
||||||
|
trace(str.substr(4,-5));
|
||||||
|
trace("// str.substr(null, -1)");
|
||||||
|
trace(str.substr(null,-1));
|
||||||
|
trace("// str.substr(undefined, -1)");
|
||||||
|
trace(str.substr(undefined,-1));
|
||||||
|
|
||||||
|
var text = "abcd";
|
||||||
|
for (var i = -5; i < 5; i += 1) {
|
||||||
|
trace("// text.substr(" + i + ")");
|
||||||
|
trace(text.substr(i));
|
||||||
|
for (var j = -5; j < 5; j += 1) {
|
||||||
|
trace("// text.substr(" + i + "," + j + ")");
|
||||||
|
trace(text.substr(i, j));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,241 @@
|
||||||
|
// var str = hello world
|
||||||
|
// str.substr(0, -1)
|
||||||
|
hello worl
|
||||||
|
// str.substr(0, -4)
|
||||||
|
hello w
|
||||||
|
// str.substr(8, -4)
|
||||||
|
|
||||||
|
// str.substr(3, -3)
|
||||||
|
|
||||||
|
// str.substr(3, -4)
|
||||||
|
lo worl
|
||||||
|
// str.substr(3, -5)
|
||||||
|
lo wor
|
||||||
|
// str.substr(4, -4)
|
||||||
|
|
||||||
|
// str.substr(4, -5)
|
||||||
|
o worl
|
||||||
|
// str.substr(null, -1)
|
||||||
|
hello worl
|
||||||
|
// str.substr(undefined, -1)
|
||||||
|
hello worl
|
||||||
|
// text.substr(-5)
|
||||||
|
abcd
|
||||||
|
// text.substr(-5,-5)
|
||||||
|
|
||||||
|
// text.substr(-5,-4)
|
||||||
|
|
||||||
|
// text.substr(-5,-3)
|
||||||
|
a
|
||||||
|
// text.substr(-5,-2)
|
||||||
|
ab
|
||||||
|
// text.substr(-5,-1)
|
||||||
|
abc
|
||||||
|
// text.substr(-5,0)
|
||||||
|
|
||||||
|
// text.substr(-5,1)
|
||||||
|
a
|
||||||
|
// text.substr(-5,2)
|
||||||
|
ab
|
||||||
|
// text.substr(-5,3)
|
||||||
|
abc
|
||||||
|
// text.substr(-5,4)
|
||||||
|
abcd
|
||||||
|
// text.substr(-4)
|
||||||
|
abcd
|
||||||
|
// text.substr(-4,-5)
|
||||||
|
|
||||||
|
// text.substr(-4,-4)
|
||||||
|
|
||||||
|
// text.substr(-4,-3)
|
||||||
|
a
|
||||||
|
// text.substr(-4,-2)
|
||||||
|
ab
|
||||||
|
// text.substr(-4,-1)
|
||||||
|
abc
|
||||||
|
// text.substr(-4,0)
|
||||||
|
|
||||||
|
// text.substr(-4,1)
|
||||||
|
a
|
||||||
|
// text.substr(-4,2)
|
||||||
|
ab
|
||||||
|
// text.substr(-4,3)
|
||||||
|
abc
|
||||||
|
// text.substr(-4,4)
|
||||||
|
abcd
|
||||||
|
// text.substr(-3)
|
||||||
|
bcd
|
||||||
|
// text.substr(-3,-5)
|
||||||
|
|
||||||
|
// text.substr(-3,-4)
|
||||||
|
|
||||||
|
// text.substr(-3,-3)
|
||||||
|
b
|
||||||
|
// text.substr(-3,-2)
|
||||||
|
bc
|
||||||
|
// text.substr(-3,-1)
|
||||||
|
|
||||||
|
// text.substr(-3,0)
|
||||||
|
|
||||||
|
// text.substr(-3,1)
|
||||||
|
b
|
||||||
|
// text.substr(-3,2)
|
||||||
|
bc
|
||||||
|
// text.substr(-3,3)
|
||||||
|
bcd
|
||||||
|
// text.substr(-3,4)
|
||||||
|
bcd
|
||||||
|
// text.substr(-2)
|
||||||
|
cd
|
||||||
|
// text.substr(-2,-5)
|
||||||
|
|
||||||
|
// text.substr(-2,-4)
|
||||||
|
|
||||||
|
// text.substr(-2,-3)
|
||||||
|
c
|
||||||
|
// text.substr(-2,-2)
|
||||||
|
|
||||||
|
// text.substr(-2,-1)
|
||||||
|
|
||||||
|
// text.substr(-2,0)
|
||||||
|
|
||||||
|
// text.substr(-2,1)
|
||||||
|
c
|
||||||
|
// text.substr(-2,2)
|
||||||
|
cd
|
||||||
|
// text.substr(-2,3)
|
||||||
|
cd
|
||||||
|
// text.substr(-2,4)
|
||||||
|
cd
|
||||||
|
// text.substr(-1)
|
||||||
|
d
|
||||||
|
// text.substr(-1,-5)
|
||||||
|
|
||||||
|
// text.substr(-1,-4)
|
||||||
|
|
||||||
|
// text.substr(-1,-3)
|
||||||
|
|
||||||
|
// text.substr(-1,-2)
|
||||||
|
|
||||||
|
// text.substr(-1,-1)
|
||||||
|
|
||||||
|
// text.substr(-1,0)
|
||||||
|
|
||||||
|
// text.substr(-1,1)
|
||||||
|
d
|
||||||
|
// text.substr(-1,2)
|
||||||
|
d
|
||||||
|
// text.substr(-1,3)
|
||||||
|
d
|
||||||
|
// text.substr(-1,4)
|
||||||
|
d
|
||||||
|
// text.substr(0)
|
||||||
|
abcd
|
||||||
|
// text.substr(0,-5)
|
||||||
|
|
||||||
|
// text.substr(0,-4)
|
||||||
|
|
||||||
|
// text.substr(0,-3)
|
||||||
|
a
|
||||||
|
// text.substr(0,-2)
|
||||||
|
ab
|
||||||
|
// text.substr(0,-1)
|
||||||
|
abc
|
||||||
|
// text.substr(0,0)
|
||||||
|
|
||||||
|
// text.substr(0,1)
|
||||||
|
a
|
||||||
|
// text.substr(0,2)
|
||||||
|
ab
|
||||||
|
// text.substr(0,3)
|
||||||
|
abc
|
||||||
|
// text.substr(0,4)
|
||||||
|
abcd
|
||||||
|
// text.substr(1)
|
||||||
|
bcd
|
||||||
|
// text.substr(1,-5)
|
||||||
|
|
||||||
|
// text.substr(1,-4)
|
||||||
|
|
||||||
|
// text.substr(1,-3)
|
||||||
|
b
|
||||||
|
// text.substr(1,-2)
|
||||||
|
bc
|
||||||
|
// text.substr(1,-1)
|
||||||
|
|
||||||
|
// text.substr(1,0)
|
||||||
|
|
||||||
|
// text.substr(1,1)
|
||||||
|
b
|
||||||
|
// text.substr(1,2)
|
||||||
|
bc
|
||||||
|
// text.substr(1,3)
|
||||||
|
bcd
|
||||||
|
// text.substr(1,4)
|
||||||
|
bcd
|
||||||
|
// text.substr(2)
|
||||||
|
cd
|
||||||
|
// text.substr(2,-5)
|
||||||
|
|
||||||
|
// text.substr(2,-4)
|
||||||
|
|
||||||
|
// text.substr(2,-3)
|
||||||
|
c
|
||||||
|
// text.substr(2,-2)
|
||||||
|
|
||||||
|
// text.substr(2,-1)
|
||||||
|
|
||||||
|
// text.substr(2,0)
|
||||||
|
|
||||||
|
// text.substr(2,1)
|
||||||
|
c
|
||||||
|
// text.substr(2,2)
|
||||||
|
cd
|
||||||
|
// text.substr(2,3)
|
||||||
|
cd
|
||||||
|
// text.substr(2,4)
|
||||||
|
cd
|
||||||
|
// text.substr(3)
|
||||||
|
d
|
||||||
|
// text.substr(3,-5)
|
||||||
|
|
||||||
|
// text.substr(3,-4)
|
||||||
|
|
||||||
|
// text.substr(3,-3)
|
||||||
|
|
||||||
|
// text.substr(3,-2)
|
||||||
|
|
||||||
|
// text.substr(3,-1)
|
||||||
|
|
||||||
|
// text.substr(3,0)
|
||||||
|
|
||||||
|
// text.substr(3,1)
|
||||||
|
d
|
||||||
|
// text.substr(3,2)
|
||||||
|
d
|
||||||
|
// text.substr(3,3)
|
||||||
|
d
|
||||||
|
// text.substr(3,4)
|
||||||
|
d
|
||||||
|
// text.substr(4)
|
||||||
|
|
||||||
|
// text.substr(4,-5)
|
||||||
|
|
||||||
|
// text.substr(4,-4)
|
||||||
|
|
||||||
|
// text.substr(4,-3)
|
||||||
|
|
||||||
|
// text.substr(4,-2)
|
||||||
|
|
||||||
|
// text.substr(4,-1)
|
||||||
|
|
||||||
|
// text.substr(4,0)
|
||||||
|
|
||||||
|
// text.substr(4,1)
|
||||||
|
|
||||||
|
// text.substr(4,2)
|
||||||
|
|
||||||
|
// text.substr(4,3)
|
||||||
|
|
||||||
|
// text.substr(4,4)
|
||||||
|
|
Binary file not shown.
|
@ -1,21 +0,0 @@
|
||||||
// var str = hello world
|
|
||||||
// str.substr(0, -1)
|
|
||||||
hello worl
|
|
||||||
// str.substr(0, -4)
|
|
||||||
hello w
|
|
||||||
// str.substr(8, -4)
|
|
||||||
|
|
||||||
// str.substr(3, -3)
|
|
||||||
|
|
||||||
// str.substr(3, -4)
|
|
||||||
lo worl
|
|
||||||
// str.substr(3, -5)
|
|
||||||
lo wor
|
|
||||||
// str.substr(4, -4)
|
|
||||||
|
|
||||||
// str.substr(4, -5)
|
|
||||||
o worl
|
|
||||||
// str.substr(null, -1)
|
|
||||||
hello worl
|
|
||||||
// str.substr(undefined, -1)
|
|
||||||
hello worl
|
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue