avm2: Implement `Array.slice`.
This commit is contained in:
parent
685fbc12e0
commit
53b564bb52
|
@ -612,6 +612,59 @@ pub fn unshift<'gc>(
|
||||||
Ok(Value::Undefined)
|
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.
|
/// Construct `Array`'s class.
|
||||||
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
|
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
|
||||||
let class = Class::new(
|
let class = Class::new(
|
||||||
|
@ -707,5 +760,10 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
|
||||||
Method::from_builtin(unshift),
|
Method::from_builtin(unshift),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
class.write(mc).define_instance_trait(Trait::from_method(
|
||||||
|
QName::new(Namespace::public_namespace(), "slice"),
|
||||||
|
Method::from_builtin(slice),
|
||||||
|
));
|
||||||
|
|
||||||
class
|
class
|
||||||
}
|
}
|
||||||
|
|
|
@ -376,6 +376,7 @@ swf_tests! {
|
||||||
(as3_array_reverse, "avm2/array_reverse", 1),
|
(as3_array_reverse, "avm2/array_reverse", 1),
|
||||||
(as3_array_shift, "avm2/array_shift", 1),
|
(as3_array_shift, "avm2/array_shift", 1),
|
||||||
(as3_array_unshift, "avm2/array_unshift", 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.
|
// 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