avm2: Make `get_property`, `set_property`, `init_property`, and various other derivative methods take a `Multiname` and run the search inside `Object`.
This also introduces a `call_property` method.
This commit is contained in:
parent
945cb2c4bf
commit
b07ad8070c
|
@ -420,7 +420,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
|||
if method.method().needs_arguments_object {
|
||||
args_object.set_property(
|
||||
args_object,
|
||||
&QName::new(Namespace::public(), "callee"),
|
||||
&QName::new(Namespace::public(), "callee").into(),
|
||||
callee.into(),
|
||||
&mut activation,
|
||||
)?;
|
||||
|
@ -1103,19 +1103,8 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
|||
let args = self.context.avm2.pop_args(arg_count);
|
||||
let multiname = self.pool_multiname(method, index)?;
|
||||
let receiver = self.context.avm2.pop().coerce_to_object(self)?;
|
||||
let name: Result<QName, Error> = receiver
|
||||
.resolve_multiname(&multiname)?
|
||||
.ok_or_else(|| format!("Could not find method {:?}", multiname.local_name()).into());
|
||||
let name = name?;
|
||||
let superclass_object = if let Some(c) = receiver.instance_of() {
|
||||
c.find_class_for_trait(&name)?
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let function = receiver
|
||||
.get_property(receiver, &name, self)?
|
||||
.coerce_to_object(self)?;
|
||||
let value = function.call(Some(receiver), &args, self, superclass_object)?;
|
||||
|
||||
let value = receiver.call_property(&multiname, &args, self)?;
|
||||
|
||||
self.context.avm2.push(value);
|
||||
|
||||
|
@ -1131,11 +1120,8 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
|||
let args = self.context.avm2.pop_args(arg_count);
|
||||
let multiname = self.pool_multiname(method, index)?;
|
||||
let receiver = self.context.avm2.pop().coerce_to_object(self)?;
|
||||
let name: Result<QName, Error> = receiver
|
||||
.resolve_multiname(&multiname)?
|
||||
.ok_or_else(|| format!("Could not find method {:?}", multiname.local_name()).into());
|
||||
let function = receiver
|
||||
.get_property(receiver, &name?, self)?
|
||||
.get_property(receiver, &multiname, self)?
|
||||
.coerce_to_object(self)?;
|
||||
let value = function.call(None, &args, self, None)?;
|
||||
|
||||
|
@ -1153,20 +1139,8 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
|||
let args = self.context.avm2.pop_args(arg_count);
|
||||
let multiname = self.pool_multiname(method, index)?;
|
||||
let receiver = self.context.avm2.pop().coerce_to_object(self)?;
|
||||
let name: Result<QName, Error> = receiver
|
||||
.resolve_multiname(&multiname)?
|
||||
.ok_or_else(|| format!("Could not find method {:?}", multiname.local_name()).into());
|
||||
let name = name?;
|
||||
let superclass_object = if let Some(c) = receiver.instance_of() {
|
||||
c.find_class_for_trait(&name)?
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let function = receiver
|
||||
.get_property(receiver, &name, self)?
|
||||
.coerce_to_object(self)?;
|
||||
|
||||
function.call(Some(receiver), &args, self, superclass_object)?;
|
||||
receiver.call_property(&multiname, &args, self)?;
|
||||
|
||||
Ok(FrameControl::Continue)
|
||||
}
|
||||
|
@ -1199,11 +1173,6 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
|||
let multiname = self.pool_multiname(method, index)?;
|
||||
let receiver = self.context.avm2.pop().coerce_to_object(self)?;
|
||||
|
||||
let name: Result<QName, Error> = receiver
|
||||
.resolve_multiname(&multiname)?
|
||||
.ok_or_else(|| format!("Could not find method {:?}", multiname.local_name()).into());
|
||||
let name = name?;
|
||||
|
||||
let superclass_object: Result<Object<'gc>, Error> = self
|
||||
.subclass_object()
|
||||
.and_then(|c| c.as_class_object())
|
||||
|
@ -1215,7 +1184,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
|||
});
|
||||
let superclass_object = superclass_object?;
|
||||
|
||||
let value = superclass_object.supercall_method(&name, Some(receiver), &args, self)?;
|
||||
let value = superclass_object.call_super(&multiname, receiver, &args, self)?;
|
||||
|
||||
self.context.avm2.push(value);
|
||||
|
||||
|
@ -1232,11 +1201,6 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
|||
let multiname = self.pool_multiname(method, index)?;
|
||||
let receiver = self.context.avm2.pop().coerce_to_object(self)?;
|
||||
|
||||
let name: Result<QName, Error> = receiver
|
||||
.resolve_multiname(&multiname)?
|
||||
.ok_or_else(|| format!("Could not find method {:?}", multiname.local_name()).into());
|
||||
let name = name?;
|
||||
|
||||
let superclass_object: Result<Object<'gc>, Error> = self
|
||||
.subclass_object()
|
||||
.and_then(|c| c.as_class_object())
|
||||
|
@ -1248,7 +1212,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
|||
});
|
||||
let superclass_object = superclass_object?;
|
||||
|
||||
superclass_object.supercall_method(&name, Some(receiver), &args, self)?;
|
||||
superclass_object.call_super(&multiname, receiver, &args, self)?;
|
||||
|
||||
Ok(FrameControl::Continue)
|
||||
}
|
||||
|
@ -1271,23 +1235,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
|||
let multiname = self.pool_multiname(method, index)?;
|
||||
let object = self.context.avm2.pop().coerce_to_object(self)?;
|
||||
|
||||
let name: Result<QName, Error> = object.resolve_multiname(&multiname)?.ok_or_else(|| {
|
||||
format!("Could not resolve property {:?}", multiname.local_name()).into()
|
||||
});
|
||||
|
||||
// Special case for dynamic properties as scripts may attempt to get
|
||||
// dynamic properties not yet set
|
||||
if name.is_err()
|
||||
&& !object
|
||||
.instance_of_class_definition()
|
||||
.map(|c| c.read().is_sealed())
|
||||
.unwrap_or(false)
|
||||
{
|
||||
self.context.avm2.push(Value::Undefined);
|
||||
return Ok(FrameControl::Continue);
|
||||
}
|
||||
|
||||
let value = object.get_property(object, &name?, self)?;
|
||||
let value = object.get_property(object, &multiname, self)?;
|
||||
self.context.avm2.push(value);
|
||||
|
||||
Ok(FrameControl::Continue)
|
||||
|
@ -1302,17 +1250,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
|||
let multiname = self.pool_multiname(method, index)?;
|
||||
let mut object = self.context.avm2.pop().coerce_to_object(self)?;
|
||||
|
||||
if let Some(name) = object.resolve_multiname(&multiname)? {
|
||||
object.set_property(object, &name, value, self)?;
|
||||
} else {
|
||||
//TODO: Non-dynamic objects should fail
|
||||
//TODO: This should only work if the public namespace is present
|
||||
let local_name: Result<AvmString<'gc>, Error> = multiname
|
||||
.local_name()
|
||||
.ok_or_else(|| "Cannot set property using any name".into());
|
||||
let name = QName::dynamic_name(local_name?);
|
||||
object.set_property(object, &name, value, self)?;
|
||||
}
|
||||
object.set_property(object, &multiname, value, self)?;
|
||||
|
||||
Ok(FrameControl::Continue)
|
||||
}
|
||||
|
@ -1326,17 +1264,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
|||
let multiname = self.pool_multiname(method, index)?;
|
||||
let mut object = self.context.avm2.pop().coerce_to_object(self)?;
|
||||
|
||||
if let Some(name) = object.resolve_multiname(&multiname)? {
|
||||
object.init_property(object, &name, value, self)?;
|
||||
} else {
|
||||
//TODO: Non-dynamic objects should fail
|
||||
//TODO: This should only work if the public namespace is present
|
||||
let local_name: Result<AvmString<'gc>, Error> = multiname
|
||||
.local_name()
|
||||
.ok_or_else(|| "Cannot set property using any name".into());
|
||||
let name = QName::dynamic_name(local_name?);
|
||||
object.init_property(object, &name, value, self)?;
|
||||
}
|
||||
object.init_property(object, &multiname, value, self)?;
|
||||
|
||||
Ok(FrameControl::Continue)
|
||||
}
|
||||
|
@ -1374,11 +1302,6 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
|||
let multiname = self.pool_multiname(method, index)?;
|
||||
let object = self.context.avm2.pop().coerce_to_object(self)?;
|
||||
|
||||
let name: Result<QName, Error> = object
|
||||
.resolve_multiname(&multiname)?
|
||||
.ok_or_else(|| format!("Could not find method {:?}", multiname.local_name()).into());
|
||||
let name = name?;
|
||||
|
||||
let superclass_object: Result<Object<'gc>, Error> = self
|
||||
.subclass_object()
|
||||
.and_then(|c| c.as_class_object())
|
||||
|
@ -1390,7 +1313,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
|||
});
|
||||
let superclass_object = superclass_object?;
|
||||
|
||||
let value = superclass_object.supercall_getter(&name, Some(object), self)?;
|
||||
let value = superclass_object.get_super(&multiname, object, self)?;
|
||||
|
||||
self.context.avm2.push(value);
|
||||
|
||||
|
@ -1406,11 +1329,6 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
|||
let multiname = self.pool_multiname(method, index)?;
|
||||
let object = self.context.avm2.pop().coerce_to_object(self)?;
|
||||
|
||||
let name: Result<QName, Error> = object
|
||||
.resolve_multiname(&multiname)?
|
||||
.ok_or_else(|| format!("Could not find method {:?}", multiname.local_name()).into());
|
||||
let name = name?;
|
||||
|
||||
let superclass_object: Result<Object<'gc>, Error> = self
|
||||
.subclass_object()
|
||||
.and_then(|c| c.as_class_object())
|
||||
|
@ -1422,7 +1340,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
|||
});
|
||||
let superclass_object = superclass_object?;
|
||||
|
||||
superclass_object.supercall_setter(&name, value, Some(object), self)?;
|
||||
superclass_object.set_super(&multiname, value, object, self)?;
|
||||
|
||||
Ok(FrameControl::Continue)
|
||||
}
|
||||
|
@ -1613,13 +1531,8 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
|||
let multiname = self.pool_multiname(method, index)?;
|
||||
let source = self.context.avm2.pop().coerce_to_object(self)?;
|
||||
|
||||
let ctor_name: Result<QName, Error> =
|
||||
source.resolve_multiname(&multiname)?.ok_or_else(|| {
|
||||
format!("Could not resolve property {:?}", multiname.local_name()).into()
|
||||
});
|
||||
let ctor_name = ctor_name?;
|
||||
let ctor = source
|
||||
.get_property(source, &ctor_name, self)?
|
||||
.get_property(source, &multiname, self)?
|
||||
.coerce_to_object(self)?;
|
||||
|
||||
let object = ctor.construct(self, &args)?;
|
||||
|
@ -1659,7 +1572,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
|||
|
||||
object.set_property(
|
||||
object,
|
||||
&QName::new(Namespace::public(), name.coerce_to_string(self)?),
|
||||
&QName::dynamic_name(name.coerce_to_string(self)?).into(),
|
||||
value,
|
||||
self,
|
||||
)?;
|
||||
|
@ -2488,7 +2401,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
|||
|
||||
let name = object.get_enumerant_name(cur_index as u32);
|
||||
let value = if let Some(name) = name {
|
||||
object.get_property(object, &name, self)?
|
||||
object.get_property(object, &name.into(), self)?
|
||||
} else {
|
||||
Value::Undefined
|
||||
};
|
||||
|
|
|
@ -145,7 +145,7 @@ impl<'gc> Domain<'gc> {
|
|||
.ok_or_else(|| format!("MovieClip Symbol {} does not exist", name.local_name()))?;
|
||||
let globals = script.globals(&mut activation.context)?;
|
||||
|
||||
globals.get_property(globals, &name, activation)
|
||||
globals.get_property(globals, &name.clone().into(), activation)
|
||||
}
|
||||
|
||||
/// Export a definition from a script into the current application domain.
|
||||
|
|
|
@ -374,7 +374,7 @@ pub fn dispatch_event_to_target<'gc>(
|
|||
let dispatch_list = target
|
||||
.get_property(
|
||||
target,
|
||||
&QName::new(Namespace::private(NS_EVENT_DISPATCHER), "dispatch_list"),
|
||||
&QName::new(Namespace::private(NS_EVENT_DISPATCHER), "dispatch_list").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_object(activation);
|
||||
|
@ -428,7 +428,7 @@ pub fn dispatch_event<'gc>(
|
|||
let target = this
|
||||
.get_property(
|
||||
this,
|
||||
&QName::new(Namespace::private(NS_EVENT_DISPATCHER), "target"),
|
||||
&QName::new(Namespace::private(NS_EVENT_DISPATCHER), "target").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_object(activation)
|
||||
|
|
|
@ -342,19 +342,13 @@ fn class<'gc>(
|
|||
|
||||
let class_read = class_def.read();
|
||||
let super_class = if let Some(sc_name) = class_read.super_class_name() {
|
||||
let super_name = global
|
||||
.resolve_multiname(sc_name)?
|
||||
.unwrap_or_else(|| QName::dynamic_name("Object"));
|
||||
|
||||
let super_class: Result<Object<'gc>, Error> = global
|
||||
.get_property(global, &super_name, activation)?
|
||||
.get_property(global, sc_name, activation)?
|
||||
.coerce_to_object(activation)
|
||||
.map_err(|_e| {
|
||||
format!(
|
||||
"Could not resolve superclass {:?} when defining global class {:?}",
|
||||
sc_name
|
||||
.local_name(activation)
|
||||
.unwrap_or_else(|_| Some("<uncoercible name>".into())),
|
||||
sc_name.local_name(),
|
||||
class_read.name().local_name()
|
||||
)
|
||||
.into()
|
||||
|
@ -382,7 +376,7 @@ fn class<'gc>(
|
|||
let proto = class_object
|
||||
.get_property(
|
||||
class_object,
|
||||
&QName::new(Namespace::public(), "prototype"),
|
||||
&QName::new(Namespace::public(), "prototype").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_object(activation)?;
|
||||
|
|
|
@ -136,7 +136,8 @@ pub fn resolve_array_hole<'gc>(
|
|||
&QName::new(
|
||||
Namespace::public(),
|
||||
AvmString::new(activation.context.gc_context, i.to_string()),
|
||||
),
|
||||
)
|
||||
.into(),
|
||||
activation,
|
||||
)
|
||||
})
|
||||
|
@ -217,7 +218,7 @@ pub fn to_locale_string<'gc>(
|
|||
|
||||
let tls = o.get_property(
|
||||
o,
|
||||
&QName::new(Namespace::public(), "toLocaleString"),
|
||||
&QName::new(Namespace::public(), "toLocaleString").into(),
|
||||
activation,
|
||||
)?;
|
||||
|
||||
|
@ -278,7 +279,7 @@ impl<'gc> ArrayIter<'gc> {
|
|||
let length = array_object
|
||||
.get_property(
|
||||
array_object,
|
||||
&QName::new(Namespace::public(), "length"),
|
||||
&QName::new(Namespace::public(), "length").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_u32(activation)?;
|
||||
|
@ -310,7 +311,8 @@ impl<'gc> ArrayIter<'gc> {
|
|||
&QName::new(
|
||||
Namespace::public(),
|
||||
AvmString::new(activation.context.gc_context, i.to_string()),
|
||||
),
|
||||
)
|
||||
.into(),
|
||||
activation,
|
||||
)
|
||||
.map(|val| (i, val)),
|
||||
|
@ -340,7 +342,8 @@ impl<'gc> ArrayIter<'gc> {
|
|||
&QName::new(
|
||||
Namespace::public(),
|
||||
AvmString::new(activation.context.gc_context, i.to_string()),
|
||||
),
|
||||
)
|
||||
.into(),
|
||||
activation,
|
||||
)
|
||||
.map(|val| (i, val)),
|
||||
|
@ -1208,14 +1211,14 @@ pub fn sort_on<'gc>(
|
|||
let a_object = a.coerce_to_object(activation)?;
|
||||
let a_field = a_object.get_property(
|
||||
a_object,
|
||||
&QName::new(Namespace::public(), *field_name),
|
||||
&QName::new(Namespace::public(), *field_name).into(),
|
||||
activation,
|
||||
)?;
|
||||
|
||||
let b_object = b.coerce_to_object(activation)?;
|
||||
let b_field = b_object.get_property(
|
||||
b_object,
|
||||
&QName::new(Namespace::public(), *field_name),
|
||||
&QName::new(Namespace::public(), *field_name).into(),
|
||||
activation,
|
||||
)?;
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ pub fn instance_init<'gc>(
|
|||
|
||||
this.set_property(
|
||||
this,
|
||||
&QName::new(Namespace::public(), "bitmapData"),
|
||||
&QName::new(Namespace::public(), "bitmapData").into(),
|
||||
bd_object.into(),
|
||||
activation,
|
||||
)?;
|
||||
|
|
|
@ -388,7 +388,7 @@ pub fn parameters<'gc>(
|
|||
let avm_v = AvmString::new(activation.context.gc_context, v);
|
||||
params_obj.set_property(
|
||||
params_obj,
|
||||
&QName::new(Namespace::public(), avm_k),
|
||||
&QName::new(Namespace::public(), avm_k).into(),
|
||||
avm_v.into(),
|
||||
activation,
|
||||
)?;
|
||||
|
|
|
@ -58,14 +58,14 @@ pub fn graphics<'gc>(
|
|||
// Lazily initialize the `Graphics` object in a hidden property.
|
||||
let graphics = match this.get_property(
|
||||
this,
|
||||
&QName::new(Namespace::private(NS_RUFFLE_INTERNAL), "graphics"),
|
||||
&QName::new(Namespace::private(NS_RUFFLE_INTERNAL), "graphics").into(),
|
||||
activation,
|
||||
)? {
|
||||
Value::Undefined | Value::Null => {
|
||||
let graphics = Value::from(StageObject::graphics(activation, dobj)?);
|
||||
this.set_property(
|
||||
this,
|
||||
&QName::new(Namespace::private(NS_RUFFLE_INTERNAL), "graphics"),
|
||||
&QName::new(Namespace::private(NS_RUFFLE_INTERNAL), "graphics").into(),
|
||||
graphics.clone(),
|
||||
activation,
|
||||
)?;
|
||||
|
|
|
@ -45,14 +45,14 @@ pub fn graphics<'gc>(
|
|||
// Lazily initialize the `Graphics` object in a hidden property.
|
||||
let graphics = match this.get_property(
|
||||
this,
|
||||
&QName::new(Namespace::private(NS_RUFFLE_INTERNAL), "graphics"),
|
||||
&QName::new(Namespace::private(NS_RUFFLE_INTERNAL), "graphics").into(),
|
||||
activation,
|
||||
)? {
|
||||
Value::Undefined | Value::Null => {
|
||||
let graphics = Value::from(StageObject::graphics(activation, dobj)?);
|
||||
this.set_property(
|
||||
this,
|
||||
&QName::new(Namespace::private(NS_RUFFLE_INTERNAL), "graphics"),
|
||||
&QName::new(Namespace::private(NS_RUFFLE_INTERNAL), "graphics").into(),
|
||||
graphics.clone(),
|
||||
activation,
|
||||
)?;
|
||||
|
|
|
@ -171,7 +171,8 @@ pub fn format_to_string<'gc>(
|
|||
let param_name = QName::dynamic_name(match param_name {
|
||||
Value::Undefined | Value::Null => "null".into(),
|
||||
_ => param_name.coerce_to_string(activation)?,
|
||||
});
|
||||
})
|
||||
.into();
|
||||
|
||||
let param_value = this
|
||||
.get_property(this, ¶m_name, activation)?
|
||||
|
@ -179,7 +180,7 @@ pub fn format_to_string<'gc>(
|
|||
write!(
|
||||
stringified_params,
|
||||
" {}={}",
|
||||
param_name.local_name(),
|
||||
param_name.local_name().unwrap(),
|
||||
param_value
|
||||
)
|
||||
.unwrap();
|
||||
|
|
|
@ -28,13 +28,13 @@ pub fn instance_init<'gc>(
|
|||
|
||||
this.init_property(
|
||||
this,
|
||||
&QName::new(Namespace::private(NS_EVENT_DISPATCHER), "target"),
|
||||
&QName::new(Namespace::private(NS_EVENT_DISPATCHER), "target").into(),
|
||||
target,
|
||||
activation,
|
||||
)?;
|
||||
this.init_property(
|
||||
this,
|
||||
&QName::new(Namespace::private(NS_EVENT_DISPATCHER), "dispatch_list"),
|
||||
&QName::new(Namespace::private(NS_EVENT_DISPATCHER), "dispatch_list").into(),
|
||||
dispatch_list.into(),
|
||||
activation,
|
||||
)?;
|
||||
|
@ -53,7 +53,7 @@ pub fn add_event_listener<'gc>(
|
|||
let dispatch_list = this
|
||||
.get_property(
|
||||
this,
|
||||
&QName::new(Namespace::private(NS_EVENT_DISPATCHER), "dispatch_list"),
|
||||
&QName::new(Namespace::private(NS_EVENT_DISPATCHER), "dispatch_list").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_object(activation)?;
|
||||
|
@ -100,7 +100,7 @@ pub fn remove_event_listener<'gc>(
|
|||
let dispatch_list = this
|
||||
.get_property(
|
||||
this,
|
||||
&QName::new(Namespace::private(NS_EVENT_DISPATCHER), "dispatch_list"),
|
||||
&QName::new(Namespace::private(NS_EVENT_DISPATCHER), "dispatch_list").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_object(activation)?;
|
||||
|
@ -139,7 +139,7 @@ pub fn has_event_listener<'gc>(
|
|||
let dispatch_list = this
|
||||
.get_property(
|
||||
this,
|
||||
&QName::new(Namespace::private(NS_EVENT_DISPATCHER), "dispatch_list"),
|
||||
&QName::new(Namespace::private(NS_EVENT_DISPATCHER), "dispatch_list").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_object(activation)?;
|
||||
|
@ -169,7 +169,7 @@ pub fn will_trigger<'gc>(
|
|||
let dispatch_list = this
|
||||
.get_property(
|
||||
this,
|
||||
&QName::new(Namespace::private(NS_EVENT_DISPATCHER), "dispatch_list"),
|
||||
&QName::new(Namespace::private(NS_EVENT_DISPATCHER), "dispatch_list").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_object(activation)?;
|
||||
|
@ -190,7 +190,7 @@ pub fn will_trigger<'gc>(
|
|||
let target = this
|
||||
.get_property(
|
||||
this,
|
||||
&QName::new(Namespace::private(NS_EVENT_DISPATCHER), "target"),
|
||||
&QName::new(Namespace::private(NS_EVENT_DISPATCHER), "target").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_object(activation)
|
||||
|
|
|
@ -33,10 +33,18 @@ fn coords<'gc>(
|
|||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
) -> Result<(f64, f64), Error> {
|
||||
let x = this
|
||||
.get_property(*this, &QName::new(Namespace::public(), "x"), activation)?
|
||||
.get_property(
|
||||
*this,
|
||||
&QName::new(Namespace::public(), "x").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_number(activation)?;
|
||||
let y = this
|
||||
.get_property(*this, &QName::new(Namespace::public(), "y"), activation)?
|
||||
.get_property(
|
||||
*this,
|
||||
&QName::new(Namespace::public(), "y").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_number(activation)?;
|
||||
Ok((x, y))
|
||||
}
|
||||
|
@ -48,13 +56,13 @@ fn set_coords<'gc>(
|
|||
) -> Result<(), Error> {
|
||||
this.set_property(
|
||||
*this,
|
||||
&QName::new(Namespace::public(), "x"),
|
||||
&QName::new(Namespace::public(), "x").into(),
|
||||
value.0.into(),
|
||||
activation,
|
||||
)?;
|
||||
this.set_property(
|
||||
*this,
|
||||
&QName::new(Namespace::public(), "y"),
|
||||
&QName::new(Namespace::public(), "y").into(),
|
||||
value.1.into(),
|
||||
activation,
|
||||
)?;
|
||||
|
@ -320,10 +328,18 @@ pub fn to_string<'gc>(
|
|||
) -> Result<Value<'gc>, Error> {
|
||||
if let Some(this) = this {
|
||||
let x = this
|
||||
.get_property(this, &QName::new(Namespace::public(), "x"), activation)?
|
||||
.get_property(
|
||||
this,
|
||||
&QName::new(Namespace::public(), "x").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_string(activation)?;
|
||||
let y = this
|
||||
.get_property(this, &QName::new(Namespace::public(), "y"), activation)?
|
||||
.get_property(
|
||||
this,
|
||||
&QName::new(Namespace::public(), "y").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_string(activation)?;
|
||||
return Ok(
|
||||
AvmString::new(activation.context.gc_context, format!("(x={}, y={})", x, y)).into(),
|
||||
|
|
|
@ -27,7 +27,11 @@ pub fn create_rectangle<'gc>(
|
|||
macro_rules! get_prop {
|
||||
($this:expr, $activation:expr, $name: expr) => {
|
||||
$this
|
||||
.get_property($this, &QName::new(Namespace::public(), $name), $activation)?
|
||||
.get_property(
|
||||
$this,
|
||||
&QName::new(Namespace::public(), $name).into(),
|
||||
$activation,
|
||||
)?
|
||||
.coerce_to_number($activation)
|
||||
};
|
||||
}
|
||||
|
@ -36,7 +40,7 @@ macro_rules! set_prop {
|
|||
($this:expr, $activation:expr, $name: expr, $value: expr) => {
|
||||
$this.set_property(
|
||||
$this,
|
||||
&QName::new(Namespace::public(), $name),
|
||||
&QName::new(Namespace::public(), $name).into(),
|
||||
$value.into(),
|
||||
$activation,
|
||||
)
|
||||
|
@ -452,12 +456,26 @@ pub fn copy_from<'gc>(
|
|||
) -> Result<Value<'gc>, Error> {
|
||||
if let Some(rect) = args.get(0) {
|
||||
let rect = rect.coerce_to_object(activation)?;
|
||||
let x = rect.get_property(rect, &QName::new(Namespace::public(), "x"), activation)?;
|
||||
let y = rect.get_property(rect, &QName::new(Namespace::public(), "y"), activation)?;
|
||||
let width =
|
||||
rect.get_property(rect, &QName::new(Namespace::public(), "width"), activation)?;
|
||||
let height =
|
||||
rect.get_property(rect, &QName::new(Namespace::public(), "height"), activation)?;
|
||||
let x = rect.get_property(
|
||||
rect,
|
||||
&QName::new(Namespace::public(), "x").into(),
|
||||
activation,
|
||||
)?;
|
||||
let y = rect.get_property(
|
||||
rect,
|
||||
&QName::new(Namespace::public(), "y").into(),
|
||||
activation,
|
||||
)?;
|
||||
let width = rect.get_property(
|
||||
rect,
|
||||
&QName::new(Namespace::public(), "width").into(),
|
||||
activation,
|
||||
)?;
|
||||
let height = rect.get_property(
|
||||
rect,
|
||||
&QName::new(Namespace::public(), "height").into(),
|
||||
activation,
|
||||
)?;
|
||||
|
||||
set_to(activation, this, &[x, y, width, height])?;
|
||||
}
|
||||
|
@ -740,16 +758,32 @@ pub fn to_string<'gc>(
|
|||
) -> Result<Value<'gc>, Error> {
|
||||
if let Some(this) = this {
|
||||
let x = this
|
||||
.get_property(this, &QName::new(Namespace::public(), "x"), activation)?
|
||||
.get_property(
|
||||
this,
|
||||
&QName::new(Namespace::public(), "x").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_string(activation)?;
|
||||
let y = this
|
||||
.get_property(this, &QName::new(Namespace::public(), "y"), activation)?
|
||||
.get_property(
|
||||
this,
|
||||
&QName::new(Namespace::public(), "y").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_string(activation)?;
|
||||
let width = this
|
||||
.get_property(this, &QName::new(Namespace::public(), "width"), activation)?
|
||||
.get_property(
|
||||
this,
|
||||
&QName::new(Namespace::public(), "width").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_string(activation)?;
|
||||
let height = this
|
||||
.get_property(this, &QName::new(Namespace::public(), "height"), activation)?
|
||||
.get_property(
|
||||
this,
|
||||
&QName::new(Namespace::public(), "height").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_string(activation)?;
|
||||
|
||||
return Ok(AvmString::new(
|
||||
|
|
|
@ -31,13 +31,13 @@ pub fn instance_init<'gc>(
|
|||
|
||||
this.set_property(
|
||||
this,
|
||||
&QName::new(Namespace::public(), "volume"),
|
||||
&QName::new(Namespace::public(), "volume").into(),
|
||||
volume.into(),
|
||||
activation,
|
||||
)?;
|
||||
this.set_property(
|
||||
this,
|
||||
&QName::new(Namespace::public(), "pan"),
|
||||
&QName::new(Namespace::public(), "pan").into(),
|
||||
pan.into(),
|
||||
activation,
|
||||
)?;
|
||||
|
@ -65,14 +65,14 @@ pub fn pan<'gc>(
|
|||
let left_to_right = this
|
||||
.get_property(
|
||||
this,
|
||||
&QName::new(Namespace::public(), "leftToRight"),
|
||||
&QName::new(Namespace::public(), "leftToRight").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_number(activation)?;
|
||||
let right_to_left = this
|
||||
.get_property(
|
||||
this,
|
||||
&QName::new(Namespace::public(), "rightToLeft"),
|
||||
&QName::new(Namespace::public(), "rightToLeft").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_number(activation)?;
|
||||
|
@ -84,7 +84,7 @@ pub fn pan<'gc>(
|
|||
let left_to_left = this
|
||||
.get_property(
|
||||
this,
|
||||
&QName::new(Namespace::public(), "leftToLeft"),
|
||||
&QName::new(Namespace::public(), "leftToLeft").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_number(activation)?;
|
||||
|
@ -110,25 +110,25 @@ pub fn set_pan<'gc>(
|
|||
|
||||
this.set_property(
|
||||
this,
|
||||
&QName::new(Namespace::public(), "leftToLeft"),
|
||||
&QName::new(Namespace::public(), "leftToLeft").into(),
|
||||
(1.0 - pan).sqrt().into(),
|
||||
activation,
|
||||
)?;
|
||||
this.set_property(
|
||||
this,
|
||||
&QName::new(Namespace::public(), "rightToRight"),
|
||||
&QName::new(Namespace::public(), "rightToRight").into(),
|
||||
(1.0 + pan).sqrt().into(),
|
||||
activation,
|
||||
)?;
|
||||
this.set_property(
|
||||
this,
|
||||
&QName::new(Namespace::public(), "leftToRight"),
|
||||
&QName::new(Namespace::public(), "leftToRight").into(),
|
||||
(0.0).into(),
|
||||
activation,
|
||||
)?;
|
||||
this.set_property(
|
||||
this,
|
||||
&QName::new(Namespace::public(), "rightToLeft"),
|
||||
&QName::new(Namespace::public(), "rightToLeft").into(),
|
||||
(0.0).into(),
|
||||
activation,
|
||||
)?;
|
||||
|
|
|
@ -80,7 +80,7 @@ pub fn get_definition<'gc>(
|
|||
.get_defining_script(&qname.into())?
|
||||
.ok_or_else(|| format!("No definition called {} exists", local_name))?;
|
||||
let globals = defined_script.globals(&mut activation.context)?;
|
||||
let definition = globals.get_property(globals, &qname, activation)?;
|
||||
let definition = globals.get_property(globals, &qname.into(), activation)?;
|
||||
|
||||
return Ok(definition);
|
||||
}
|
||||
|
|
|
@ -21,79 +21,79 @@ pub fn instance_init<'gc>(
|
|||
|
||||
this.set_property(
|
||||
this,
|
||||
&QName::new(Namespace::public(), "font"),
|
||||
&QName::new(Namespace::public(), "font").into(),
|
||||
args.get(0).cloned().unwrap_or(Value::Null),
|
||||
activation,
|
||||
)?;
|
||||
this.set_property(
|
||||
this,
|
||||
&QName::new(Namespace::public(), "size"),
|
||||
&QName::new(Namespace::public(), "size").into(),
|
||||
args.get(1).cloned().unwrap_or(Value::Null),
|
||||
activation,
|
||||
)?;
|
||||
this.set_property(
|
||||
this,
|
||||
&QName::new(Namespace::public(), "color"),
|
||||
&QName::new(Namespace::public(), "color").into(),
|
||||
args.get(2).cloned().unwrap_or(Value::Null),
|
||||
activation,
|
||||
)?;
|
||||
this.set_property(
|
||||
this,
|
||||
&QName::new(Namespace::public(), "bold"),
|
||||
&QName::new(Namespace::public(), "bold").into(),
|
||||
args.get(3).cloned().unwrap_or(Value::Null),
|
||||
activation,
|
||||
)?;
|
||||
this.set_property(
|
||||
this,
|
||||
&QName::new(Namespace::public(), "italic"),
|
||||
&QName::new(Namespace::public(), "italic").into(),
|
||||
args.get(4).cloned().unwrap_or(Value::Null),
|
||||
activation,
|
||||
)?;
|
||||
this.set_property(
|
||||
this,
|
||||
&QName::new(Namespace::public(), "underline"),
|
||||
&QName::new(Namespace::public(), "underline").into(),
|
||||
args.get(5).cloned().unwrap_or(Value::Null),
|
||||
activation,
|
||||
)?;
|
||||
this.set_property(
|
||||
this,
|
||||
&QName::new(Namespace::public(), "url"),
|
||||
&QName::new(Namespace::public(), "url").into(),
|
||||
args.get(6).cloned().unwrap_or(Value::Null),
|
||||
activation,
|
||||
)?;
|
||||
this.set_property(
|
||||
this,
|
||||
&QName::new(Namespace::public(), "target"),
|
||||
&QName::new(Namespace::public(), "target").into(),
|
||||
args.get(7).cloned().unwrap_or(Value::Null),
|
||||
activation,
|
||||
)?;
|
||||
this.set_property(
|
||||
this,
|
||||
&QName::new(Namespace::public(), "align"),
|
||||
&QName::new(Namespace::public(), "align").into(),
|
||||
args.get(8).cloned().unwrap_or(Value::Null),
|
||||
activation,
|
||||
)?;
|
||||
this.set_property(
|
||||
this,
|
||||
&QName::new(Namespace::public(), "leftMargin"),
|
||||
&QName::new(Namespace::public(), "leftMargin").into(),
|
||||
args.get(9).cloned().unwrap_or(Value::Null),
|
||||
activation,
|
||||
)?;
|
||||
this.set_property(
|
||||
this,
|
||||
&QName::new(Namespace::public(), "rightMargin"),
|
||||
&QName::new(Namespace::public(), "rightMargin").into(),
|
||||
args.get(10).cloned().unwrap_or(Value::Null),
|
||||
activation,
|
||||
)?;
|
||||
this.set_property(
|
||||
this,
|
||||
&QName::new(Namespace::public(), "indent"),
|
||||
&QName::new(Namespace::public(), "indent").into(),
|
||||
args.get(11).cloned().unwrap_or(Value::Null),
|
||||
activation,
|
||||
)?;
|
||||
this.set_property(
|
||||
this,
|
||||
&QName::new(Namespace::public(), "leading"),
|
||||
&QName::new(Namespace::public(), "leading").into(),
|
||||
args.get(12).cloned().unwrap_or(Value::Null),
|
||||
activation,
|
||||
)?;
|
||||
|
|
|
@ -31,7 +31,7 @@ pub fn class_init<'gc>(
|
|||
) -> Result<Value<'gc>, Error> {
|
||||
if let Some(this) = this {
|
||||
let mut function_proto = this
|
||||
.get_property(this, &QName::dynamic_name("prototype"), activation)?
|
||||
.get_property(this, &QName::dynamic_name("prototype").into(), activation)?
|
||||
.coerce_to_object(activation)?;
|
||||
|
||||
function_proto.install_dynamic_property(
|
||||
|
|
|
@ -27,7 +27,7 @@ pub fn class_init<'gc>(
|
|||
) -> Result<Value<'gc>, Error> {
|
||||
if let Some(this) = this {
|
||||
let mut object_proto = this
|
||||
.get_property(this, &QName::dynamic_name("prototype"), activation)?
|
||||
.get_property(this, &QName::dynamic_name("prototype").into(), activation)?
|
||||
.coerce_to_object(activation)?;
|
||||
let gc_context = activation.context.gc_context;
|
||||
|
||||
|
|
|
@ -146,7 +146,7 @@ pub fn specialized_class_init<'gc>(
|
|||
) -> Result<Value<'gc>, Error> {
|
||||
if let Some(this) = this {
|
||||
let mut proto = this
|
||||
.get_property(this, &QName::dynamic_name("prototype"), activation)?
|
||||
.get_property(this, &QName::dynamic_name("prototype").into(), activation)?
|
||||
.coerce_to_object(activation)?;
|
||||
let scope = this.get_scope();
|
||||
|
||||
|
@ -174,7 +174,7 @@ pub fn specialized_class_init<'gc>(
|
|||
for (pubname, func) in PUBLIC_PROTOTYPE_METHODS {
|
||||
proto.set_property(
|
||||
this,
|
||||
&QName::dynamic_name(*pubname),
|
||||
&QName::dynamic_name(*pubname).into(),
|
||||
FunctionObject::from_function(
|
||||
activation,
|
||||
Method::from_builtin(*func, pubname, activation.context.gc_context),
|
||||
|
@ -402,7 +402,11 @@ pub fn to_locale_string<'gc>(
|
|||
) -> Result<Value<'gc>, Error> {
|
||||
join_inner(activation, this, &[",".into()], |v, act| {
|
||||
if let Ok(o) = v.coerce_to_object(act) {
|
||||
let ls = o.get_property(o, &QName::new(Namespace::public(), "toLocaleString"), act)?;
|
||||
let ls = o.get_property(
|
||||
o,
|
||||
&QName::new(Namespace::public(), "toLocaleString").into(),
|
||||
act,
|
||||
)?;
|
||||
|
||||
ls.coerce_to_object(act)?.call(Some(o), &[], act, None)
|
||||
} else {
|
||||
|
@ -601,7 +605,11 @@ pub fn index_of<'gc>(
|
|||
|
||||
let from_index = if from_index < 0 {
|
||||
let length = this
|
||||
.get_property(this, &QName::new(Namespace::public(), "length"), activation)?
|
||||
.get_property(
|
||||
this,
|
||||
&QName::new(Namespace::public(), "length").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_i32(activation)?;
|
||||
max(length + from_index, 0) as u32
|
||||
} else {
|
||||
|
@ -638,7 +646,11 @@ pub fn last_index_of<'gc>(
|
|||
|
||||
let from_index = if from_index < 0 {
|
||||
let length = this
|
||||
.get_property(this, &QName::new(Namespace::public(), "length"), activation)?
|
||||
.get_property(
|
||||
this,
|
||||
&QName::new(Namespace::public(), "length").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_i32(activation)?;
|
||||
max(length + from_index, 0) as u32
|
||||
} else {
|
||||
|
|
|
@ -96,8 +96,11 @@ pub use crate::avm2::object::xml_object::{xml_allocator, XmlObject};
|
|||
}
|
||||
)]
|
||||
pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy {
|
||||
/// Retrieve a property by its QName, without taking prototype lookups
|
||||
/// into account.
|
||||
/// Retrieve a property by QName, after multiname resolution, prototype
|
||||
/// lookups, and all other considerations have been taken.
|
||||
///
|
||||
/// This required method is only intended to be called by other TObject
|
||||
/// methods.
|
||||
fn get_property_local(
|
||||
self,
|
||||
receiver: Object<'gc>,
|
||||
|
@ -105,21 +108,45 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
|||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
) -> Result<Value<'gc>, Error>;
|
||||
|
||||
/// Retrieve a property by its QName.
|
||||
/// Retrieve a property by Multiname lookup.
|
||||
///
|
||||
/// This corresponds directly to the AVM2 operation `getproperty`.
|
||||
fn get_property(
|
||||
self,
|
||||
receiver: Object<'gc>,
|
||||
name: &QName<'gc>,
|
||||
multiname: &Multiname<'gc>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
) -> Result<Value<'gc>, Error> {
|
||||
let has_no_getter = self.has_own_virtual_setter(name) && !self.has_own_virtual_getter(name);
|
||||
let name = self.resolve_multiname(multiname)?;
|
||||
|
||||
if self.has_own_property(name)? && !has_no_getter {
|
||||
return self.get_property_local(receiver, name, activation);
|
||||
// Special case: Unresolvable properties on dynamic classes are treated
|
||||
// as dynamic properties that have not yet been set, and yield
|
||||
// `undefined`
|
||||
if name.is_none() {
|
||||
if !self
|
||||
.instance_of_class_definition()
|
||||
.map(|c| c.read().is_sealed())
|
||||
.unwrap_or(false)
|
||||
{
|
||||
return Ok(Value::Undefined);
|
||||
}
|
||||
|
||||
return Err(
|
||||
format!("Cannot get undefined property {:?}", multiname.local_name()).into(),
|
||||
);
|
||||
}
|
||||
|
||||
// At this point, the name must be a valid QName.
|
||||
let name = name.unwrap();
|
||||
let has_no_getter =
|
||||
self.has_own_virtual_setter(&name) && !self.has_own_virtual_getter(&name);
|
||||
|
||||
if self.has_own_property(&name)? && !has_no_getter {
|
||||
return self.get_property_local(receiver, &name, activation);
|
||||
}
|
||||
|
||||
if let Some(proto) = self.proto() {
|
||||
return proto.get_property(receiver, name, activation);
|
||||
return proto.get_property(receiver, multiname, activation);
|
||||
}
|
||||
|
||||
Ok(Value::Undefined)
|
||||
|
@ -151,7 +178,11 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
|||
Ok(None)
|
||||
}
|
||||
|
||||
/// Set a property on this specific object.
|
||||
/// Set a property by QName, after multiname resolution and all other
|
||||
/// considerations have been taken.
|
||||
///
|
||||
/// This required method is only intended to be called by other TObject
|
||||
/// methods.
|
||||
fn set_property_local(
|
||||
self,
|
||||
receiver: Object<'gc>,
|
||||
|
@ -160,18 +191,46 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
|||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
) -> Result<(), Error>;
|
||||
|
||||
/// Set a property by its QName.
|
||||
/// Set a property by Multiname lookup.
|
||||
///
|
||||
/// This corresponds directly with the AVM2 operation `setproperty`.
|
||||
fn set_property(
|
||||
&mut self,
|
||||
receiver: Object<'gc>,
|
||||
name: &QName<'gc>,
|
||||
multiname: &Multiname<'gc>,
|
||||
value: Value<'gc>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
) -> Result<(), Error> {
|
||||
self.set_property_local(receiver, name, value, activation)
|
||||
let name = self.resolve_multiname(multiname)?;
|
||||
|
||||
// Special case: Unresolvable properties on dynamic classes are treated
|
||||
// as initializing a new dynamic property on namespace Public("").
|
||||
if name.is_none() {
|
||||
if !self
|
||||
.instance_of_class_definition()
|
||||
.map(|c| c.read().is_sealed())
|
||||
.unwrap_or(false)
|
||||
{
|
||||
let local_name: Result<AvmString<'gc>, Error> = multiname
|
||||
.local_name()
|
||||
.ok_or_else(|| "Cannot set undefined property using any name".into());
|
||||
let name = QName::dynamic_name(local_name?);
|
||||
return self.set_property_local(receiver, &name, value, activation);
|
||||
}
|
||||
|
||||
return Err(
|
||||
format!("Cannot set undefined property {:?}", multiname.local_name()).into(),
|
||||
);
|
||||
}
|
||||
|
||||
self.set_property_local(receiver, &name.unwrap(), value, activation)
|
||||
}
|
||||
|
||||
/// Init a property on this specific object.
|
||||
/// Initialize a property by QName, after multiname resolution and all
|
||||
/// other considerations have been taken.
|
||||
///
|
||||
/// This required method is only intended to be called by other TObject
|
||||
/// methods.
|
||||
fn init_property_local(
|
||||
self,
|
||||
receiver: Object<'gc>,
|
||||
|
@ -180,31 +239,80 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
|||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
) -> Result<(), Error>;
|
||||
|
||||
/// Init a property by its QName.
|
||||
/// Initialize a property by Multiname lookup.
|
||||
///
|
||||
/// This corresponds directly with the AVM2 operation `initproperty`.
|
||||
fn init_property(
|
||||
&mut self,
|
||||
receiver: Object<'gc>,
|
||||
name: &QName<'gc>,
|
||||
multiname: &Multiname<'gc>,
|
||||
value: Value<'gc>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
) -> Result<(), Error> {
|
||||
if self.has_own_virtual_setter(name) {
|
||||
return self.init_property_local(receiver, name, value, activation);
|
||||
}
|
||||
let name = self.resolve_multiname(multiname)?;
|
||||
|
||||
let mut proto = self.proto();
|
||||
while let Some(mut my_proto) = proto {
|
||||
//NOTE: This only works because we validate ahead-of-time that
|
||||
//we're calling a virtual setter. If you call `set_property` on
|
||||
//a non-virtual you will actually alter the prototype.
|
||||
if my_proto.has_own_virtual_setter(name) {
|
||||
return my_proto.init_property(receiver, name, value, activation);
|
||||
// Special case: Unresolvable properties on dynamic classes are treated
|
||||
// as initializing a new dynamic property on namespace Public("").
|
||||
if name.is_none() {
|
||||
if !self
|
||||
.instance_of_class_definition()
|
||||
.map(|c| c.read().is_sealed())
|
||||
.unwrap_or(false)
|
||||
{
|
||||
let local_name: Result<AvmString<'gc>, Error> = multiname
|
||||
.local_name()
|
||||
.ok_or_else(|| "Cannot set undefined property using any name".into());
|
||||
let name = QName::dynamic_name(local_name?);
|
||||
return self.init_property_local(receiver, &name, value, activation);
|
||||
}
|
||||
|
||||
proto = my_proto.proto();
|
||||
return Err(
|
||||
format!("Cannot set undefined property {:?}", multiname.local_name()).into(),
|
||||
);
|
||||
}
|
||||
|
||||
receiver.init_property_local(receiver, name, value, activation)
|
||||
self.init_property_local(receiver, &name.unwrap(), value, activation)
|
||||
}
|
||||
|
||||
/// Call a named property on the object.
|
||||
///
|
||||
/// This corresponds directly to the `callproperty` operation in AVM2.
|
||||
fn call_property(
|
||||
self,
|
||||
multiname: &Multiname<'gc>,
|
||||
arguments: &[Value<'gc>],
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
) -> Result<Value<'gc>, Error> {
|
||||
let name = self.resolve_multiname(multiname)?;
|
||||
if name.is_none() {
|
||||
return Err(format!(
|
||||
"Attempted to call undefined property {:?}",
|
||||
multiname.local_name()
|
||||
)
|
||||
.into());
|
||||
}
|
||||
|
||||
let name = name.unwrap();
|
||||
let superclass_object = if let Some(c) = self.instance_of() {
|
||||
c.find_class_for_trait(&name)?
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let function = self
|
||||
.get_property(self.into(), multiname, activation)?
|
||||
.coerce_to_object(activation);
|
||||
if function.is_err() {
|
||||
return Err(format!(
|
||||
"Attempted to call undefined property {:?}",
|
||||
multiname.local_name()
|
||||
)
|
||||
.into());
|
||||
}
|
||||
|
||||
function
|
||||
.unwrap()
|
||||
.call(Some(self.into()), arguments, activation, superclass_object)
|
||||
}
|
||||
|
||||
/// Retrieve a slot by its index.
|
||||
|
@ -689,14 +797,28 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
|||
/// The class that defined the method being called will also be provided to
|
||||
/// the `Activation` that the method runs on so that further supercalls
|
||||
/// will work as expected.
|
||||
fn supercall_method(
|
||||
///
|
||||
/// This method corresponds directly to the AVM2 operation `callsuper`,
|
||||
/// with the caveat listed above about what object to call it on.
|
||||
fn call_super(
|
||||
self,
|
||||
name: &QName<'gc>,
|
||||
reciever: Option<Object<'gc>>,
|
||||
multiname: &Multiname<'gc>,
|
||||
reciever: Object<'gc>,
|
||||
arguments: &[Value<'gc>],
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
) -> Result<Value<'gc>, Error> {
|
||||
let superclass_object = self.find_class_for_trait(name)?.ok_or_else(|| {
|
||||
let name = reciever.resolve_multiname(multiname)?;
|
||||
if name.is_none() {
|
||||
return Err(format!(
|
||||
"Attempted to supercall method {:?}, which does not exist",
|
||||
multiname.local_name()
|
||||
)
|
||||
.into());
|
||||
}
|
||||
|
||||
let name = name.unwrap();
|
||||
|
||||
let superclass_object = self.find_class_for_trait(&name)?.ok_or_else(|| {
|
||||
format!(
|
||||
"Attempted to supercall method {:?}, which does not exist",
|
||||
name
|
||||
|
@ -707,24 +829,28 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
|||
.as_class_definition()
|
||||
.unwrap()
|
||||
.read()
|
||||
.lookup_instance_traits(name, &mut class_traits)?;
|
||||
.lookup_instance_traits(&name, &mut class_traits)?;
|
||||
let base_trait = class_traits
|
||||
.iter()
|
||||
.find(|t| matches!(t.kind(), TraitKind::Method { .. }));
|
||||
let scope = superclass_object.get_scope();
|
||||
|
||||
if let Some(TraitKind::Method { method, .. }) = base_trait.map(|b| b.kind()) {
|
||||
let callee = FunctionObject::from_method(activation, method.clone(), scope, reciever);
|
||||
let callee =
|
||||
FunctionObject::from_method(activation, method.clone(), scope, Some(reciever));
|
||||
|
||||
callee.call(reciever, arguments, activation, Some(superclass_object))
|
||||
callee.call(
|
||||
Some(reciever),
|
||||
arguments,
|
||||
activation,
|
||||
Some(superclass_object),
|
||||
)
|
||||
} else {
|
||||
if let Some(reciever) = reciever {
|
||||
if let Ok(callee) = reciever
|
||||
.get_property(reciever, name, activation)
|
||||
.and_then(|v| v.coerce_to_object(activation))
|
||||
{
|
||||
return callee.call(Some(reciever), arguments, activation, None);
|
||||
}
|
||||
if let Ok(callee) = reciever
|
||||
.get_property(reciever, multiname, activation)
|
||||
.and_then(|v| v.coerce_to_object(activation))
|
||||
{
|
||||
return callee.call(Some(reciever), arguments, activation, None);
|
||||
}
|
||||
|
||||
Err(format!(
|
||||
|
@ -756,13 +882,27 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
|||
/// The class that defined the getter being called will also be provided to
|
||||
/// the `Activation` that the getter runs on so that further supercalls
|
||||
/// will work as expected.
|
||||
fn supercall_getter(
|
||||
///
|
||||
/// This method corresponds directly to the AVM2 operation `getsuper`,
|
||||
/// with the caveat listed above about what object to call it on.
|
||||
fn get_super(
|
||||
self,
|
||||
name: &QName<'gc>,
|
||||
reciever: Option<Object<'gc>>,
|
||||
multiname: &Multiname<'gc>,
|
||||
reciever: Object<'gc>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
) -> Result<Value<'gc>, Error> {
|
||||
let superclass_object = self.find_class_for_trait(name)?.ok_or_else(|| {
|
||||
let name = reciever.resolve_multiname(multiname)?;
|
||||
if name.is_none() {
|
||||
return Err(format!(
|
||||
"Attempted to supercall getter {:?}, which does not exist",
|
||||
multiname.local_name()
|
||||
)
|
||||
.into());
|
||||
}
|
||||
|
||||
let name = name.unwrap();
|
||||
|
||||
let superclass_object = self.find_class_for_trait(&name)?.ok_or_else(|| {
|
||||
format!(
|
||||
"Attempted to supercall getter {:?}, which does not exist",
|
||||
name
|
||||
|
@ -773,24 +913,19 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
|||
.as_class_definition()
|
||||
.unwrap()
|
||||
.read()
|
||||
.lookup_instance_traits(name, &mut class_traits)?;
|
||||
.lookup_instance_traits(&name, &mut class_traits)?;
|
||||
let base_trait = class_traits
|
||||
.iter()
|
||||
.find(|t| matches!(t.kind(), TraitKind::Getter { .. }));
|
||||
let scope = superclass_object.get_scope();
|
||||
|
||||
if let Some(TraitKind::Getter { method, .. }) = base_trait.map(|b| b.kind()) {
|
||||
let callee = FunctionObject::from_method(activation, method.clone(), scope, reciever);
|
||||
let callee =
|
||||
FunctionObject::from_method(activation, method.clone(), scope, Some(reciever));
|
||||
|
||||
callee.call(reciever, &[], activation, Some(superclass_object))
|
||||
} else if let Some(reciever) = reciever {
|
||||
reciever.get_property(reciever, name, activation)
|
||||
callee.call(Some(reciever), &[], activation, Some(superclass_object))
|
||||
} else {
|
||||
Err(format!(
|
||||
"Attempted to supercall getter {:?}, which does not exist",
|
||||
name
|
||||
)
|
||||
.into())
|
||||
reciever.get_property(reciever, multiname, activation)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -815,14 +950,29 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
|||
/// The class that defined the setter being called will also be provided to
|
||||
/// the `Activation` that the setter runs on so that further supercalls
|
||||
/// will work as expected.
|
||||
fn supercall_setter(
|
||||
///
|
||||
/// This method corresponds directly to the AVM2 operation `setsuper`,
|
||||
/// with the caveat listed above about what object to call it on.
|
||||
#[allow(unused_mut)]
|
||||
fn set_super(
|
||||
self,
|
||||
name: &QName<'gc>,
|
||||
multiname: &Multiname<'gc>,
|
||||
value: Value<'gc>,
|
||||
reciever: Option<Object<'gc>>,
|
||||
mut reciever: Object<'gc>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
) -> Result<(), Error> {
|
||||
let superclass_object = self.find_class_for_trait(name)?.ok_or_else(|| {
|
||||
let name = reciever.resolve_multiname(multiname)?;
|
||||
if name.is_none() {
|
||||
return Err(format!(
|
||||
"Attempted to supercall setter {:?}, which does not exist",
|
||||
multiname.local_name()
|
||||
)
|
||||
.into());
|
||||
}
|
||||
|
||||
let name = name.unwrap();
|
||||
|
||||
let superclass_object = self.find_class_for_trait(&name)?.ok_or_else(|| {
|
||||
format!(
|
||||
"Attempted to supercall setter {:?}, which does not exist",
|
||||
name
|
||||
|
@ -833,26 +983,26 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
|||
.as_class_definition()
|
||||
.unwrap()
|
||||
.read()
|
||||
.lookup_instance_traits(name, &mut class_traits)?;
|
||||
.lookup_instance_traits(&name, &mut class_traits)?;
|
||||
let base_trait = class_traits
|
||||
.iter()
|
||||
.find(|t| matches!(t.kind(), TraitKind::Setter { .. }));
|
||||
let scope = superclass_object.get_scope();
|
||||
|
||||
if let Some(TraitKind::Setter { method, .. }) = base_trait.map(|b| b.kind()) {
|
||||
let callee = FunctionObject::from_method(activation, method.clone(), scope, reciever);
|
||||
let callee =
|
||||
FunctionObject::from_method(activation, method.clone(), scope, Some(reciever));
|
||||
|
||||
callee.call(reciever, &[value], activation, Some(superclass_object))?;
|
||||
callee.call(
|
||||
Some(reciever),
|
||||
&[value],
|
||||
activation,
|
||||
Some(superclass_object),
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
} else if let Some(mut reciever) = reciever {
|
||||
reciever.set_property(reciever, name, value, activation)
|
||||
} else {
|
||||
Err(format!(
|
||||
"Attempted to supercall setter {:?}, which does not exist",
|
||||
name
|
||||
)
|
||||
.into())
|
||||
reciever.set_property(reciever, multiname, value, activation)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -975,7 +1125,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
|||
class: Object<'gc>,
|
||||
) -> Result<bool, Error> {
|
||||
let type_proto = class
|
||||
.get_property(class, &QName::dynamic_name("prototype"), activation)?
|
||||
.get_property(class, &QName::dynamic_name("prototype").into(), activation)?
|
||||
.coerce_to_object(activation)?;
|
||||
|
||||
self.has_prototype_in_chain(type_proto)
|
||||
|
|
|
@ -54,7 +54,7 @@ impl<'gc> BitmapDataObject<'gc> {
|
|||
let proto = class
|
||||
.get_property(
|
||||
class,
|
||||
&QName::new(Namespace::public(), "prototype"),
|
||||
&QName::new(Namespace::public(), "prototype").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_object(activation)?;
|
||||
|
|
|
@ -96,7 +96,7 @@ impl<'gc> ClassObject<'gc> {
|
|||
let base_proto = superclass_object
|
||||
.get_property(
|
||||
superclass_object,
|
||||
&QName::new(Namespace::public(), "prototype"),
|
||||
&QName::new(Namespace::public(), "prototype").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_object(activation)?;
|
||||
|
@ -437,7 +437,7 @@ impl<'gc> TObject<'gc> for ClassObject<'gc> {
|
|||
let prototype = self
|
||||
.get_property(
|
||||
class_object,
|
||||
&QName::new(Namespace::public(), "prototype"),
|
||||
&QName::new(Namespace::public(), "prototype").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_object(activation)?;
|
||||
|
@ -585,7 +585,7 @@ impl<'gc> TObject<'gc> for ClassObject<'gc> {
|
|||
let base_proto = superclass_object
|
||||
.get_property(
|
||||
superclass_object,
|
||||
&QName::new(Namespace::public(), "prototype"),
|
||||
&QName::new(Namespace::public(), "prototype").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_object(activation)?;
|
||||
|
|
|
@ -133,7 +133,7 @@ impl<'gc> TObject<'gc> for DomainObject<'gc> {
|
|||
let constr = this
|
||||
.get_property(
|
||||
this,
|
||||
&QName::new(Namespace::public(), "constructor"),
|
||||
&QName::new(Namespace::public(), "constructor").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_object(activation)?;
|
||||
|
|
|
@ -60,7 +60,7 @@ impl<'gc> EventObject<'gc> {
|
|||
let proto = class
|
||||
.get_property(
|
||||
class,
|
||||
&QName::new(Namespace::public(), "prototype"),
|
||||
&QName::new(Namespace::public(), "prototype").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_object(activation)?;
|
||||
|
|
|
@ -136,7 +136,7 @@ impl<'gc> TObject<'gc> for FunctionObject<'gc> {
|
|||
let prototype = self
|
||||
.get_property(
|
||||
class,
|
||||
&QName::new(Namespace::public(), "prototype"),
|
||||
&QName::new(Namespace::public(), "prototype").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_object(activation)?;
|
||||
|
|
|
@ -58,7 +58,7 @@ impl<'gc> SoundObject<'gc> {
|
|||
let proto = class
|
||||
.get_property(
|
||||
class,
|
||||
&QName::new(Namespace::public(), "prototype"),
|
||||
&QName::new(Namespace::public(), "prototype").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_object(activation)?;
|
||||
|
|
|
@ -54,7 +54,7 @@ impl<'gc> SoundChannelObject<'gc> {
|
|||
let proto = class
|
||||
.get_property(
|
||||
class,
|
||||
&QName::new(Namespace::public(), "prototype"),
|
||||
&QName::new(Namespace::public(), "prototype").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_object(activation)?;
|
||||
|
|
|
@ -63,7 +63,7 @@ impl<'gc> StageObject<'gc> {
|
|||
let proto = class
|
||||
.get_property(
|
||||
class,
|
||||
&QName::new(Namespace::public(), "prototype"),
|
||||
&QName::new(Namespace::public(), "prototype").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_object(activation)?;
|
||||
|
|
|
@ -69,7 +69,7 @@ impl<'gc> VectorObject<'gc> {
|
|||
let applied_proto = applied_class
|
||||
.get_property(
|
||||
applied_class,
|
||||
&QName::new(Namespace::public(), "prototype"),
|
||||
&QName::new(Namespace::public(), "prototype").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_object(activation)?;
|
||||
|
|
|
@ -146,7 +146,7 @@ impl<'gc> Scope<'gc> {
|
|||
if self.locals().has_property(&qname)? {
|
||||
return Ok(Some(self.values.get_property(
|
||||
self.values,
|
||||
&qname,
|
||||
&qname.into(),
|
||||
activation,
|
||||
)?));
|
||||
}
|
||||
|
@ -164,7 +164,7 @@ impl<'gc> Scope<'gc> {
|
|||
|
||||
return Ok(Some(script_scope.get_property(
|
||||
script_scope,
|
||||
&qname,
|
||||
&qname.into(),
|
||||
activation,
|
||||
)?));
|
||||
}
|
||||
|
|
|
@ -303,7 +303,7 @@ impl<'gc> Value<'gc> {
|
|||
let object = *o;
|
||||
|
||||
if let Value::Object(f) =
|
||||
object.get_property(*o, &QName::dynamic_name("toString"), activation)?
|
||||
object.get_property(*o, &QName::dynamic_name("toString").into(), activation)?
|
||||
{
|
||||
prim = f.call(Some(*o), &[], activation, None)?;
|
||||
}
|
||||
|
@ -313,7 +313,7 @@ impl<'gc> Value<'gc> {
|
|||
}
|
||||
|
||||
if let Value::Object(f) =
|
||||
object.get_property(*o, &QName::dynamic_name("valueOf"), activation)?
|
||||
object.get_property(*o, &QName::dynamic_name("valueOf").into(), activation)?
|
||||
{
|
||||
prim = f.call(Some(*o), &[], activation, None)?;
|
||||
}
|
||||
|
@ -329,7 +329,7 @@ impl<'gc> Value<'gc> {
|
|||
let object = *o;
|
||||
|
||||
if let Value::Object(f) =
|
||||
object.get_property(*o, &QName::dynamic_name("valueOf"), activation)?
|
||||
object.get_property(*o, &QName::dynamic_name("valueOf").into(), activation)?
|
||||
{
|
||||
prim = f.call(Some(*o), &[], activation, None)?;
|
||||
}
|
||||
|
@ -339,7 +339,7 @@ impl<'gc> Value<'gc> {
|
|||
}
|
||||
|
||||
if let Value::Object(f) =
|
||||
object.get_property(*o, &QName::dynamic_name("toString"), activation)?
|
||||
object.get_property(*o, &QName::dynamic_name("toString").into(), activation)?
|
||||
{
|
||||
prim = f.call(Some(*o), &[], activation, None)?;
|
||||
}
|
||||
|
|
|
@ -1780,7 +1780,7 @@ impl SoundTransform {
|
|||
left_to_left: (as3_st
|
||||
.get_property(
|
||||
as3_st,
|
||||
&Avm2QName::new(Avm2Namespace::public(), "leftToLeft"),
|
||||
&Avm2QName::new(Avm2Namespace::public(), "leftToLeft").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_number(activation)?
|
||||
|
@ -1788,7 +1788,7 @@ impl SoundTransform {
|
|||
left_to_right: (as3_st
|
||||
.get_property(
|
||||
as3_st,
|
||||
&Avm2QName::new(Avm2Namespace::public(), "leftToRight"),
|
||||
&Avm2QName::new(Avm2Namespace::public(), "leftToRight").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_number(activation)?
|
||||
|
@ -1796,7 +1796,7 @@ impl SoundTransform {
|
|||
right_to_left: (as3_st
|
||||
.get_property(
|
||||
as3_st,
|
||||
&Avm2QName::new(Avm2Namespace::public(), "rightToLeft"),
|
||||
&Avm2QName::new(Avm2Namespace::public(), "rightToLeft").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_number(activation)?
|
||||
|
@ -1804,7 +1804,7 @@ impl SoundTransform {
|
|||
right_to_right: (as3_st
|
||||
.get_property(
|
||||
as3_st,
|
||||
&Avm2QName::new(Avm2Namespace::public(), "rightToRight"),
|
||||
&Avm2QName::new(Avm2Namespace::public(), "rightToRight").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_number(activation)?
|
||||
|
@ -1812,7 +1812,7 @@ impl SoundTransform {
|
|||
volume: (as3_st
|
||||
.get_property(
|
||||
as3_st,
|
||||
&Avm2QName::new(Avm2Namespace::public(), "volume"),
|
||||
&Avm2QName::new(Avm2Namespace::public(), "volume").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_number(activation)?
|
||||
|
@ -1832,31 +1832,31 @@ impl SoundTransform {
|
|||
|
||||
as3_st.set_property(
|
||||
as3_st,
|
||||
&Avm2QName::new(Avm2Namespace::public(), "leftToLeft"),
|
||||
&Avm2QName::new(Avm2Namespace::public(), "leftToLeft").into(),
|
||||
(self.left_to_left as f64 / 100.0).into(),
|
||||
activation,
|
||||
)?;
|
||||
as3_st.set_property(
|
||||
as3_st,
|
||||
&Avm2QName::new(Avm2Namespace::public(), "leftToRight"),
|
||||
&Avm2QName::new(Avm2Namespace::public(), "leftToRight").into(),
|
||||
(self.left_to_right as f64 / 100.0).into(),
|
||||
activation,
|
||||
)?;
|
||||
as3_st.set_property(
|
||||
as3_st,
|
||||
&Avm2QName::new(Avm2Namespace::public(), "rightToLeft"),
|
||||
&Avm2QName::new(Avm2Namespace::public(), "rightToLeft").into(),
|
||||
(self.right_to_left as f64 / 100.0).into(),
|
||||
activation,
|
||||
)?;
|
||||
as3_st.set_property(
|
||||
as3_st,
|
||||
&Avm2QName::new(Avm2Namespace::public(), "rightToRight"),
|
||||
&Avm2QName::new(Avm2Namespace::public(), "rightToRight").into(),
|
||||
(self.right_to_right as f64 / 100.0).into(),
|
||||
activation,
|
||||
)?;
|
||||
as3_st.set_property(
|
||||
as3_st,
|
||||
&Avm2QName::new(Avm2Namespace::public(), "volume"),
|
||||
&Avm2QName::new(Avm2Namespace::public(), "volume").into(),
|
||||
(self.volume as f64 / 100.0).into(),
|
||||
activation,
|
||||
)?;
|
||||
|
|
|
@ -1173,7 +1173,8 @@ impl<'gc> MovieClip<'gc> {
|
|||
AvmString::new(context.gc_context, child.name().to_owned()),
|
||||
);
|
||||
let mut activation = Avm2Activation::from_nothing(context.reborrow());
|
||||
if let Err(e) = p.init_property(p, &name, c.into(), &mut activation) {
|
||||
if let Err(e) = p.init_property(p, &name.into(), c.into(), &mut activation)
|
||||
{
|
||||
log::error!(
|
||||
"Got error when setting AVM2 child named \"{}\": {}",
|
||||
&child.name(),
|
||||
|
|
|
@ -198,7 +198,7 @@ fn getstr_from_avm2_object<'gc>(
|
|||
Ok(
|
||||
match object.get_property(
|
||||
object,
|
||||
&Avm2QName::new(Avm2Namespace::public(), pubname),
|
||||
&Avm2QName::new(Avm2Namespace::public(), pubname).into(),
|
||||
activation,
|
||||
)? {
|
||||
Avm2Value::Undefined => None,
|
||||
|
@ -216,7 +216,7 @@ fn getfloat_from_avm2_object<'gc>(
|
|||
Ok(
|
||||
match object.get_property(
|
||||
object,
|
||||
&Avm2QName::new(Avm2Namespace::public(), pubname),
|
||||
&Avm2QName::new(Avm2Namespace::public(), pubname).into(),
|
||||
activation,
|
||||
)? {
|
||||
Avm2Value::Undefined => None,
|
||||
|
@ -234,7 +234,7 @@ fn getbool_from_avm2_object<'gc>(
|
|||
Ok(
|
||||
match object.get_property(
|
||||
object,
|
||||
&Avm2QName::new(Avm2Namespace::public(), pubname),
|
||||
&Avm2QName::new(Avm2Namespace::public(), pubname).into(),
|
||||
activation,
|
||||
)? {
|
||||
Avm2Value::Undefined => None,
|
||||
|
@ -252,7 +252,7 @@ fn getfloatarray_from_avm2_object<'gc>(
|
|||
Ok(
|
||||
match object.get_property(
|
||||
object,
|
||||
&Avm2QName::new(Avm2Namespace::public(), pubname),
|
||||
&Avm2QName::new(Avm2Namespace::public(), pubname).into(),
|
||||
activation,
|
||||
)? {
|
||||
Avm2Value::Undefined => None,
|
||||
|
@ -271,7 +271,8 @@ fn getfloatarray_from_avm2_object<'gc>(
|
|||
&Avm2QName::new(
|
||||
Avm2Namespace::public(),
|
||||
AvmString::new(activation.context.gc_context, format!("{}", i)),
|
||||
),
|
||||
)
|
||||
.into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_number(activation)?,
|
||||
|
@ -704,7 +705,7 @@ impl TextFormat {
|
|||
|
||||
object.set_property(
|
||||
object,
|
||||
&Avm2QName::new(Avm2Namespace::public(), "font"),
|
||||
&Avm2QName::new(Avm2Namespace::public(), "font").into(),
|
||||
self.font
|
||||
.clone()
|
||||
.map(|v| AvmString::new(activation.context.gc_context, v).into())
|
||||
|
@ -713,13 +714,13 @@ impl TextFormat {
|
|||
)?;
|
||||
object.set_property(
|
||||
object,
|
||||
&Avm2QName::new(Avm2Namespace::public(), "size"),
|
||||
&Avm2QName::new(Avm2Namespace::public(), "size").into(),
|
||||
self.size.map(|v| v.into()).unwrap_or(Avm2Value::Null),
|
||||
activation,
|
||||
)?;
|
||||
object.set_property(
|
||||
object,
|
||||
&Avm2QName::new(Avm2Namespace::public(), "color"),
|
||||
&Avm2QName::new(Avm2Namespace::public(), "color").into(),
|
||||
self.color
|
||||
.clone()
|
||||
.map(|v| v.to_rgb().into())
|
||||
|
@ -728,7 +729,7 @@ impl TextFormat {
|
|||
)?;
|
||||
object.set_property(
|
||||
object,
|
||||
&Avm2QName::new(Avm2Namespace::public(), "align"),
|
||||
&Avm2QName::new(Avm2Namespace::public(), "align").into(),
|
||||
self.align
|
||||
.map(|v| {
|
||||
AvmString::new(
|
||||
|
@ -748,25 +749,25 @@ impl TextFormat {
|
|||
)?;
|
||||
object.set_property(
|
||||
object,
|
||||
&Avm2QName::new(Avm2Namespace::public(), "bold"),
|
||||
&Avm2QName::new(Avm2Namespace::public(), "bold").into(),
|
||||
self.bold.map(|v| v.into()).unwrap_or(Avm2Value::Null),
|
||||
activation,
|
||||
)?;
|
||||
object.set_property(
|
||||
object,
|
||||
&Avm2QName::new(Avm2Namespace::public(), "italic"),
|
||||
&Avm2QName::new(Avm2Namespace::public(), "italic").into(),
|
||||
self.italic.map(|v| v.into()).unwrap_or(Avm2Value::Null),
|
||||
activation,
|
||||
)?;
|
||||
object.set_property(
|
||||
object,
|
||||
&Avm2QName::new(Avm2Namespace::public(), "underline"),
|
||||
&Avm2QName::new(Avm2Namespace::public(), "underline").into(),
|
||||
self.underline.map(|v| v.into()).unwrap_or(Avm2Value::Null),
|
||||
activation,
|
||||
)?;
|
||||
object.set_property(
|
||||
object,
|
||||
&Avm2QName::new(Avm2Namespace::public(), "leftMargin"),
|
||||
&Avm2QName::new(Avm2Namespace::public(), "leftMargin").into(),
|
||||
self.left_margin
|
||||
.map(|v| v.into())
|
||||
.unwrap_or(Avm2Value::Null),
|
||||
|
@ -774,7 +775,7 @@ impl TextFormat {
|
|||
)?;
|
||||
object.set_property(
|
||||
object,
|
||||
&Avm2QName::new(Avm2Namespace::public(), "rightMargin"),
|
||||
&Avm2QName::new(Avm2Namespace::public(), "rightMargin").into(),
|
||||
self.right_margin
|
||||
.map(|v| v.into())
|
||||
.unwrap_or(Avm2Value::Null),
|
||||
|
@ -782,13 +783,13 @@ impl TextFormat {
|
|||
)?;
|
||||
object.set_property(
|
||||
object,
|
||||
&Avm2QName::new(Avm2Namespace::public(), "indent"),
|
||||
&Avm2QName::new(Avm2Namespace::public(), "indent").into(),
|
||||
self.indent.map(|v| v.into()).unwrap_or(Avm2Value::Null),
|
||||
activation,
|
||||
)?;
|
||||
object.set_property(
|
||||
object,
|
||||
&Avm2QName::new(Avm2Namespace::public(), "blockIndent"),
|
||||
&Avm2QName::new(Avm2Namespace::public(), "blockIndent").into(),
|
||||
self.block_indent
|
||||
.map(|v| v.into())
|
||||
.unwrap_or(Avm2Value::Null),
|
||||
|
@ -796,19 +797,19 @@ impl TextFormat {
|
|||
)?;
|
||||
object.set_property(
|
||||
object,
|
||||
&Avm2QName::new(Avm2Namespace::public(), "kerning"),
|
||||
&Avm2QName::new(Avm2Namespace::public(), "kerning").into(),
|
||||
self.kerning.map(|v| v.into()).unwrap_or(Avm2Value::Null),
|
||||
activation,
|
||||
)?;
|
||||
object.set_property(
|
||||
object,
|
||||
&Avm2QName::new(Avm2Namespace::public(), "leading"),
|
||||
&Avm2QName::new(Avm2Namespace::public(), "leading").into(),
|
||||
self.leading.map(|v| v.into()).unwrap_or(Avm2Value::Null),
|
||||
activation,
|
||||
)?;
|
||||
object.set_property(
|
||||
object,
|
||||
&Avm2QName::new(Avm2Namespace::public(), "letterSpacing"),
|
||||
&Avm2QName::new(Avm2Namespace::public(), "letterSpacing").into(),
|
||||
self.letter_spacing
|
||||
.map(|v| v.into())
|
||||
.unwrap_or(Avm2Value::Null),
|
||||
|
@ -816,13 +817,13 @@ impl TextFormat {
|
|||
)?;
|
||||
object.set_property(
|
||||
object,
|
||||
&Avm2QName::new(Avm2Namespace::public(), "bullet"),
|
||||
&Avm2QName::new(Avm2Namespace::public(), "bullet").into(),
|
||||
self.bullet.map(|v| v.into()).unwrap_or(Avm2Value::Null),
|
||||
activation,
|
||||
)?;
|
||||
object.set_property(
|
||||
object,
|
||||
&Avm2QName::new(Avm2Namespace::public(), "url"),
|
||||
&Avm2QName::new(Avm2Namespace::public(), "url").into(),
|
||||
self.url
|
||||
.clone()
|
||||
.map(|v| AvmString::new(activation.context.gc_context, v).into())
|
||||
|
@ -831,7 +832,7 @@ impl TextFormat {
|
|||
)?;
|
||||
object.set_property(
|
||||
object,
|
||||
&Avm2QName::new(Avm2Namespace::public(), "target"),
|
||||
&Avm2QName::new(Avm2Namespace::public(), "target").into(),
|
||||
self.target
|
||||
.clone()
|
||||
.map(|v| AvmString::new(activation.context.gc_context, v).into())
|
||||
|
@ -846,14 +847,14 @@ impl TextFormat {
|
|||
|
||||
object.set_property(
|
||||
object,
|
||||
&Avm2QName::new(Avm2Namespace::public(), "tabStops"),
|
||||
&Avm2QName::new(Avm2Namespace::public(), "tabStops").into(),
|
||||
tab_stops.into(),
|
||||
activation,
|
||||
)?;
|
||||
} else {
|
||||
object.set_property(
|
||||
object,
|
||||
&Avm2QName::new(Avm2Namespace::public(), "tabStops"),
|
||||
&Avm2QName::new(Avm2Namespace::public(), "tabStops").into(),
|
||||
Avm2Value::Null,
|
||||
activation,
|
||||
)?;
|
||||
|
|
Loading…
Reference in New Issue