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() {
|
||||
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 mut null_activation = Activation::from_nothing(context.reborrow());
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ mod boolean;
|
|||
mod class;
|
||||
mod flash;
|
||||
mod function;
|
||||
mod global_scope;
|
||||
mod int;
|
||||
mod namespace;
|
||||
mod number;
|
||||
|
@ -47,6 +48,7 @@ pub struct SystemPrototypes<'gc> {
|
|||
pub object: Object<'gc>,
|
||||
pub function: Object<'gc>,
|
||||
pub class: Object<'gc>,
|
||||
pub global: Object<'gc>,
|
||||
pub string: Object<'gc>,
|
||||
pub boolean: Object<'gc>,
|
||||
pub number: Object<'gc>,
|
||||
|
@ -77,6 +79,7 @@ impl<'gc> SystemPrototypes<'gc> {
|
|||
object,
|
||||
function,
|
||||
class,
|
||||
global: empty,
|
||||
string: empty,
|
||||
boolean: 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.
|
||||
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(
|
||||
activation,
|
||||
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::method::{BytecodeMethod, Method};
|
||||
use crate::avm2::object::{Object, ScriptObject};
|
||||
use crate::avm2::string::AvmString;
|
||||
use crate::avm2::traits::Trait;
|
||||
use crate::avm2::{Avm2, Error};
|
||||
|
@ -128,7 +129,9 @@ impl<'gc> TranslationUnit<'gc> {
|
|||
|
||||
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);
|
||||
|
||||
script.write(mc).load_traits(self, script_index, avm2, mc)?;
|
||||
|
@ -192,6 +195,9 @@ impl<'gc> TranslationUnit<'gc> {
|
|||
#[derive(Clone, Debug, Collect)]
|
||||
#[collect(no_drop)]
|
||||
pub struct Script<'gc> {
|
||||
/// The global scope for the script.
|
||||
globals: Object<'gc>,
|
||||
|
||||
/// The initializer method to run for the script.
|
||||
init: Method<'gc>,
|
||||
|
||||
|
@ -209,9 +215,13 @@ impl<'gc> Script<'gc> {
|
|||
/// The caller is responsible for storing the class in the
|
||||
/// `TranslationUnit` and calling `load_traits` to complete the
|
||||
/// 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(
|
||||
unit: TranslationUnit<'gc>,
|
||||
script_index: u32,
|
||||
globals: Object<'gc>,
|
||||
mc: MutationContext<'gc, '_>,
|
||||
) -> Result<GcCell<'gc, Self>, Error> {
|
||||
let abc = unit.abc();
|
||||
|
@ -226,6 +236,7 @@ impl<'gc> Script<'gc> {
|
|||
Ok(GcCell::allocate(
|
||||
mc,
|
||||
Self {
|
||||
globals,
|
||||
init,
|
||||
traits: Vec::new(),
|
||||
traits_loaded: false,
|
||||
|
@ -272,6 +283,11 @@ impl<'gc> Script<'gc> {
|
|||
self.init.clone()
|
||||
}
|
||||
|
||||
/// Return the global scope for the script.
|
||||
pub fn globals(&self) -> Object<'gc> {
|
||||
self.globals
|
||||
}
|
||||
|
||||
/// Return traits for this script.
|
||||
///
|
||||
/// This function will return an error if it is incorrectly called before
|
||||
|
|
Loading…
Reference in New Issue