Implement `pushscope`, `popscope`, and `pushwith`.
This commit is contained in:
parent
5e6fc79f42
commit
78a1c9a7e3
|
@ -4,6 +4,7 @@ use crate::avm2::activation::Activation;
|
||||||
use crate::avm2::names::{Multiname, Namespace, QName};
|
use crate::avm2::names::{Multiname, Namespace, QName};
|
||||||
use crate::avm2::object::{Object, TObject};
|
use crate::avm2::object::{Object, TObject};
|
||||||
use crate::avm2::return_value::ReturnValue;
|
use crate::avm2::return_value::ReturnValue;
|
||||||
|
use crate::avm2::scope::Scope;
|
||||||
use crate::avm2::value::Value;
|
use crate::avm2::value::Value;
|
||||||
use crate::context::UpdateContext;
|
use crate::context::UpdateContext;
|
||||||
use crate::tag_utils::SwfSlice;
|
use crate::tag_utils::SwfSlice;
|
||||||
|
@ -339,6 +340,9 @@ impl<'gc> Avm2<'gc> {
|
||||||
Op::ReturnVoid => self.op_return_void(context),
|
Op::ReturnVoid => self.op_return_void(context),
|
||||||
Op::GetProperty { index } => self.op_get_property(context, index),
|
Op::GetProperty { index } => self.op_get_property(context, index),
|
||||||
Op::SetProperty { index } => self.op_set_property(context, index),
|
Op::SetProperty { index } => self.op_set_property(context, index),
|
||||||
|
Op::PushScope => self.op_push_scope(context),
|
||||||
|
Op::PushWith => self.op_push_with(context),
|
||||||
|
Op::PopScope => self.op_pop_scope(context),
|
||||||
Op::FindProperty { index } => self.op_find_property(context, index),
|
Op::FindProperty { index } => self.op_find_property(context, index),
|
||||||
Op::FindPropStrict { index } => self.op_find_prop_strict(context, index),
|
Op::FindPropStrict { index } => self.op_find_prop_strict(context, index),
|
||||||
Op::GetLex { index } => self.op_get_lex(context, index),
|
Op::GetLex { index } => self.op_get_lex(context, index),
|
||||||
|
@ -499,6 +503,41 @@ impl<'gc> Avm2<'gc> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn op_push_scope(&mut self, context: &mut UpdateContext<'_, 'gc, '_>) -> Result<(), Error> {
|
||||||
|
let object = self.pop().as_object()?;
|
||||||
|
let activation = self.current_stack_frame().unwrap();
|
||||||
|
let mut write = activation.write(context.gc_context);
|
||||||
|
let scope_stack = write.scope();
|
||||||
|
let new_scope = Scope::push_scope(scope_stack, object, context.gc_context);
|
||||||
|
|
||||||
|
write.set_scope(Some(new_scope));
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn op_push_with(&mut self, context: &mut UpdateContext<'_, 'gc, '_>) -> Result<(), Error> {
|
||||||
|
let object = self.pop().as_object()?;
|
||||||
|
let activation = self.current_stack_frame().unwrap();
|
||||||
|
let mut write = activation.write(context.gc_context);
|
||||||
|
let scope_stack = write.scope();
|
||||||
|
let new_scope = Scope::push_with(scope_stack, object, context.gc_context);
|
||||||
|
|
||||||
|
write.set_scope(Some(new_scope));
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn op_pop_scope(&mut self, context: &mut UpdateContext<'_, 'gc, '_>) -> Result<(), Error> {
|
||||||
|
let activation = self.current_stack_frame().unwrap();
|
||||||
|
let mut write = activation.write(context.gc_context);
|
||||||
|
let scope_stack = write.scope();
|
||||||
|
let new_scope = scope_stack.and_then(|s| s.read().pop_scope());
|
||||||
|
|
||||||
|
write.set_scope(new_scope);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn op_find_property(
|
fn op_find_property(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
|
|
|
@ -158,10 +158,16 @@ impl<'gc> Activation<'gc> {
|
||||||
self.local_registers.read().get(id).cloned()
|
self.local_registers.read().get(id).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the current scope stack.
|
||||||
pub fn scope(&self) -> Option<GcCell<'gc, Scope<'gc>>> {
|
pub fn scope(&self) -> Option<GcCell<'gc, Scope<'gc>>> {
|
||||||
self.scope
|
self.scope
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set a new scope stack.
|
||||||
|
pub fn set_scope(&mut self, new_scope: Option<GcCell<'gc, Scope<'gc>>>) {
|
||||||
|
self.scope = new_scope;
|
||||||
|
}
|
||||||
|
|
||||||
/// Set a local register.
|
/// Set a local register.
|
||||||
///
|
///
|
||||||
/// Returns `true` if the set was successful; `false` otherwise
|
/// Returns `true` if the set was successful; `false` otherwise
|
||||||
|
|
|
@ -69,6 +69,10 @@ impl<'gc> Scope<'gc> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn pop_scope(&self) -> Option<GcCell<'gc, Scope<'gc>>> {
|
||||||
|
self.parent
|
||||||
|
}
|
||||||
|
|
||||||
/// Construct a closure scope to be used as the scope stack when invoking a
|
/// Construct a closure scope to be used as the scope stack when invoking a
|
||||||
/// function.
|
/// function.
|
||||||
///
|
///
|
||||||
|
|
Loading…
Reference in New Issue