Add separate scope object for each script.
This commit is contained in:
parent
89c1378569
commit
02e05e3d7f
|
@ -137,7 +137,7 @@ impl<'gc> Avm2<'gc> {
|
||||||
|
|
||||||
for i in (0..abc_file.scripts.len()).rev() {
|
for i in (0..abc_file.scripts.len()).rev() {
|
||||||
let script = tunit.load_script(i as u32, context.avm2, context.gc_context)?;
|
let script = tunit.load_script(i as u32, context.avm2, context.gc_context)?;
|
||||||
let mut globals = context.avm2.globals();
|
let mut globals = script.read().globals();
|
||||||
let scope = Scope::push_scope(None, globals, context.gc_context);
|
let scope = Scope::push_scope(None, globals, context.gc_context);
|
||||||
let mut null_activation = Activation::from_nothing(context.reborrow());
|
let mut null_activation = Activation::from_nothing(context.reborrow());
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ mod boolean;
|
||||||
mod class;
|
mod class;
|
||||||
mod flash;
|
mod flash;
|
||||||
mod function;
|
mod function;
|
||||||
|
mod global_scope;
|
||||||
mod int;
|
mod int;
|
||||||
mod namespace;
|
mod namespace;
|
||||||
mod number;
|
mod number;
|
||||||
|
@ -47,6 +48,7 @@ pub struct SystemPrototypes<'gc> {
|
||||||
pub object: Object<'gc>,
|
pub object: Object<'gc>,
|
||||||
pub function: Object<'gc>,
|
pub function: Object<'gc>,
|
||||||
pub class: Object<'gc>,
|
pub class: Object<'gc>,
|
||||||
|
pub global: Object<'gc>,
|
||||||
pub string: Object<'gc>,
|
pub string: Object<'gc>,
|
||||||
pub boolean: Object<'gc>,
|
pub boolean: Object<'gc>,
|
||||||
pub number: Object<'gc>,
|
pub number: Object<'gc>,
|
||||||
|
@ -77,6 +79,7 @@ impl<'gc> SystemPrototypes<'gc> {
|
||||||
object,
|
object,
|
||||||
function,
|
function,
|
||||||
class,
|
class,
|
||||||
|
global: empty,
|
||||||
string: empty,
|
string: empty,
|
||||||
boolean: empty,
|
boolean: empty,
|
||||||
number: empty,
|
number: empty,
|
||||||
|
@ -277,6 +280,12 @@ pub fn load_player_globals<'gc>(activation: &mut Activation<'_, 'gc, '_>) -> Res
|
||||||
// other from the activation they're handed.
|
// other from the activation they're handed.
|
||||||
let mut sp = activation.context.avm2.system_prototypes.clone().unwrap();
|
let mut sp = activation.context.avm2.system_prototypes.clone().unwrap();
|
||||||
|
|
||||||
|
sp.global = class(
|
||||||
|
activation,
|
||||||
|
gs,
|
||||||
|
global_scope::create_class(activation.context.gc_context),
|
||||||
|
implicit_deriver,
|
||||||
|
)?;
|
||||||
sp.string = class(
|
sp.string = class(
|
||||||
activation,
|
activation,
|
||||||
gs,
|
gs,
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
//! `global` constructor
|
||||||
|
//!
|
||||||
|
//! Globals are an undocumented Flash class that don't appear to have any
|
||||||
|
//! public methods, but are the class that the script global scope is an
|
||||||
|
//! instance of.
|
||||||
|
|
||||||
|
use crate::avm2::activation::Activation;
|
||||||
|
use crate::avm2::class::Class;
|
||||||
|
use crate::avm2::method::Method;
|
||||||
|
use crate::avm2::names::{Namespace, QName};
|
||||||
|
use crate::avm2::object::Object;
|
||||||
|
use crate::avm2::value::Value;
|
||||||
|
use crate::avm2::Error;
|
||||||
|
use gc_arena::{GcCell, MutationContext};
|
||||||
|
|
||||||
|
/// Implements `global`'s instance constructor.
|
||||||
|
pub fn instance_init<'gc>(
|
||||||
|
_activation: &mut Activation<'_, 'gc, '_>,
|
||||||
|
_this: Option<Object<'gc>>,
|
||||||
|
_args: &[Value<'gc>],
|
||||||
|
) -> Result<Value<'gc>, Error> {
|
||||||
|
Ok(Value::Undefined)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Implements `global`'s class constructor.
|
||||||
|
pub fn class_init<'gc>(
|
||||||
|
_activation: &mut Activation<'_, 'gc, '_>,
|
||||||
|
_this: Option<Object<'gc>>,
|
||||||
|
_args: &[Value<'gc>],
|
||||||
|
) -> Result<Value<'gc>, Error> {
|
||||||
|
Ok(Value::Undefined)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct `global`'s class.
|
||||||
|
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
|
||||||
|
Class::new(
|
||||||
|
QName::new(Namespace::package(""), "global"),
|
||||||
|
Some(QName::new(Namespace::package(""), "Object").into()),
|
||||||
|
Method::from_builtin(instance_init),
|
||||||
|
Method::from_builtin(class_init),
|
||||||
|
mc,
|
||||||
|
)
|
||||||
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
use crate::avm2::class::Class;
|
use crate::avm2::class::Class;
|
||||||
use crate::avm2::method::{BytecodeMethod, Method};
|
use crate::avm2::method::{BytecodeMethod, Method};
|
||||||
|
use crate::avm2::object::{Object, ScriptObject};
|
||||||
use crate::avm2::string::AvmString;
|
use crate::avm2::string::AvmString;
|
||||||
use crate::avm2::traits::Trait;
|
use crate::avm2::traits::Trait;
|
||||||
use crate::avm2::{Avm2, Error};
|
use crate::avm2::{Avm2, Error};
|
||||||
|
@ -128,7 +129,9 @@ impl<'gc> TranslationUnit<'gc> {
|
||||||
|
|
||||||
drop(read);
|
drop(read);
|
||||||
|
|
||||||
let script = Script::from_abc_index(self, script_index, mc)?;
|
let global = ScriptObject::object(mc, avm2.prototypes().global);
|
||||||
|
|
||||||
|
let script = Script::from_abc_index(self, script_index, global, mc)?;
|
||||||
self.0.write(mc).scripts.insert(script_index, script);
|
self.0.write(mc).scripts.insert(script_index, script);
|
||||||
|
|
||||||
script.write(mc).load_traits(self, script_index, avm2, mc)?;
|
script.write(mc).load_traits(self, script_index, avm2, mc)?;
|
||||||
|
@ -192,6 +195,9 @@ impl<'gc> TranslationUnit<'gc> {
|
||||||
#[derive(Clone, Debug, Collect)]
|
#[derive(Clone, Debug, Collect)]
|
||||||
#[collect(no_drop)]
|
#[collect(no_drop)]
|
||||||
pub struct Script<'gc> {
|
pub struct Script<'gc> {
|
||||||
|
/// The global scope for the script.
|
||||||
|
globals: Object<'gc>,
|
||||||
|
|
||||||
/// The initializer method to run for the script.
|
/// The initializer method to run for the script.
|
||||||
init: Method<'gc>,
|
init: Method<'gc>,
|
||||||
|
|
||||||
|
@ -209,9 +215,13 @@ impl<'gc> Script<'gc> {
|
||||||
/// The caller is responsible for storing the class in the
|
/// The caller is responsible for storing the class in the
|
||||||
/// `TranslationUnit` and calling `load_traits` to complete the
|
/// `TranslationUnit` and calling `load_traits` to complete the
|
||||||
/// trait-loading process.
|
/// trait-loading process.
|
||||||
|
///
|
||||||
|
/// The given `globals` should be an empty object of the `global` hidden
|
||||||
|
/// type. The initializer script will create and store traits on it.
|
||||||
pub fn from_abc_index(
|
pub fn from_abc_index(
|
||||||
unit: TranslationUnit<'gc>,
|
unit: TranslationUnit<'gc>,
|
||||||
script_index: u32,
|
script_index: u32,
|
||||||
|
globals: Object<'gc>,
|
||||||
mc: MutationContext<'gc, '_>,
|
mc: MutationContext<'gc, '_>,
|
||||||
) -> Result<GcCell<'gc, Self>, Error> {
|
) -> Result<GcCell<'gc, Self>, Error> {
|
||||||
let abc = unit.abc();
|
let abc = unit.abc();
|
||||||
|
@ -226,6 +236,7 @@ impl<'gc> Script<'gc> {
|
||||||
Ok(GcCell::allocate(
|
Ok(GcCell::allocate(
|
||||||
mc,
|
mc,
|
||||||
Self {
|
Self {
|
||||||
|
globals,
|
||||||
init,
|
init,
|
||||||
traits: Vec::new(),
|
traits: Vec::new(),
|
||||||
traits_loaded: false,
|
traits_loaded: false,
|
||||||
|
@ -272,6 +283,11 @@ impl<'gc> Script<'gc> {
|
||||||
self.init.clone()
|
self.init.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the global scope for the script.
|
||||||
|
pub fn globals(&self) -> Object<'gc> {
|
||||||
|
self.globals
|
||||||
|
}
|
||||||
|
|
||||||
/// Return traits for this script.
|
/// Return traits for this script.
|
||||||
///
|
///
|
||||||
/// This function will return an error if it is incorrectly called before
|
/// This function will return an error if it is incorrectly called before
|
||||||
|
|
Loading…
Reference in New Issue