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:
David Wendt 2021-09-16 19:17:56 -04:00 committed by kmeisthax
parent 945cb2c4bf
commit b07ad8070c
34 changed files with 431 additions and 306 deletions

View File

@ -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
};

View File

@ -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.

View File

@ -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)

View File

@ -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)?;

View File

@ -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,
)?;

View File

@ -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,
)?;

View File

@ -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,
)?;

View File

@ -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,
)?;

View File

@ -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,
)?;

View File

@ -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, &param_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();

View File

@ -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)

View File

@ -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(),

View File

@ -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(

View File

@ -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,
)?;

View File

@ -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);
}

View File

@ -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,
)?;

View File

@ -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(

View File

@ -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;

View File

@ -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 {

View File

@ -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)

View File

@ -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)?;

View File

@ -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)?;

View File

@ -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)?;

View File

@ -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)?;

View File

@ -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)?;

View File

@ -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)?;

View File

@ -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)?;

View File

@ -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)?;

View File

@ -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)?;

View File

@ -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,
)?));
}

View File

@ -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)?;
}

View File

@ -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,
)?;

View File

@ -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(),

View File

@ -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,
)?;