avm1: Fix double-borrow when calling a getter that calls another method

This commit is contained in:
Nathan Adams 2020-07-01 18:53:16 +02:00
parent 987375299b
commit 9b66b496d0
2 changed files with 12 additions and 22 deletions

View File

@ -1,10 +1,8 @@
//! User-defined properties
use self::Attribute::*;
use crate::avm1::error::Error;
use crate::avm1::function::Executable;
use crate::avm1::stack_frame::StackFrame;
use crate::avm1::{Object, UpdateContext, Value};
use crate::avm1::Value;
use core::fmt;
use enumset::{EnumSet, EnumSetType};
@ -32,23 +30,6 @@ pub enum Property<'gc> {
}
impl<'gc> Property<'gc> {
/// Get the value of a property slot.
///
/// This function yields `ReturnValue` because some properties may be
/// user-defined.
pub fn get(
&self,
activation: &mut StackFrame<'_, 'gc>,
context: &mut UpdateContext<'_, 'gc, '_>,
this: Object<'gc>,
base_proto: Option<Object<'gc>>,
) -> Result<Value<'gc>, Error<'gc>> {
match self {
Property::Virtual { get, .. } => get.exec(activation, context, this, base_proto, &[]),
Property::Stored { value, .. } => Ok(value.to_owned()),
}
}
/// Set a property slot.
///
/// This function may return an `Executable` of the property's virtual

View File

@ -309,16 +309,25 @@ impl<'gc> TObject<'gc> for ScriptObject<'gc> {
return Ok(self.proto().map_or(Value::Undefined, Value::Object));
}
let mut exec = None;
if let Some(value) = self
.0
.read()
.values
.get(name, activation.is_case_sensitive())
{
return value.get(activation, context, this, Some((*self).into()));
match value {
Property::Virtual { get, .. } => exec = Some(get.to_owned()),
Property::Stored { value, .. } => return Ok(value.to_owned()),
}
}
Ok(Value::Undefined)
if let Some(get) = exec {
get.exec(activation, context, this, Some((*self).into()), &[])
} else {
Ok(Value::Undefined)
}
}
/// Set a named property on the object.