Implement `setPropertyIsEnumerable`
This commit is contained in:
parent
dc0cb00a03
commit
f13e2ea3c4
|
@ -575,6 +575,18 @@ impl<'gc> TObject<'gc> for FunctionObject<'gc> {
|
||||||
self.0.read().base.property_is_enumerable(name)
|
self.0.read().base.property_is_enumerable(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_local_property_is_enumerable(
|
||||||
|
&self,
|
||||||
|
mc: MutationContext<'gc, '_>,
|
||||||
|
name: &QName,
|
||||||
|
is_enumerable: bool,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
self.0
|
||||||
|
.write(mc)
|
||||||
|
.base
|
||||||
|
.set_local_property_is_enumerable(name, is_enumerable)
|
||||||
|
}
|
||||||
|
|
||||||
fn as_ptr(&self) -> *const ObjectPtr {
|
fn as_ptr(&self) -> *const ObjectPtr {
|
||||||
self.0.as_ptr() as *const ObjectPtr
|
self.0.as_ptr() as *const ObjectPtr
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,6 +86,33 @@ pub fn property_is_enumerable<'gc>(
|
||||||
Ok(false.into())
|
Ok(false.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `Object.prototype.setPropertyIsEnumerable`
|
||||||
|
pub fn set_property_is_enumerable<'gc>(
|
||||||
|
_avm: &mut Avm2<'gc>,
|
||||||
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
|
this: Option<Object<'gc>>,
|
||||||
|
args: &[Value<'gc>],
|
||||||
|
) -> Result<ReturnValue<'gc>, Error> {
|
||||||
|
let this: Result<Object<'gc>, Error> = this.ok_or_else(|| "No valid this parameter".into());
|
||||||
|
let this = this?;
|
||||||
|
let name: Result<&Value<'gc>, Error> = args.get(0).ok_or_else(|| "No name specified".into());
|
||||||
|
let name = name?.as_string()?;
|
||||||
|
let is_enum = args
|
||||||
|
.get(1)
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or(Value::Bool(true))
|
||||||
|
.as_bool()?;
|
||||||
|
|
||||||
|
if let Some(ns) = this.resolve_any(&name)? {
|
||||||
|
if !ns.is_private() {
|
||||||
|
let qname = QName::new(ns, &name);
|
||||||
|
this.set_local_property_is_enumerable(context.gc_context, &qname, is_enum)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Value::Undefined.into())
|
||||||
|
}
|
||||||
|
|
||||||
/// Partially construct `Object.prototype`.
|
/// Partially construct `Object.prototype`.
|
||||||
///
|
///
|
||||||
/// `__proto__` and other cross-linked properties of this object will *not*
|
/// `__proto__` and other cross-linked properties of this object will *not*
|
||||||
|
@ -118,4 +145,10 @@ pub fn fill_proto<'gc>(
|
||||||
0,
|
0,
|
||||||
FunctionObject::from_builtin(gc_context, property_is_enumerable, fn_proto),
|
FunctionObject::from_builtin(gc_context, property_is_enumerable, fn_proto),
|
||||||
);
|
);
|
||||||
|
object_proto.install_method(
|
||||||
|
gc_context,
|
||||||
|
QName::new(Namespace::public_namespace(), "setPropertyIsEnumerable"),
|
||||||
|
0,
|
||||||
|
FunctionObject::from_builtin(gc_context, set_property_is_enumerable, fn_proto),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -357,6 +357,14 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
||||||
/// Properties that do not exist are also not enumerable.
|
/// Properties that do not exist are also not enumerable.
|
||||||
fn property_is_enumerable(&self, name: &QName) -> bool;
|
fn property_is_enumerable(&self, name: &QName) -> bool;
|
||||||
|
|
||||||
|
/// Mark a dynamic property on this object as enumerable.
|
||||||
|
fn set_local_property_is_enumerable(
|
||||||
|
&self,
|
||||||
|
mc: MutationContext<'gc, '_>,
|
||||||
|
name: &QName,
|
||||||
|
is_enumerable: bool,
|
||||||
|
) -> Result<(), Error>;
|
||||||
|
|
||||||
/// Install a method (or any other non-slot value) on an object.
|
/// Install a method (or any other non-slot value) on an object.
|
||||||
fn install_method(
|
fn install_method(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
|
@ -206,6 +206,17 @@ impl<'gc> TObject<'gc> for ScriptObject<'gc> {
|
||||||
self.0.read().property_is_enumerable(name)
|
self.0.read().property_is_enumerable(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_local_property_is_enumerable(
|
||||||
|
&self,
|
||||||
|
mc: MutationContext<'gc, '_>,
|
||||||
|
name: &QName,
|
||||||
|
is_enumerable: bool,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
self.0
|
||||||
|
.write(mc)
|
||||||
|
.set_local_property_is_enumerable(name, is_enumerable)
|
||||||
|
}
|
||||||
|
|
||||||
fn as_ptr(&self) -> *const ObjectPtr {
|
fn as_ptr(&self) -> *const ObjectPtr {
|
||||||
self.0.as_ptr() as *const ObjectPtr
|
self.0.as_ptr() as *const ObjectPtr
|
||||||
}
|
}
|
||||||
|
@ -758,6 +769,34 @@ impl<'gc> ScriptObjectData<'gc> {
|
||||||
self.enumerants.contains(name)
|
self.enumerants.contains(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_local_property_is_enumerable(
|
||||||
|
&mut self,
|
||||||
|
name: &QName,
|
||||||
|
is_enumerable: bool,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
if is_enumerable && self.values.contains_key(name) && !self.enumerants.contains(name) {
|
||||||
|
// Traits are never enumerable
|
||||||
|
if self.has_trait(name)? {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
self.enumerants.push(name.clone());
|
||||||
|
} else if !is_enumerable && self.enumerants.contains(name) {
|
||||||
|
let mut index = None;
|
||||||
|
for (i, other_name) in self.enumerants.iter().enumerate() {
|
||||||
|
if other_name == name {
|
||||||
|
index = Some(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(index) = index {
|
||||||
|
self.enumerants.remove(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Install a method into the object.
|
/// Install a method into the object.
|
||||||
pub fn install_method(&mut self, name: QName, disp_id: u32, function: Object<'gc>) {
|
pub fn install_method(&mut self, name: QName, disp_id: u32, function: Object<'gc>) {
|
||||||
if disp_id > 0 {
|
if disp_id > 0 {
|
||||||
|
|
Loading…
Reference in New Issue