avm2: Implement `Array.slice`.
This commit is contained in:
parent
685fbc12e0
commit
53b564bb52
|
@ -612,6 +612,59 @@ pub fn unshift<'gc>(
|
|||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
/// Implements `Array.slice`
|
||||
pub fn slice<'gc>(
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
this: Option<Object<'gc>>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error> {
|
||||
if let Some(this) = this {
|
||||
let array_length = this.as_array_storage().map(|a| a.length());
|
||||
|
||||
if let Some(array_length) = array_length {
|
||||
let start = args
|
||||
.get(0)
|
||||
.cloned()
|
||||
.unwrap_or_else(|| 0.into())
|
||||
.coerce_to_i32(activation)?;
|
||||
let end = args
|
||||
.get(1)
|
||||
.cloned()
|
||||
.unwrap_or_else(|| 0xFFFFFF.into())
|
||||
.coerce_to_i32(activation)?;
|
||||
|
||||
let actual_start = if start < 0 {
|
||||
(array_length as isize).saturating_add(start as isize) as usize
|
||||
} else {
|
||||
start as usize
|
||||
};
|
||||
let actual_end = if end < 0 {
|
||||
(array_length as isize).saturating_add(end as isize) as usize
|
||||
} else {
|
||||
end as usize
|
||||
};
|
||||
|
||||
let mut new_array = ArrayStorage::new(0);
|
||||
for i in actual_start..actual_end {
|
||||
if i >= array_length {
|
||||
break;
|
||||
}
|
||||
|
||||
new_array.push(resolve_array_hole(
|
||||
activation,
|
||||
this,
|
||||
i,
|
||||
this.as_array_storage().unwrap().get(i),
|
||||
)?);
|
||||
}
|
||||
|
||||
return build_array(activation, new_array);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
/// Construct `Array`'s class.
|
||||
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
|
||||
let class = Class::new(
|
||||
|
@ -707,5 +760,10 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
|
|||
Method::from_builtin(unshift),
|
||||
));
|
||||
|
||||
class.write(mc).define_instance_trait(Trait::from_method(
|
||||
QName::new(Namespace::public_namespace(), "slice"),
|
||||
Method::from_builtin(slice),
|
||||
));
|
||||
|
||||
class
|
||||
}
|
||||
|
|
|
@ -376,6 +376,7 @@ swf_tests! {
|
|||
(as3_array_reverse, "avm2/array_reverse", 1),
|
||||
(as3_array_shift, "avm2/array_shift", 1),
|
||||
(as3_array_unshift, "avm2/array_unshift", 1),
|
||||
(as3_array_slice, "avm2/array_slice", 1),
|
||||
}
|
||||
|
||||
// TODO: These tests have some inaccuracies currently, so we use approx_eq to test that numeric values are close enough.
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
package {
|
||||
public class Test {
|
||||
}
|
||||
}
|
||||
|
||||
function assert_array(a) {
|
||||
for (var i = 0; i < a.length; i += 1) {
|
||||
trace(a[i]);
|
||||
}
|
||||
}
|
||||
|
||||
trace("//var a = new Array(8)");
|
||||
var a = new Array(8);
|
||||
|
||||
trace("//Array.prototype[0] = 999");
|
||||
Array.prototype[0] = 999;
|
||||
|
||||
trace("//Array.prototype[1] = 998");
|
||||
Array.prototype[1] = 998;
|
||||
|
||||
trace("//a[2] = 2");
|
||||
a[2] = 2;
|
||||
|
||||
trace("//Array.prototype[3] = 997");
|
||||
Array.prototype[3] = 997;
|
||||
|
||||
trace("//a[4] = 4");
|
||||
a[4] = 4;
|
||||
|
||||
trace("//Array.prototype[5] = 996");
|
||||
Array.prototype[5] = 996;
|
||||
|
||||
trace("//a[6] = 6");
|
||||
a[6] = 6;
|
||||
|
||||
trace("//Array.prototype[7] = 995");
|
||||
Array.prototype[7] = 995;
|
||||
|
||||
trace("//var b = a.slice();");
|
||||
var b = a.slice();
|
||||
|
||||
trace("//(contents of b)");
|
||||
assert_array(b);
|
||||
|
||||
trace("//var c = a.slice(0, 3);");
|
||||
var c = a.slice(0, 3);
|
||||
|
||||
trace("//(contents of c)");
|
||||
assert_array(c);
|
||||
|
||||
trace("//var d = a.slice(-1, 3);");
|
||||
var d = a.slice(-1, 3);
|
||||
|
||||
trace("//(contents of d)");
|
||||
assert_array(d);
|
||||
|
||||
trace("//var e = a.slice(0, 3);");
|
||||
var e = a.slice(0, -3);
|
||||
|
||||
trace("//(contents of e)");
|
||||
assert_array(e);
|
||||
|
||||
trace("//var f = a.slice(-1, -3);");
|
||||
var f = a.slice(-1, -3);
|
||||
|
||||
trace("//(contents of f)");
|
||||
assert_array(f);
|
||||
|
||||
trace("//var g = a.slice(-3, -1);");
|
||||
var g = a.slice(-3, -1);
|
||||
|
||||
trace("//(contents of g)");
|
||||
assert_array(g);
|
|
@ -0,0 +1,39 @@
|
|||
//var a = new Array(8)
|
||||
//Array.prototype[0] = 999
|
||||
//Array.prototype[1] = 998
|
||||
//a[2] = 2
|
||||
//Array.prototype[3] = 997
|
||||
//a[4] = 4
|
||||
//Array.prototype[5] = 996
|
||||
//a[6] = 6
|
||||
//Array.prototype[7] = 995
|
||||
//var b = a.slice();
|
||||
//(contents of b)
|
||||
999
|
||||
998
|
||||
2
|
||||
997
|
||||
4
|
||||
996
|
||||
6
|
||||
995
|
||||
//var c = a.slice(0, 3);
|
||||
//(contents of c)
|
||||
999
|
||||
998
|
||||
2
|
||||
//var d = a.slice(-1, 3);
|
||||
//(contents of d)
|
||||
//var e = a.slice(0, 3);
|
||||
//(contents of e)
|
||||
999
|
||||
998
|
||||
2
|
||||
997
|
||||
4
|
||||
//var f = a.slice(-1, -3);
|
||||
//(contents of f)
|
||||
//var g = a.slice(-3, -1);
|
||||
//(contents of g)
|
||||
996
|
||||
6
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue