avm1: Fix double-borrow when calling a getter that calls another method
This commit is contained in:
parent
987375299b
commit
9b66b496d0
|
@ -1,10 +1,8 @@
|
||||||
//! User-defined properties
|
//! User-defined properties
|
||||||
|
|
||||||
use self::Attribute::*;
|
use self::Attribute::*;
|
||||||
use crate::avm1::error::Error;
|
|
||||||
use crate::avm1::function::Executable;
|
use crate::avm1::function::Executable;
|
||||||
use crate::avm1::stack_frame::StackFrame;
|
use crate::avm1::Value;
|
||||||
use crate::avm1::{Object, UpdateContext, Value};
|
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use enumset::{EnumSet, EnumSetType};
|
use enumset::{EnumSet, EnumSetType};
|
||||||
|
|
||||||
|
@ -32,23 +30,6 @@ pub enum Property<'gc> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'gc> 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.
|
/// Set a property slot.
|
||||||
///
|
///
|
||||||
/// This function may return an `Executable` of the property's virtual
|
/// This function may return an `Executable` of the property's virtual
|
||||||
|
|
|
@ -309,16 +309,25 @@ impl<'gc> TObject<'gc> for ScriptObject<'gc> {
|
||||||
return Ok(self.proto().map_or(Value::Undefined, Value::Object));
|
return Ok(self.proto().map_or(Value::Undefined, Value::Object));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut exec = None;
|
||||||
|
|
||||||
if let Some(value) = self
|
if let Some(value) = self
|
||||||
.0
|
.0
|
||||||
.read()
|
.read()
|
||||||
.values
|
.values
|
||||||
.get(name, activation.is_case_sensitive())
|
.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.
|
/// Set a named property on the object.
|
||||||
|
|
Loading…
Reference in New Issue