avm2: Add target property to XMLListObject
This commit is contained in:
parent
a3b95d9534
commit
4285d998dc
|
@ -2140,7 +2140,7 @@ impl<'a, 'gc> Activation<'a, 'gc> {
|
|||
) => {
|
||||
let mut children = value1.children().clone();
|
||||
children.push(E4XOrXml::Xml(value2));
|
||||
XmlListObject::new(self, children, None).into()
|
||||
XmlListObject::new(self, children, None, None).into()
|
||||
}
|
||||
(
|
||||
Value::Object(Object::XmlObject(value1)),
|
||||
|
@ -2148,14 +2148,14 @@ impl<'a, 'gc> Activation<'a, 'gc> {
|
|||
) => {
|
||||
let mut children = vec![E4XOrXml::Xml(value1)];
|
||||
children.extend(value2.children().clone());
|
||||
XmlListObject::new(self, children, None).into()
|
||||
XmlListObject::new(self, children, None, None).into()
|
||||
}
|
||||
(
|
||||
Value::Object(Object::XmlObject(value1)),
|
||||
Value::Object(Object::XmlObject(value2)),
|
||||
) => {
|
||||
let children = vec![E4XOrXml::Xml(value1), E4XOrXml::Xml(value2)];
|
||||
XmlListObject::new(self, children, None).into()
|
||||
XmlListObject::new(self, children, None, None).into()
|
||||
}
|
||||
(value1, value2) => {
|
||||
let prim_value1 = value1.coerce_to_primitive(None, self)?;
|
||||
|
|
|
@ -224,7 +224,7 @@ pub fn child<'gc>(
|
|||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
return Ok(XmlListObject::new(activation, children, None).into());
|
||||
return Ok(XmlListObject::new(activation, children, None, None).into());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -237,7 +237,8 @@ pub fn child<'gc>(
|
|||
Vec::new()
|
||||
};
|
||||
|
||||
Ok(XmlListObject::new(activation, children, Some(xml.into())).into())
|
||||
// FIXME: If name is not a number index, then we should call [[Get]] (get_property_local) with the name.
|
||||
Ok(XmlListObject::new(activation, children, Some(xml.into()), Some(multiname)).into())
|
||||
}
|
||||
|
||||
pub fn child_index<'gc>(
|
||||
|
@ -281,7 +282,14 @@ pub fn children<'gc>(
|
|||
Vec::new()
|
||||
};
|
||||
|
||||
Ok(XmlListObject::new(activation, children, Some(xml.into())).into())
|
||||
// FIXME: Spec says to just call [[Get]] with * (any multiname).
|
||||
Ok(XmlListObject::new(
|
||||
activation,
|
||||
children,
|
||||
Some(xml.into()),
|
||||
Some(Multiname::any(activation.gc())),
|
||||
)
|
||||
.into())
|
||||
}
|
||||
|
||||
pub fn copy<'gc>(
|
||||
|
@ -329,7 +337,7 @@ pub fn elements<'gc>(
|
|||
Vec::new()
|
||||
};
|
||||
|
||||
Ok(XmlListObject::new(activation, children, Some(xml.into())).into())
|
||||
Ok(XmlListObject::new(activation, children, Some(xml.into()), None).into())
|
||||
}
|
||||
|
||||
pub fn attributes<'gc>(
|
||||
|
@ -344,7 +352,14 @@ pub fn attributes<'gc>(
|
|||
Vec::new()
|
||||
};
|
||||
|
||||
Ok(XmlListObject::new(activation, attributes, Some(xml.into())).into())
|
||||
// FIXME: Spec/avmplus says to call [[Get]] with * attribute name (any attribute multiname).
|
||||
Ok(XmlListObject::new(
|
||||
activation,
|
||||
attributes,
|
||||
Some(xml.into()),
|
||||
Some(Multiname::any_attribute(activation.gc())),
|
||||
)
|
||||
.into())
|
||||
}
|
||||
|
||||
pub fn attribute<'gc>(
|
||||
|
@ -364,7 +379,8 @@ pub fn attribute<'gc>(
|
|||
Vec::new()
|
||||
};
|
||||
|
||||
Ok(XmlListObject::new(activation, attributes, Some(xml.into())).into())
|
||||
// FIXME: Spec/avmplus call [[Get]] with attribute name.
|
||||
Ok(XmlListObject::new(activation, attributes, Some(xml.into()), Some(multiname)).into())
|
||||
}
|
||||
|
||||
pub fn call_handler<'gc>(
|
||||
|
@ -510,9 +526,10 @@ pub fn descendants<'gc>(
|
|||
let multiname = name_to_multiname(activation, &args[0], false)?;
|
||||
let mut descendants = Vec::new();
|
||||
xml.node().descendants(&multiname, &mut descendants);
|
||||
Ok(XmlListObject::new(activation, descendants, Some(xml.into())).into())
|
||||
Ok(XmlListObject::new(activation, descendants, None, None).into())
|
||||
}
|
||||
|
||||
// ECMA-357 13.4.4.37 XML.prototype.text ( )
|
||||
pub fn text<'gc>(
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
this: Object<'gc>,
|
||||
|
@ -528,7 +545,9 @@ pub fn text<'gc>(
|
|||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
Ok(XmlListObject::new(activation, nodes, Some(xml.into())).into())
|
||||
// 1. Let list be a new XMLList with list.[[TargetObject]] = x and list.[[TargetProperty]] = null
|
||||
// 3. Return list
|
||||
Ok(XmlListObject::new(activation, nodes, Some(xml.into()), None).into())
|
||||
}
|
||||
|
||||
pub fn length<'gc>(
|
||||
|
@ -559,6 +578,7 @@ pub fn has_simple_content<'gc>(
|
|||
Ok(result.into())
|
||||
}
|
||||
|
||||
// ECMA-357 13.4.4.9 XML.prototype.comments ( )
|
||||
pub fn comments<'gc>(
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
this: Object<'gc>,
|
||||
|
@ -575,9 +595,12 @@ pub fn comments<'gc>(
|
|||
Vec::new()
|
||||
};
|
||||
|
||||
Ok(XmlListObject::new(activation, comments, Some(xml.into())).into())
|
||||
// 1. Let list be a new XMLList with list.[[TargetObject]] = x and list.[[TargetProperty]] = null
|
||||
// 3. Return list
|
||||
Ok(XmlListObject::new(activation, comments, Some(xml.into()), None).into())
|
||||
}
|
||||
|
||||
// ECMA-357 13.4.4.28 XML.prototype.processingInstructions ( [ name ] )
|
||||
pub fn processing_instructions<'gc>(
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
this: Object<'gc>,
|
||||
|
@ -598,7 +621,9 @@ pub fn processing_instructions<'gc>(
|
|||
Vec::new()
|
||||
};
|
||||
|
||||
Ok(XmlListObject::new(activation, nodes, Some(xml.into())).into())
|
||||
// 3. Let list = a new XMLList with list.[[TargetObject]] = x and list.[[TargetProperty]] = null
|
||||
// 5. Return list
|
||||
Ok(XmlListObject::new(activation, nodes, Some(xml.into()), None).into())
|
||||
}
|
||||
|
||||
// ECMA-357 13.4.4.18 XML.prototype.insertChildAfter (child1, child2)
|
||||
|
|
|
@ -6,6 +6,7 @@ pub use crate::avm2::object::xml_list_allocator;
|
|||
use crate::avm2::{
|
||||
e4x::{name_to_multiname, simple_content_to_string, E4XNode, E4XNodeKind},
|
||||
error::type_error,
|
||||
multiname::Multiname,
|
||||
object::{E4XOrXml, XmlListObject},
|
||||
parameters::ParametersExt,
|
||||
string::AvmString,
|
||||
|
@ -176,7 +177,7 @@ pub fn child<'gc>(
|
|||
);
|
||||
}
|
||||
}
|
||||
Ok(XmlListObject::new(activation, sub_children, Some(list.into())).into())
|
||||
Ok(XmlListObject::new(activation, sub_children, Some(list.into()), None).into())
|
||||
}
|
||||
|
||||
pub fn children<'gc>(
|
||||
|
@ -192,7 +193,14 @@ pub fn children<'gc>(
|
|||
sub_children.extend(children.iter().map(|node| E4XOrXml::E4X(*node)));
|
||||
}
|
||||
}
|
||||
Ok(XmlListObject::new(activation, sub_children, Some(list.into())).into())
|
||||
// FIXME: This method should just call get_property_local with "*".
|
||||
Ok(XmlListObject::new(
|
||||
activation,
|
||||
sub_children,
|
||||
Some(list.into()),
|
||||
Some(Multiname::any(activation.gc())),
|
||||
)
|
||||
.into())
|
||||
}
|
||||
|
||||
pub fn copy<'gc>(
|
||||
|
@ -227,7 +235,9 @@ pub fn attribute<'gc>(
|
|||
}
|
||||
}
|
||||
}
|
||||
Ok(XmlListObject::new(activation, sub_children, Some(list.into())).into())
|
||||
|
||||
// FIXME: This should just use get_property_local with an attribute Multiname.
|
||||
Ok(XmlListObject::new(activation, sub_children, Some(list.into()), Some(multiname)).into())
|
||||
}
|
||||
|
||||
pub fn attributes<'gc>(
|
||||
|
@ -244,7 +254,14 @@ pub fn attributes<'gc>(
|
|||
}
|
||||
}
|
||||
|
||||
Ok(XmlListObject::new(activation, child_attrs, Some(list.into())).into())
|
||||
// FIXME: This should just use get_property_local with an any attribute Multiname.
|
||||
Ok(XmlListObject::new(
|
||||
activation,
|
||||
child_attrs,
|
||||
Some(list.into()),
|
||||
Some(Multiname::any_attribute(activation.gc())),
|
||||
)
|
||||
.into())
|
||||
}
|
||||
|
||||
pub fn name<'gc>(
|
||||
|
@ -299,7 +316,7 @@ pub fn text<'gc>(
|
|||
);
|
||||
}
|
||||
}
|
||||
Ok(XmlListObject::new(activation, nodes, Some(xml_list.into())).into())
|
||||
Ok(XmlListObject::new(activation, nodes, Some(xml_list.into()), None).into())
|
||||
}
|
||||
|
||||
pub fn comments<'gc>(
|
||||
|
@ -319,7 +336,7 @@ pub fn comments<'gc>(
|
|||
);
|
||||
}
|
||||
}
|
||||
Ok(XmlListObject::new(activation, nodes, Some(xml_list.into())).into())
|
||||
Ok(XmlListObject::new(activation, nodes, Some(xml_list.into()), None).into())
|
||||
}
|
||||
|
||||
pub fn processing_instructions<'gc>(
|
||||
|
@ -344,5 +361,5 @@ pub fn processing_instructions<'gc>(
|
|||
}
|
||||
}
|
||||
|
||||
Ok(XmlListObject::new(activation, nodes, Some(xml_list.into())).into())
|
||||
Ok(XmlListObject::new(activation, nodes, Some(xml_list.into()), None).into())
|
||||
}
|
||||
|
|
|
@ -310,6 +310,16 @@ impl<'gc> Multiname<'gc> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Indicates the any attribute type (any attribute in any namespace).
|
||||
pub fn any_attribute(mc: &Mutation<'gc>) -> Self {
|
||||
Self {
|
||||
ns: NamespaceSet::single(Namespace::any(mc)),
|
||||
name: None,
|
||||
param: None,
|
||||
flags: MultinameFlags::ATTRIBUTE,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(ns: Namespace<'gc>, name: impl Into<AvmString<'gc>>) -> Self {
|
||||
Self {
|
||||
ns: NamespaceSet::single(ns),
|
||||
|
|
|
@ -26,7 +26,8 @@ pub fn xml_list_allocator<'gc>(
|
|||
children: Vec::new(),
|
||||
// An XMLList created by 'new XMLList()' is not linked
|
||||
// to any object
|
||||
target: None,
|
||||
target_object: None,
|
||||
target_property: None,
|
||||
},
|
||||
))
|
||||
.into())
|
||||
|
@ -52,7 +53,8 @@ impl<'gc> XmlListObject<'gc> {
|
|||
pub fn new(
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
children: Vec<E4XOrXml<'gc>>,
|
||||
target: Option<Object<'gc>>,
|
||||
target_object: Option<Object<'gc>>,
|
||||
target_property: Option<Multiname<'gc>>,
|
||||
) -> Self {
|
||||
let base = ScriptObjectData::new(activation.context.avm2.classes().xml_list);
|
||||
XmlListObject(GcCell::new(
|
||||
|
@ -60,7 +62,8 @@ impl<'gc> XmlListObject<'gc> {
|
|||
XmlListObjectData {
|
||||
base,
|
||||
children,
|
||||
target,
|
||||
target_object,
|
||||
target_property,
|
||||
},
|
||||
))
|
||||
}
|
||||
|
@ -94,8 +97,12 @@ impl<'gc> XmlListObject<'gc> {
|
|||
self.0.write(mc).children = children;
|
||||
}
|
||||
|
||||
pub fn target(&self) -> Option<Object<'gc>> {
|
||||
self.0.read().target
|
||||
pub fn target_object(&self) -> Option<Object<'gc>> {
|
||||
self.0.read().target_object
|
||||
}
|
||||
|
||||
pub fn target_property(&self) -> Option<Multiname<'gc>> {
|
||||
self.0.read().target_property.clone()
|
||||
}
|
||||
|
||||
pub fn deep_copy(&self, activation: &mut Activation<'_, 'gc>) -> XmlListObject<'gc> {
|
||||
|
@ -104,7 +111,12 @@ impl<'gc> XmlListObject<'gc> {
|
|||
.iter()
|
||||
.map(|child| E4XOrXml::E4X(child.node().deep_copy(activation.context.gc_context)))
|
||||
.collect();
|
||||
XmlListObject::new(activation, children, self.target())
|
||||
XmlListObject::new(
|
||||
activation,
|
||||
children,
|
||||
self.target_object(),
|
||||
self.target_property(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn equals(
|
||||
|
@ -160,7 +172,7 @@ impl<'gc> XmlListObject<'gc> {
|
|||
let mut out = vec![];
|
||||
out.extend(left.children().clone());
|
||||
out.extend(right.children().clone());
|
||||
Self::new(activation, out, None)
|
||||
Self::new(activation, out, None, None)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -177,7 +189,9 @@ pub struct XmlListObjectData<'gc> {
|
|||
/// The XML or XMLList object that this list was created from.
|
||||
/// If `Some`, then modifications to this list are reflected
|
||||
/// in the original object.
|
||||
target: Option<Object<'gc>>,
|
||||
target_object: Option<Object<'gc>>,
|
||||
|
||||
target_property: Option<Multiname<'gc>>,
|
||||
}
|
||||
|
||||
/// Holds either an `E4XNode` or an `XmlObject`. This can be converted
|
||||
|
@ -260,11 +274,7 @@ impl<'gc> TObject<'gc> for XmlListObject<'gc> {
|
|||
for child in self.0.read().children.iter() {
|
||||
child.node().descendants(multiname, &mut descendants);
|
||||
}
|
||||
Some(XmlListObject::new(
|
||||
activation,
|
||||
descendants,
|
||||
Some((*self).into()),
|
||||
))
|
||||
Some(XmlListObject::new(activation, descendants, None, None))
|
||||
}
|
||||
|
||||
fn get_property_local(
|
||||
|
@ -309,7 +319,13 @@ impl<'gc> TObject<'gc> for XmlListObject<'gc> {
|
|||
})
|
||||
.collect();
|
||||
|
||||
Ok(XmlListObject::new(activation, matched_children, Some(self.into())).into())
|
||||
Ok(XmlListObject::new(
|
||||
activation,
|
||||
matched_children,
|
||||
Some(self.into()),
|
||||
Some(name.clone()),
|
||||
)
|
||||
.into())
|
||||
}
|
||||
|
||||
fn call_property_local(
|
||||
|
@ -377,7 +393,7 @@ impl<'gc> TObject<'gc> for XmlListObject<'gc> {
|
|||
if let Some(local_name) = name.local_name() {
|
||||
if let Ok(index) = local_name.parse::<usize>() {
|
||||
// 2.a. If x.[[TargetObject]] is not null
|
||||
if let Some(target) = write.target {
|
||||
if let Some(target) = write.target_object {
|
||||
return Err(format!(
|
||||
"Modifying an XMLList object is not yet implemented: target {:?}",
|
||||
target
|
||||
|
|
|
@ -183,11 +183,7 @@ impl<'gc> TObject<'gc> for XmlObject<'gc> {
|
|||
) -> Option<XmlListObject<'gc>> {
|
||||
let mut descendants = Vec::new();
|
||||
self.0.read().node.descendants(multiname, &mut descendants);
|
||||
Some(XmlListObject::new(
|
||||
activation,
|
||||
descendants,
|
||||
Some((*self).into()),
|
||||
))
|
||||
Some(XmlListObject::new(activation, descendants, None, None))
|
||||
}
|
||||
|
||||
fn get_property_local(
|
||||
|
@ -236,7 +232,13 @@ impl<'gc> TObject<'gc> for XmlObject<'gc> {
|
|||
Vec::new()
|
||||
};
|
||||
|
||||
return Ok(XmlListObject::new(activation, matched_children, Some(self.into())).into());
|
||||
return Ok(XmlListObject::new(
|
||||
activation,
|
||||
matched_children,
|
||||
Some(self.into()),
|
||||
Some(name.clone()),
|
||||
)
|
||||
.into());
|
||||
}
|
||||
|
||||
fn call_property_local(
|
||||
|
|
Loading…
Reference in New Issue