Add global scope which is automatically included on all new activations.

This commit is contained in:
David Wendt 2020-02-12 14:58:33 -05:00
parent 984e701142
commit 7d75255a1a
5 changed files with 27 additions and 6 deletions

View File

@ -8,7 +8,7 @@ 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;
use gc_arena::{Collect, GcCell}; use gc_arena::{Collect, GcCell, MutationContext};
use std::io::Cursor; use std::io::Cursor;
use std::rc::Rc; use std::rc::Rc;
use swf::avm2::read::Reader; use swf::avm2::read::Reader;
@ -19,6 +19,7 @@ use swf::read::SwfRead;
mod activation; mod activation;
mod function; mod function;
mod globals;
mod names; mod names;
mod object; mod object;
mod return_value; mod return_value;
@ -48,14 +49,18 @@ pub struct Avm2<'gc> {
/// Values currently present on the operand stack. /// Values currently present on the operand stack.
stack: Vec<Value<'gc>>, stack: Vec<Value<'gc>>,
/// Global scope object.
globals: Object<'gc>,
} }
impl<'gc> Avm2<'gc> { impl<'gc> Avm2<'gc> {
/// Construct a new AVM interpreter. /// Construct a new AVM interpreter.
pub fn new() -> Self { pub fn new(mc: MutationContext<'gc, '_>) -> Self {
Self { Self {
stack_frames: Vec::new(), stack_frames: Vec::new(),
stack: Vec::new(), stack: Vec::new(),
globals: globals::construct_global_scope(mc),
} }
} }
@ -80,6 +85,10 @@ impl<'gc> Avm2<'gc> {
Ok(()) Ok(())
} }
pub fn globals(&self) -> Object<'gc> {
self.globals
}
/// Get the current stack frame (`Activation` object). /// Get the current stack frame (`Activation` object).
pub fn current_stack_frame(&self) -> Option<GcCell<'gc, Activation<'gc>>> { pub fn current_stack_frame(&self) -> Option<GcCell<'gc, Activation<'gc>>> {
self.stack_frames.last().copied() self.stack_frames.last().copied()

View File

@ -5,7 +5,7 @@ use crate::avm2::object::Object;
use crate::avm2::scope::Scope; use crate::avm2::scope::Scope;
use crate::avm2::script_object::ScriptObject; use crate::avm2::script_object::ScriptObject;
use crate::avm2::value::Value; use crate::avm2::value::Value;
use crate::avm2::Error; use crate::avm2::{Avm2, Error};
use crate::context::UpdateContext; use crate::context::UpdateContext;
use gc_arena::{Collect, Gc, GcCell, MutationContext}; use gc_arena::{Collect, Gc, GcCell, MutationContext};
use smallvec::SmallVec; use smallvec::SmallVec;
@ -96,6 +96,7 @@ impl<'gc> Activation<'gc> {
action: Gc<'gc, Avm2Function>, action: Gc<'gc, Avm2Function>,
this: Object<'gc>, this: Object<'gc>,
arguments: Option<Object<'gc>>, arguments: Option<Object<'gc>>,
avm2: &mut Avm2<'gc>,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
let abc = action.abc.clone(); let abc = action.abc.clone();
let method_body = abc let method_body = abc
@ -115,7 +116,7 @@ impl<'gc> Activation<'gc> {
), ),
return_value: None, return_value: None,
local_scope: ScriptObject::bare_object(context.gc_context), local_scope: ScriptObject::bare_object(context.gc_context),
scope: None, scope: Some(Scope::push_scope(None, avm2.globals(), context.gc_context)),
}) })
} }

View File

@ -136,7 +136,7 @@ impl<'gc> TObject<'gc> for FunctionObject<'gc> {
Executable::Action(a2f) => { Executable::Action(a2f) => {
let activation = GcCell::allocate( let activation = GcCell::allocate(
context.gc_context, context.gc_context,
Activation::from_action(context, a2f, reciever, None)?, Activation::from_action(context, a2f, reciever, None, avm)?,
); );
avm.insert_stack_frame(activation); avm.insert_stack_frame(activation);

11
core/src/avm2/globals.rs Normal file
View File

@ -0,0 +1,11 @@
//! Global scope built-ins
use crate::avm2::object::{Object, TObject};
use crate::avm2::script_object::ScriptObject;
use gc_arena::MutationContext;
pub fn construct_global_scope<'gc>(mc: MutationContext<'gc, '_>) -> Object<'gc> {
let global_scope = ScriptObject::bare_object(mc);
global_scope
}

View File

@ -247,7 +247,7 @@ impl Player {
mouse_hovered_object: None, mouse_hovered_object: None,
drag_object: None, drag_object: None,
avm1: Avm1::new(gc_context, NEWEST_PLAYER_VERSION), avm1: Avm1::new(gc_context, NEWEST_PLAYER_VERSION),
avm2: Avm2::new(), avm2: Avm2::new(gc_context),
action_queue: ActionQueue::new(), action_queue: ActionQueue::new(),
load_manager: LoadManager::new(), load_manager: LoadManager::new(),
shared_objects: HashMap::new(), shared_objects: HashMap::new(),