avm2: Implement `removeChildAt`

This commit is contained in:
David Wendt 2020-11-10 22:12:18 -05:00 committed by Mike Welsh
parent c97ff2b024
commit 38fd29ae5f
5 changed files with 57 additions and 0 deletions

View File

@ -336,6 +336,40 @@ pub fn get_child_index<'gc>(
Err("ArgumentError: Child is not a child of this object".into())
}
/// Implements `DisplayObjectContainer.removeChildAt`
pub fn remove_child_at<'gc>(
activation: &mut Activation<'_, 'gc, '_>,
this: Option<Object<'gc>>,
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error> {
if let Some(parent) = this.and_then(|this| this.as_display_object()) {
if let Some(mut ctr) = parent.as_container() {
let target_child = args
.get(0)
.cloned()
.unwrap_or(Value::Undefined)
.coerce_to_i32(activation)?;
if target_child >= ctr.num_children() as i32 || target_child < 0 {
return Err(format!(
"RangeError: {} does not exist in the child list (valid range is 0 to {})",
target_child,
ctr.num_children()
)
.into());
}
let child = ctr.child_by_id(target_child as usize).unwrap();
ctr.remove_child(&mut activation.context, child);
return Ok(child.object2());
}
}
Ok(Value::Undefined)
}
/// Construct `DisplayObjectContainer`'s class.
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
let class = Class::new(
@ -383,6 +417,10 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
QName::new(Namespace::public_namespace(), "getChildIndex"),
Method::from_builtin(get_child_index),
));
write.define_instance_trait(Trait::from_method(
QName::new(Namespace::public_namespace(), "removeChildAt"),
Method::from_builtin(remove_child_at),
));
class
}

View File

@ -425,6 +425,7 @@ swf_tests! {
(as3_displayobjectcontainer_addchildat_timelinelock2, "avm2/displayobjectcontainer_addchildat_timelinelock2", 7),
(as3_displayobjectcontainer_contains, "avm2/displayobjectcontainer_contains", 5),
(as3_displayobjectcontainer_getchildindex, "avm2/displayobjectcontainer_getchildindex", 5),
(as3_displayobjectcontainer_removechildat, "avm2/displayobjectcontainer_removechildat", 1),
}
// TODO: These tests have some inaccuracies currently, so we use approx_eq to test that numeric values are close enough.

View File

@ -0,0 +1,18 @@
//var chx = this.getChildAt(0)
//var chy = this.getChildAt(1)
//var chz = this.getChildAt(2)
//this.removeChildAt(1)
//chx === this.getChildAt(0)
true
//chz === this.getChildAt(1)
true
//this.numChildren
2
//this.removeChildAt(0)
//chz === this.getChildAt(0)
true
//this.numChildren
1
//this.removeChildAt(0)
//this.numChildren
0