avm1: Boxing a value calls the object constructor

This commit is contained in:
Mike Welsh 2020-01-19 14:10:04 -08:00
parent ccf62979a1
commit b49357e46f
3 changed files with 25 additions and 17 deletions

View File

@ -937,8 +937,8 @@ impl<'gc> Avm1<'gc> {
context: &mut UpdateContext<'_, 'gc, '_>,
) -> Result<(), Error> {
let method_name = self.pop();
let object =
value_object::ValueObject::boxed(context.gc_context, self.pop(), &self.prototypes);
let object_val = self.pop();
let object = value_object::ValueObject::boxed(self, context, object_val);
let num_args = self.pop().as_i64()?; // TODO(Herschel): max arg count?
let mut args = Vec::new();
for _ in 0..num_args {
@ -1276,8 +1276,8 @@ impl<'gc> Avm1<'gc> {
fn action_get_member(&mut self, context: &mut UpdateContext<'_, 'gc, '_>) -> Result<(), Error> {
let name_val = self.pop();
let name = name_val.coerce_to_string(self, context)?;
let object =
value_object::ValueObject::boxed(context.gc_context, self.pop(), &self.prototypes);
let object_val = self.pop();
let object = value_object::ValueObject::boxed(self, context, object_val);
object.get(&name, self, context)?.push(self);

View File

@ -19,7 +19,7 @@ pub(crate) mod movie_clip;
mod object;
mod sound;
mod stage;
mod string;
pub(crate) mod string;
pub(crate) mod text_field;
mod xml;

View File

@ -1,7 +1,6 @@
//! Object impl for boxed values
use crate::avm1::function::Executable;
use crate::avm1::globals::SystemPrototypes;
use crate::avm1::object::{ObjectPtr, TObject};
use crate::avm1::property::Attribute;
use crate::avm1::return_value::ReturnValue;
@ -40,26 +39,35 @@ impl<'gc> ValueObject<'gc> {
/// If a class exists for a given value type, this function automatically
/// selects the correct prototype for it from the system prototypes list.
pub fn boxed(
gc_context: MutationContext<'gc, '_>,
avm: &mut Avm1<'gc>,
context: &mut UpdateContext<'_, 'gc, '_>,
value: Value<'gc>,
system_prototypes: &SystemPrototypes<'gc>,
) -> Object<'gc> {
if let Value::Object(ob) = value {
ob
} else {
let proto = match value {
Value::String(_) => Some(system_prototypes.string),
_ => None,
let (constructor, proto) = match &value {
Value::String(_) => (
Some(crate::avm1::globals::string::string),
Some(avm.prototypes.string),
),
_ => (None, None),
};
ValueObject(GcCell::allocate(
gc_context,
let obj = ValueObject(GcCell::allocate(
context.gc_context,
ValueObjectData {
base: ScriptObject::object(gc_context, proto),
value,
base: ScriptObject::object(context.gc_context, proto),
value: Value::Undefined,
},
))
.into()
));
// Constructor populates the boxed object with the value.
if let Some(constructor) = constructor {
let _ = constructor(avm, context, obj.into(), &[value]);
}
obj.into()
}
}