avm2: Allow small mutations to ScopeChain
This commit is contained in:
parent
9de7d7ba7a
commit
1dd899a76f
|
@ -402,10 +402,11 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
||||||
let translation_unit = method.translation_unit();
|
let translation_unit = method.translation_unit();
|
||||||
let abc_method = method.method();
|
let abc_method = method.method();
|
||||||
let mut dummy_activation = Activation::from_nothing(context.reborrow());
|
let mut dummy_activation = Activation::from_nothing(context.reborrow());
|
||||||
|
dummy_activation.set_outer(outer);
|
||||||
let activation_class =
|
let activation_class =
|
||||||
Class::for_activation(&mut dummy_activation, translation_unit, abc_method, body)?;
|
Class::for_activation(&mut dummy_activation, translation_unit, abc_method, body)?;
|
||||||
let activation_class_object =
|
let activation_class_object =
|
||||||
ClassObject::from_class(&mut dummy_activation, activation_class, None, outer)?;
|
ClassObject::from_class(&mut dummy_activation, activation_class, None)?;
|
||||||
|
|
||||||
drop(dummy_activation);
|
drop(dummy_activation);
|
||||||
|
|
||||||
|
@ -579,6 +580,11 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the outer scope of this activation
|
||||||
|
pub fn set_outer(&mut self, new_outer: ScopeChain<'gc>) {
|
||||||
|
self.outer = new_outer;
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a new ScopeChain by chaining the current state of this
|
/// Creates a new ScopeChain by chaining the current state of this
|
||||||
/// activation's scope stack with the outer scope.
|
/// activation's scope stack with the outer scope.
|
||||||
pub fn create_scopechain(&self) -> ScopeChain<'gc> {
|
pub fn create_scopechain(&self) -> ScopeChain<'gc> {
|
||||||
|
@ -1726,9 +1732,8 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let class_entry = self.table_class(method, index)?;
|
let class_entry = self.table_class(method, index)?;
|
||||||
let scope = self.create_scopechain();
|
|
||||||
|
|
||||||
let new_class = ClassObject::from_class(self, class_entry, base_class, scope)?;
|
let new_class = ClassObject::from_class(self, class_entry, base_class)?;
|
||||||
|
|
||||||
self.context.avm2.push(new_class);
|
self.context.avm2.push(new_class);
|
||||||
|
|
||||||
|
|
|
@ -288,10 +288,10 @@ fn function<'gc>(
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
nf: NativeMethodImpl,
|
nf: NativeMethodImpl,
|
||||||
script: Script<'gc>,
|
script: Script<'gc>,
|
||||||
scope: ScopeChain<'gc>,
|
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let (_, _, mut domain) = script.init();
|
let (_, _, mut domain) = script.init();
|
||||||
let mc = activation.context.gc_context;
|
let mc = activation.context.gc_context;
|
||||||
|
let scope = activation.create_scopechain();
|
||||||
let qname = QName::new(Namespace::package(package), name);
|
let qname = QName::new(Namespace::package(package), name);
|
||||||
let method = Method::from_builtin(nf, name, mc);
|
let method = Method::from_builtin(nf, name, mc);
|
||||||
let as3fn = FunctionObject::from_method(activation, method, scope, None).into();
|
let as3fn = FunctionObject::from_method(activation, method, scope, None).into();
|
||||||
|
@ -330,7 +330,6 @@ fn class<'gc>(
|
||||||
activation: &mut Activation<'_, 'gc, '_>,
|
activation: &mut Activation<'_, 'gc, '_>,
|
||||||
class_def: GcCell<'gc, Class<'gc>>,
|
class_def: GcCell<'gc, Class<'gc>>,
|
||||||
script: Script<'gc>,
|
script: Script<'gc>,
|
||||||
scope: ScopeChain<'gc>,
|
|
||||||
) -> Result<(ClassObject<'gc>, Object<'gc>), Error> {
|
) -> Result<(ClassObject<'gc>, Object<'gc>), Error> {
|
||||||
let (_, mut global, mut domain) = script.init();
|
let (_, mut global, mut domain) = script.init();
|
||||||
|
|
||||||
|
@ -359,7 +358,7 @@ fn class<'gc>(
|
||||||
let class_name = class_read.name().clone();
|
let class_name = class_read.name().clone();
|
||||||
drop(class_read);
|
drop(class_read);
|
||||||
|
|
||||||
let class_object = ClassObject::from_class(activation, class_def, super_class, scope)?;
|
let class_object = ClassObject::from_class(activation, class_def, super_class)?;
|
||||||
global.install_const(
|
global.install_const(
|
||||||
activation.context.gc_context,
|
activation.context.gc_context,
|
||||||
class_name.clone(),
|
class_name.clone(),
|
||||||
|
@ -397,8 +396,8 @@ fn constant<'gc>(
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! avm2_system_class {
|
macro_rules! avm2_system_class {
|
||||||
($field:ident, $activation:ident, $class:expr, $script:expr, $scope:expr) => {
|
($field:ident, $activation:ident, $class:expr, $script:expr) => {
|
||||||
let (class_object, proto) = class($activation, $class, $script, $scope)?;
|
let (class_object, proto) = class($activation, $class, $script)?;
|
||||||
|
|
||||||
let sc = $activation.avm2().system_classes.as_mut().unwrap();
|
let sc = $activation.avm2().system_classes.as_mut().unwrap();
|
||||||
sc.$field = class_object;
|
sc.$field = class_object;
|
||||||
|
@ -424,6 +423,9 @@ pub fn load_player_globals<'gc>(
|
||||||
let gs = ScopeChain::new(domain).chain(mc, &[Scope::new(globals)]);
|
let gs = ScopeChain::new(domain).chain(mc, &[Scope::new(globals)]);
|
||||||
let script = Script::empty_script(mc, globals, domain);
|
let script = Script::empty_script(mc, globals, domain);
|
||||||
|
|
||||||
|
// Set the outer scope of this activation to the global scope.
|
||||||
|
activation.set_outer(gs);
|
||||||
|
|
||||||
// public / root package
|
// public / root package
|
||||||
//
|
//
|
||||||
// This part of global initialization is very complicated, because
|
// This part of global initialization is very complicated, because
|
||||||
|
@ -439,17 +441,17 @@ pub fn load_player_globals<'gc>(
|
||||||
// Hence, this ridiculously complicated dance of classdef, type allocation,
|
// Hence, this ridiculously complicated dance of classdef, type allocation,
|
||||||
// and partial initialization.
|
// and partial initialization.
|
||||||
let object_classdef = object::create_class(mc);
|
let object_classdef = object::create_class(mc);
|
||||||
let object_class = ClassObject::from_class_partial(activation, object_classdef, None, gs)?;
|
let object_class = ClassObject::from_class_partial(activation, object_classdef, None)?;
|
||||||
let object_proto = ScriptObject::bare_object(mc);
|
let object_proto = ScriptObject::bare_object(mc);
|
||||||
|
|
||||||
let fn_classdef = function::create_class(mc);
|
let fn_classdef = function::create_class(mc);
|
||||||
let fn_class =
|
let fn_class =
|
||||||
ClassObject::from_class_partial(activation, fn_classdef, Some(object_class.into()), gs)?;
|
ClassObject::from_class_partial(activation, fn_classdef, Some(object_class.into()))?;
|
||||||
let fn_proto = ScriptObject::object(mc, object_proto);
|
let fn_proto = ScriptObject::object(mc, object_proto);
|
||||||
|
|
||||||
let class_classdef = class::create_class(mc);
|
let class_classdef = class::create_class(mc);
|
||||||
let class_class =
|
let class_class =
|
||||||
ClassObject::from_class_partial(activation, class_classdef, Some(object_class.into()), gs)?;
|
ClassObject::from_class_partial(activation, class_classdef, Some(object_class.into()))?;
|
||||||
let class_proto = ScriptObject::object(mc, object_proto);
|
let class_proto = ScriptObject::object(mc, object_proto);
|
||||||
|
|
||||||
// Now to weave the Gordian knot...
|
// Now to weave the Gordian knot...
|
||||||
|
@ -489,14 +491,7 @@ pub fn load_player_globals<'gc>(
|
||||||
|
|
||||||
// After this point, it is safe to initialize any other classes.
|
// After this point, it is safe to initialize any other classes.
|
||||||
// Make sure to initialize superclasses *before* their subclasses!
|
// Make sure to initialize superclasses *before* their subclasses!
|
||||||
|
avm2_system_class!(global, activation, global_scope::create_class(mc), script);
|
||||||
avm2_system_class!(
|
|
||||||
global,
|
|
||||||
activation,
|
|
||||||
global_scope::create_class(mc),
|
|
||||||
script,
|
|
||||||
gs
|
|
||||||
);
|
|
||||||
|
|
||||||
// Oh, one more small hitch: the domain everything gets put into was
|
// Oh, one more small hitch: the domain everything gets put into was
|
||||||
// actually made *before* the core class weave, so let's fix that up now
|
// actually made *before* the core class weave, so let's fix that up now
|
||||||
|
@ -504,132 +499,104 @@ pub fn load_player_globals<'gc>(
|
||||||
globals.set_proto(mc, activation.avm2().prototypes().global);
|
globals.set_proto(mc, activation.avm2().prototypes().global);
|
||||||
globals.set_instance_of(mc, activation.avm2().classes().global);
|
globals.set_instance_of(mc, activation.avm2().classes().global);
|
||||||
|
|
||||||
avm2_system_class!(string, activation, string::create_class(mc), script, gs);
|
avm2_system_class!(string, activation, string::create_class(mc), script);
|
||||||
avm2_system_class!(boolean, activation, boolean::create_class(mc), script, gs);
|
avm2_system_class!(boolean, activation, boolean::create_class(mc), script);
|
||||||
avm2_system_class!(number, activation, number::create_class(mc), script, gs);
|
avm2_system_class!(number, activation, number::create_class(mc), script);
|
||||||
avm2_system_class!(int, activation, int::create_class(mc), script, gs);
|
avm2_system_class!(int, activation, int::create_class(mc), script);
|
||||||
avm2_system_class!(uint, activation, uint::create_class(mc), script, gs);
|
avm2_system_class!(uint, activation, uint::create_class(mc), script);
|
||||||
avm2_system_class!(
|
avm2_system_class!(namespace, activation, namespace::create_class(mc), script);
|
||||||
namespace,
|
avm2_system_class!(qname, activation, qname::create_class(mc), script);
|
||||||
activation,
|
avm2_system_class!(array, activation, array::create_class(mc), script);
|
||||||
namespace::create_class(mc),
|
|
||||||
script,
|
|
||||||
gs
|
|
||||||
);
|
|
||||||
avm2_system_class!(qname, activation, qname::create_class(mc), script, gs);
|
|
||||||
avm2_system_class!(array, activation, array::create_class(mc), script, gs);
|
|
||||||
|
|
||||||
function(activation, "", "trace", trace, script, gs)?;
|
function(activation, "", "trace", trace, script)?;
|
||||||
function(activation, "", "isFinite", is_finite, script, gs)?;
|
function(activation, "", "isFinite", is_finite, script)?;
|
||||||
function(activation, "", "isNaN", is_nan, script, gs)?;
|
function(activation, "", "isNaN", is_nan, script)?;
|
||||||
constant(mc, "", "undefined", Value::Undefined, script)?;
|
constant(mc, "", "undefined", Value::Undefined, script)?;
|
||||||
constant(mc, "", "null", Value::Null, script)?;
|
constant(mc, "", "null", Value::Null, script)?;
|
||||||
constant(mc, "", "NaN", f64::NAN.into(), script)?;
|
constant(mc, "", "NaN", f64::NAN.into(), script)?;
|
||||||
constant(mc, "", "Infinity", f64::INFINITY.into(), script)?;
|
constant(mc, "", "Infinity", f64::INFINITY.into(), script)?;
|
||||||
|
|
||||||
class(activation, math::create_class(mc), script, gs)?;
|
class(activation, math::create_class(mc), script)?;
|
||||||
avm2_system_class!(regexp, activation, regexp::create_class(mc), script, gs);
|
avm2_system_class!(regexp, activation, regexp::create_class(mc), script);
|
||||||
avm2_system_class!(vector, activation, vector::create_class(mc), script, gs);
|
avm2_system_class!(vector, activation, vector::create_class(mc), script);
|
||||||
avm2_system_class!(xml, activation, xml::create_class(mc), script, gs);
|
avm2_system_class!(xml, activation, xml::create_class(mc), script);
|
||||||
avm2_system_class!(xml_list, activation, xml_list::create_class(mc), script, gs);
|
avm2_system_class!(xml_list, activation, xml_list::create_class(mc), script);
|
||||||
|
|
||||||
avm2_system_class!(date, activation, date::create_class(mc), script, gs);
|
avm2_system_class!(date, activation, date::create_class(mc), script);
|
||||||
|
|
||||||
// package `flash.system`
|
// package `flash.system`
|
||||||
avm2_system_class!(
|
avm2_system_class!(
|
||||||
application_domain,
|
application_domain,
|
||||||
activation,
|
activation,
|
||||||
flash::system::application_domain::create_class(mc),
|
flash::system::application_domain::create_class(mc),
|
||||||
script,
|
script
|
||||||
gs
|
|
||||||
);
|
);
|
||||||
class(
|
class(
|
||||||
activation,
|
activation,
|
||||||
flash::system::capabilities::create_class(mc),
|
flash::system::capabilities::create_class(mc),
|
||||||
script,
|
script,
|
||||||
gs,
|
|
||||||
)?;
|
)?;
|
||||||
class(
|
class(
|
||||||
activation,
|
activation,
|
||||||
flash::system::security::create_class(mc),
|
flash::system::security::create_class(mc),
|
||||||
script,
|
script,
|
||||||
gs,
|
|
||||||
)?;
|
|
||||||
class(
|
|
||||||
activation,
|
|
||||||
flash::system::system::create_class(mc),
|
|
||||||
script,
|
|
||||||
gs,
|
|
||||||
)?;
|
)?;
|
||||||
|
class(activation, flash::system::system::create_class(mc), script)?;
|
||||||
|
|
||||||
// package `flash.events`
|
// package `flash.events`
|
||||||
avm2_system_class!(
|
avm2_system_class!(
|
||||||
event,
|
event,
|
||||||
activation,
|
activation,
|
||||||
flash::events::event::create_class(mc),
|
flash::events::event::create_class(mc),
|
||||||
script,
|
script
|
||||||
gs
|
|
||||||
);
|
);
|
||||||
class(
|
class(
|
||||||
activation,
|
activation,
|
||||||
flash::events::ieventdispatcher::create_interface(mc),
|
flash::events::ieventdispatcher::create_interface(mc),
|
||||||
script,
|
script,
|
||||||
gs,
|
|
||||||
)?;
|
)?;
|
||||||
class(
|
class(
|
||||||
activation,
|
activation,
|
||||||
flash::events::eventdispatcher::create_class(mc),
|
flash::events::eventdispatcher::create_class(mc),
|
||||||
script,
|
script,
|
||||||
gs,
|
|
||||||
)?;
|
)?;
|
||||||
class(
|
class(
|
||||||
activation,
|
activation,
|
||||||
flash::events::mouseevent::create_class(mc),
|
flash::events::mouseevent::create_class(mc),
|
||||||
script,
|
script,
|
||||||
gs,
|
|
||||||
)?;
|
)?;
|
||||||
class(
|
class(
|
||||||
activation,
|
activation,
|
||||||
flash::events::keyboardevent::create_class(mc),
|
flash::events::keyboardevent::create_class(mc),
|
||||||
script,
|
script,
|
||||||
gs,
|
|
||||||
)?;
|
)?;
|
||||||
class(
|
class(
|
||||||
activation,
|
activation,
|
||||||
flash::events::progressevent::create_class(mc),
|
flash::events::progressevent::create_class(mc),
|
||||||
script,
|
script,
|
||||||
gs,
|
|
||||||
)?;
|
)?;
|
||||||
// package `flash.utils`
|
// package `flash.utils`
|
||||||
avm2_system_class!(
|
avm2_system_class!(
|
||||||
bytearray,
|
bytearray,
|
||||||
activation,
|
activation,
|
||||||
flash::utils::bytearray::create_class(mc),
|
flash::utils::bytearray::create_class(mc),
|
||||||
script,
|
script
|
||||||
gs
|
|
||||||
);
|
);
|
||||||
|
|
||||||
domain.init_default_domain_memory(activation)?;
|
domain.init_default_domain_memory(activation)?;
|
||||||
|
|
||||||
class(
|
class(activation, flash::utils::endian::create_class(mc), script)?;
|
||||||
activation,
|
|
||||||
flash::utils::endian::create_class(mc),
|
|
||||||
script,
|
|
||||||
gs,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
class(
|
class(
|
||||||
activation,
|
activation,
|
||||||
flash::utils::compression_algorithm::create_class(mc),
|
flash::utils::compression_algorithm::create_class(mc),
|
||||||
script,
|
script,
|
||||||
gs,
|
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
class(
|
class(
|
||||||
activation,
|
activation,
|
||||||
flash::utils::dictionary::create_class(mc),
|
flash::utils::dictionary::create_class(mc),
|
||||||
script,
|
script,
|
||||||
gs,
|
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
function(
|
function(
|
||||||
|
@ -638,7 +605,6 @@ pub fn load_player_globals<'gc>(
|
||||||
"getTimer",
|
"getTimer",
|
||||||
flash::utils::get_timer,
|
flash::utils::get_timer,
|
||||||
script,
|
script,
|
||||||
gs,
|
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
function(
|
function(
|
||||||
|
@ -647,7 +613,6 @@ pub fn load_player_globals<'gc>(
|
||||||
"getQualifiedClassName",
|
"getQualifiedClassName",
|
||||||
flash::utils::get_qualified_class_name,
|
flash::utils::get_qualified_class_name,
|
||||||
script,
|
script,
|
||||||
gs,
|
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
function(
|
function(
|
||||||
|
@ -656,7 +621,6 @@ pub fn load_player_globals<'gc>(
|
||||||
"getQualifiedSuperclassName",
|
"getQualifiedSuperclassName",
|
||||||
flash::utils::get_qualified_super_class_name,
|
flash::utils::get_qualified_super_class_name,
|
||||||
script,
|
script,
|
||||||
gs,
|
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
function(
|
function(
|
||||||
|
@ -665,7 +629,6 @@ pub fn load_player_globals<'gc>(
|
||||||
"getDefinitionByName",
|
"getDefinitionByName",
|
||||||
flash::utils::get_definition_by_name,
|
flash::utils::get_definition_by_name,
|
||||||
script,
|
script,
|
||||||
gs,
|
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// package `flash.display`
|
// package `flash.display`
|
||||||
|
@ -673,157 +636,133 @@ pub fn load_player_globals<'gc>(
|
||||||
activation,
|
activation,
|
||||||
flash::display::ibitmapdrawable::create_interface(mc),
|
flash::display::ibitmapdrawable::create_interface(mc),
|
||||||
script,
|
script,
|
||||||
gs,
|
|
||||||
)?;
|
)?;
|
||||||
avm2_system_class!(
|
avm2_system_class!(
|
||||||
display_object,
|
display_object,
|
||||||
activation,
|
activation,
|
||||||
flash::display::displayobject::create_class(mc),
|
flash::display::displayobject::create_class(mc),
|
||||||
script,
|
script
|
||||||
gs
|
|
||||||
);
|
);
|
||||||
avm2_system_class!(
|
avm2_system_class!(
|
||||||
shape,
|
shape,
|
||||||
activation,
|
activation,
|
||||||
flash::display::shape::create_class(mc),
|
flash::display::shape::create_class(mc),
|
||||||
script,
|
script
|
||||||
gs
|
|
||||||
);
|
);
|
||||||
class(
|
class(
|
||||||
activation,
|
activation,
|
||||||
flash::display::interactiveobject::create_class(mc),
|
flash::display::interactiveobject::create_class(mc),
|
||||||
script,
|
script,
|
||||||
gs,
|
|
||||||
)?;
|
)?;
|
||||||
avm2_system_class!(
|
avm2_system_class!(
|
||||||
simplebutton,
|
simplebutton,
|
||||||
activation,
|
activation,
|
||||||
flash::display::simplebutton::create_class(mc),
|
flash::display::simplebutton::create_class(mc),
|
||||||
script,
|
script
|
||||||
gs
|
|
||||||
);
|
);
|
||||||
class(
|
class(
|
||||||
activation,
|
activation,
|
||||||
flash::display::displayobjectcontainer::create_class(mc),
|
flash::display::displayobjectcontainer::create_class(mc),
|
||||||
script,
|
script,
|
||||||
gs,
|
|
||||||
)?;
|
)?;
|
||||||
avm2_system_class!(
|
avm2_system_class!(
|
||||||
sprite,
|
sprite,
|
||||||
activation,
|
activation,
|
||||||
flash::display::sprite::create_class(mc),
|
flash::display::sprite::create_class(mc),
|
||||||
script,
|
script
|
||||||
gs
|
|
||||||
);
|
);
|
||||||
avm2_system_class!(
|
avm2_system_class!(
|
||||||
movieclip,
|
movieclip,
|
||||||
activation,
|
activation,
|
||||||
flash::display::movieclip::create_class(mc),
|
flash::display::movieclip::create_class(mc),
|
||||||
script,
|
script
|
||||||
gs
|
|
||||||
);
|
);
|
||||||
avm2_system_class!(
|
avm2_system_class!(
|
||||||
framelabel,
|
framelabel,
|
||||||
activation,
|
activation,
|
||||||
flash::display::framelabel::create_class(mc),
|
flash::display::framelabel::create_class(mc),
|
||||||
script,
|
script
|
||||||
gs
|
|
||||||
);
|
);
|
||||||
avm2_system_class!(
|
avm2_system_class!(
|
||||||
scene,
|
scene,
|
||||||
activation,
|
activation,
|
||||||
flash::display::scene::create_class(mc),
|
flash::display::scene::create_class(mc),
|
||||||
script,
|
script
|
||||||
gs
|
|
||||||
);
|
);
|
||||||
avm2_system_class!(
|
avm2_system_class!(
|
||||||
graphics,
|
graphics,
|
||||||
activation,
|
activation,
|
||||||
flash::display::graphics::create_class(mc),
|
flash::display::graphics::create_class(mc),
|
||||||
script,
|
script
|
||||||
gs
|
|
||||||
);
|
);
|
||||||
class(
|
class(
|
||||||
activation,
|
activation,
|
||||||
flash::display::jointstyle::create_class(mc),
|
flash::display::jointstyle::create_class(mc),
|
||||||
script,
|
script,
|
||||||
gs,
|
|
||||||
)?;
|
)?;
|
||||||
class(
|
class(
|
||||||
activation,
|
activation,
|
||||||
flash::display::linescalemode::create_class(mc),
|
flash::display::linescalemode::create_class(mc),
|
||||||
script,
|
script,
|
||||||
gs,
|
|
||||||
)?;
|
)?;
|
||||||
class(
|
class(
|
||||||
activation,
|
activation,
|
||||||
flash::display::capsstyle::create_class(mc),
|
flash::display::capsstyle::create_class(mc),
|
||||||
script,
|
script,
|
||||||
gs,
|
|
||||||
)?;
|
)?;
|
||||||
avm2_system_class!(
|
avm2_system_class!(
|
||||||
loaderinfo,
|
loaderinfo,
|
||||||
activation,
|
activation,
|
||||||
flash::display::loaderinfo::create_class(mc),
|
flash::display::loaderinfo::create_class(mc),
|
||||||
script,
|
script
|
||||||
gs
|
|
||||||
);
|
);
|
||||||
class(
|
class(
|
||||||
activation,
|
activation,
|
||||||
flash::display::actionscriptversion::create_class(mc),
|
flash::display::actionscriptversion::create_class(mc),
|
||||||
script,
|
script,
|
||||||
gs,
|
|
||||||
)?;
|
)?;
|
||||||
class(
|
class(
|
||||||
activation,
|
activation,
|
||||||
flash::display::swfversion::create_class(mc),
|
flash::display::swfversion::create_class(mc),
|
||||||
script,
|
script,
|
||||||
gs,
|
|
||||||
)?;
|
)?;
|
||||||
avm2_system_class!(
|
avm2_system_class!(
|
||||||
stage,
|
stage,
|
||||||
activation,
|
activation,
|
||||||
flash::display::stage::create_class(mc),
|
flash::display::stage::create_class(mc),
|
||||||
script,
|
script
|
||||||
gs
|
|
||||||
);
|
);
|
||||||
class(
|
class(
|
||||||
activation,
|
activation,
|
||||||
flash::display::stagescalemode::create_class(mc),
|
flash::display::stagescalemode::create_class(mc),
|
||||||
script,
|
script,
|
||||||
gs,
|
|
||||||
)?;
|
)?;
|
||||||
class(
|
class(
|
||||||
activation,
|
activation,
|
||||||
flash::display::stagealign::create_class(mc),
|
flash::display::stagealign::create_class(mc),
|
||||||
script,
|
script,
|
||||||
gs,
|
|
||||||
)?;
|
)?;
|
||||||
class(
|
class(
|
||||||
activation,
|
activation,
|
||||||
flash::display::stagedisplaystate::create_class(mc),
|
flash::display::stagedisplaystate::create_class(mc),
|
||||||
script,
|
script,
|
||||||
gs,
|
|
||||||
)?;
|
)?;
|
||||||
class(
|
class(
|
||||||
activation,
|
activation,
|
||||||
flash::display::stagequality::create_class(mc),
|
flash::display::stagequality::create_class(mc),
|
||||||
script,
|
script,
|
||||||
gs,
|
|
||||||
)?;
|
)?;
|
||||||
avm2_system_class!(
|
avm2_system_class!(
|
||||||
bitmap,
|
bitmap,
|
||||||
activation,
|
activation,
|
||||||
flash::display::bitmap::create_class(mc),
|
flash::display::bitmap::create_class(mc),
|
||||||
script,
|
script
|
||||||
gs
|
|
||||||
);
|
);
|
||||||
avm2_system_class!(
|
avm2_system_class!(
|
||||||
bitmapdata,
|
bitmapdata,
|
||||||
activation,
|
activation,
|
||||||
flash::display::bitmapdata::create_class(mc),
|
flash::display::bitmapdata::create_class(mc),
|
||||||
script,
|
script
|
||||||
gs
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// package `flash.geom`
|
// package `flash.geom`
|
||||||
|
@ -831,15 +770,13 @@ pub fn load_player_globals<'gc>(
|
||||||
point,
|
point,
|
||||||
activation,
|
activation,
|
||||||
flash::geom::point::create_class(mc),
|
flash::geom::point::create_class(mc),
|
||||||
script,
|
script
|
||||||
gs
|
|
||||||
);
|
);
|
||||||
avm2_system_class!(
|
avm2_system_class!(
|
||||||
rectangle,
|
rectangle,
|
||||||
activation,
|
activation,
|
||||||
flash::geom::rectangle::create_class(mc),
|
flash::geom::rectangle::create_class(mc),
|
||||||
script,
|
script
|
||||||
gs
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// package `flash.media`
|
// package `flash.media`
|
||||||
|
@ -847,34 +784,25 @@ pub fn load_player_globals<'gc>(
|
||||||
video,
|
video,
|
||||||
activation,
|
activation,
|
||||||
flash::media::video::create_class(mc),
|
flash::media::video::create_class(mc),
|
||||||
script,
|
script
|
||||||
gs
|
|
||||||
);
|
);
|
||||||
class(
|
class(activation, flash::media::sound::create_class(mc), script)?;
|
||||||
activation,
|
|
||||||
flash::media::sound::create_class(mc),
|
|
||||||
script,
|
|
||||||
gs,
|
|
||||||
)?;
|
|
||||||
avm2_system_class!(
|
avm2_system_class!(
|
||||||
soundtransform,
|
soundtransform,
|
||||||
activation,
|
activation,
|
||||||
flash::media::soundtransform::create_class(mc),
|
flash::media::soundtransform::create_class(mc),
|
||||||
script,
|
script
|
||||||
gs
|
|
||||||
);
|
);
|
||||||
class(
|
class(
|
||||||
activation,
|
activation,
|
||||||
flash::media::soundmixer::create_class(mc),
|
flash::media::soundmixer::create_class(mc),
|
||||||
script,
|
script,
|
||||||
gs,
|
|
||||||
)?;
|
)?;
|
||||||
avm2_system_class!(
|
avm2_system_class!(
|
||||||
soundchannel,
|
soundchannel,
|
||||||
activation,
|
activation,
|
||||||
flash::media::soundchannel::create_class(mc),
|
flash::media::soundchannel::create_class(mc),
|
||||||
script,
|
script
|
||||||
gs
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// package `flash.text`
|
// package `flash.text`
|
||||||
|
@ -882,35 +810,30 @@ pub fn load_player_globals<'gc>(
|
||||||
textfield,
|
textfield,
|
||||||
activation,
|
activation,
|
||||||
flash::text::textfield::create_class(mc),
|
flash::text::textfield::create_class(mc),
|
||||||
script,
|
script
|
||||||
gs
|
|
||||||
);
|
);
|
||||||
avm2_system_class!(
|
avm2_system_class!(
|
||||||
textformat,
|
textformat,
|
||||||
activation,
|
activation,
|
||||||
flash::text::textformat::create_class(mc),
|
flash::text::textformat::create_class(mc),
|
||||||
script,
|
script
|
||||||
gs
|
|
||||||
);
|
);
|
||||||
class(
|
class(
|
||||||
activation,
|
activation,
|
||||||
flash::text::textfieldautosize::create_class(mc),
|
flash::text::textfieldautosize::create_class(mc),
|
||||||
script,
|
script,
|
||||||
gs,
|
|
||||||
)?;
|
)?;
|
||||||
class(
|
class(
|
||||||
activation,
|
activation,
|
||||||
flash::text::textformatalign::create_class(mc),
|
flash::text::textformatalign::create_class(mc),
|
||||||
script,
|
script,
|
||||||
gs,
|
|
||||||
)?;
|
)?;
|
||||||
class(
|
class(
|
||||||
activation,
|
activation,
|
||||||
flash::text::textfieldtype::create_class(mc),
|
flash::text::textfieldtype::create_class(mc),
|
||||||
script,
|
script,
|
||||||
gs,
|
|
||||||
)?;
|
)?;
|
||||||
class(activation, flash::text::font::create_class(mc), script, gs)?;
|
class(activation, flash::text::font::create_class(mc), script)?;
|
||||||
|
|
||||||
// package `flash.crypto`
|
// package `flash.crypto`
|
||||||
function(
|
function(
|
||||||
|
@ -919,7 +842,6 @@ pub fn load_player_globals<'gc>(
|
||||||
"generateRandomBytes",
|
"generateRandomBytes",
|
||||||
flash::crypto::generate_random_bytes,
|
flash::crypto::generate_random_bytes,
|
||||||
script,
|
script,
|
||||||
gs,
|
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -85,9 +85,8 @@ impl<'gc> ClassObject<'gc> {
|
||||||
activation: &mut Activation<'_, 'gc, '_>,
|
activation: &mut Activation<'_, 'gc, '_>,
|
||||||
class: GcCell<'gc, Class<'gc>>,
|
class: GcCell<'gc, Class<'gc>>,
|
||||||
superclass_object: Option<ClassObject<'gc>>,
|
superclass_object: Option<ClassObject<'gc>>,
|
||||||
scope: ScopeChain<'gc>,
|
) -> Result<Self, Error> {
|
||||||
) -> Result<ClassObject<'gc>, Error> {
|
let class_object = Self::from_class_partial(activation, class, superclass_object)?;
|
||||||
let class_object = Self::from_class_partial(activation, class, superclass_object, scope)?;
|
|
||||||
|
|
||||||
//TODO: Class prototypes are *not* instances of their class and should
|
//TODO: Class prototypes are *not* instances of their class and should
|
||||||
//not be allocated by the class allocator, but instead should be
|
//not be allocated by the class allocator, but instead should be
|
||||||
|
@ -130,8 +129,8 @@ impl<'gc> ClassObject<'gc> {
|
||||||
activation: &mut Activation<'_, 'gc, '_>,
|
activation: &mut Activation<'_, 'gc, '_>,
|
||||||
class: GcCell<'gc, Class<'gc>>,
|
class: GcCell<'gc, Class<'gc>>,
|
||||||
superclass_object: Option<ClassObject<'gc>>,
|
superclass_object: Option<ClassObject<'gc>>,
|
||||||
scope: ScopeChain<'gc>,
|
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
|
let scope = activation.create_scopechain();
|
||||||
if let Some(base_class) = superclass_object.map(|b| b.inner_class_definition()) {
|
if let Some(base_class) = superclass_object.map(|b| b.inner_class_definition()) {
|
||||||
if base_class.read().is_final() {
|
if base_class.read().is_final() {
|
||||||
return Err(format!(
|
return Err(format!(
|
||||||
|
@ -174,7 +173,7 @@ impl<'gc> ClassObject<'gc> {
|
||||||
ClassObjectData {
|
ClassObjectData {
|
||||||
base: ScriptObjectData::base_new(None, None),
|
base: ScriptObjectData::base_new(None, None),
|
||||||
class,
|
class,
|
||||||
scope,
|
scope: scope,
|
||||||
superclass_object,
|
superclass_object,
|
||||||
instance_allocator: Allocator(instance_allocator),
|
instance_allocator: Allocator(instance_allocator),
|
||||||
constructor,
|
constructor,
|
||||||
|
@ -204,7 +203,7 @@ impl<'gc> ClassObject<'gc> {
|
||||||
pub fn into_finished_class(
|
pub fn into_finished_class(
|
||||||
mut self,
|
mut self,
|
||||||
activation: &mut Activation<'_, 'gc, '_>,
|
activation: &mut Activation<'_, 'gc, '_>,
|
||||||
) -> Result<ClassObject<'gc>, Error> {
|
) -> Result<Self, Error> {
|
||||||
let class = self.inner_class_definition();
|
let class = self.inner_class_definition();
|
||||||
let class_class = self.instance_of().ok_or(
|
let class_class = self.instance_of().ok_or(
|
||||||
"Cannot finish initialization of core class without it being linked to a type!",
|
"Cannot finish initialization of core class without it being linked to a type!",
|
||||||
|
@ -301,8 +300,8 @@ impl<'gc> ClassObject<'gc> {
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let object: Object<'gc> = self.into();
|
let object: Object<'gc> = self.into();
|
||||||
|
|
||||||
let class = self.0.read().class;
|
|
||||||
let scope = self.0.read().scope;
|
let scope = self.0.read().scope;
|
||||||
|
let class = self.0.read().class;
|
||||||
let class_read = class.read();
|
let class_read = class.read();
|
||||||
|
|
||||||
if !class_read.is_class_initialized() {
|
if !class_read.is_class_initialized() {
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::avm2::names::Multiname;
|
||||||
use crate::avm2::object::{Object, TObject};
|
use crate::avm2::object::{Object, TObject};
|
||||||
use crate::avm2::value::Value;
|
use crate::avm2::value::Value;
|
||||||
use crate::avm2::Error;
|
use crate::avm2::Error;
|
||||||
use gc_arena::{Collect, Gc, MutationContext};
|
use gc_arena::{Collect, GcCell, MutationContext};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
/// Represents a Scope that can be on either a ScopeChain or local ScopeStack.
|
/// Represents a Scope that can be on either a ScopeChain or local ScopeStack.
|
||||||
|
@ -59,10 +59,13 @@ impl<'gc> Scope<'gc> {
|
||||||
/// ScopeChain's are copy-on-write, meaning when we chain new scopes on top of a ScopeChain, we
|
/// ScopeChain's are copy-on-write, meaning when we chain new scopes on top of a ScopeChain, we
|
||||||
/// actually create a completely brand new ScopeChain. The Domain of the ScopeChain we are chaining
|
/// actually create a completely brand new ScopeChain. The Domain of the ScopeChain we are chaining
|
||||||
/// on top of will be used for the new ScopeChain.
|
/// on top of will be used for the new ScopeChain.
|
||||||
|
///
|
||||||
|
/// Alternatively, the `add` method allows mutating the ScopeChain, but it should be used with caution.
|
||||||
|
/// Mutating a ScopeChain that functions/classes saved could cause bizzare bugs.
|
||||||
#[derive(Debug, Collect, Clone, Copy)]
|
#[derive(Debug, Collect, Clone, Copy)]
|
||||||
#[collect(no_drop)]
|
#[collect(no_drop)]
|
||||||
pub struct ScopeChain<'gc> {
|
pub struct ScopeChain<'gc> {
|
||||||
scopes: Option<Gc<'gc, Vec<Scope<'gc>>>>,
|
scopes: Option<GcCell<'gc, Vec<Scope<'gc>>>>,
|
||||||
domain: Domain<'gc>,
|
domain: Domain<'gc>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,19 +80,15 @@ impl<'gc> ScopeChain<'gc> {
|
||||||
|
|
||||||
/// Creates a new ScopeChain by chaining new scopes on top of this ScopeChain
|
/// Creates a new ScopeChain by chaining new scopes on top of this ScopeChain
|
||||||
pub fn chain(&self, mc: MutationContext<'gc, '_>, new_scopes: &[Scope<'gc>]) -> Self {
|
pub fn chain(&self, mc: MutationContext<'gc, '_>, new_scopes: &[Scope<'gc>]) -> Self {
|
||||||
if new_scopes.is_empty() {
|
|
||||||
// If we are not actually adding any new scopes, we don't need to do anything.
|
|
||||||
return *self;
|
|
||||||
}
|
|
||||||
// TODO: This current implementation is a bit expensive, but it is exactly what avmplus does, so it's good enough for now.
|
// TODO: This current implementation is a bit expensive, but it is exactly what avmplus does, so it's good enough for now.
|
||||||
match self.scopes {
|
match self.scopes {
|
||||||
Some(scopes) => {
|
Some(scopes) => {
|
||||||
// The new ScopeChain is created by cloning the scopes of this ScopeChain,
|
// The new ScopeChain is created by cloning the scopes of this ScopeChain,
|
||||||
// and pushing the new scopes on top of that.
|
// and pushing the new scopes on top of that.
|
||||||
let mut cloned = scopes.deref().clone();
|
let mut cloned = scopes.read().deref().clone();
|
||||||
cloned.extend_from_slice(new_scopes);
|
cloned.extend_from_slice(new_scopes);
|
||||||
Self {
|
Self {
|
||||||
scopes: Some(Gc::allocate(mc, cloned)),
|
scopes: Some(GcCell::allocate(mc, cloned)),
|
||||||
domain: self.domain,
|
domain: self.domain,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,20 +96,33 @@ impl<'gc> ScopeChain<'gc> {
|
||||||
// We are chaining on top of an empty ScopeChain, so we don't actually
|
// We are chaining on top of an empty ScopeChain, so we don't actually
|
||||||
// need to chain anything.
|
// need to chain anything.
|
||||||
Self {
|
Self {
|
||||||
scopes: Some(Gc::allocate(mc, new_scopes.to_vec())),
|
scopes: Some(GcCell::allocate(mc, new_scopes.to_vec())),
|
||||||
domain: self.domain,
|
domain: self.domain,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Adds a new scope to this ScopeChain. Unlike `chain`, this will actually mutate the
|
||||||
|
/// underlying scopes.
|
||||||
|
///
|
||||||
|
/// If this ScopeChain is empty (self.scopes is None), this is a no-op.
|
||||||
|
///
|
||||||
|
/// WARNING: This can cause bizarre bugs, because it can change the saved ScopeChain
|
||||||
|
/// of functions/classes that are using it.
|
||||||
|
pub fn add(&self, mc: MutationContext<'gc, '_>, scope: Scope<'gc>) {
|
||||||
|
self.scopes.map(|scopes| scopes.write(mc).push(scope));
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get(&self, index: usize) -> Option<Scope<'gc>> {
|
pub fn get(&self, index: usize) -> Option<Scope<'gc>> {
|
||||||
self.scopes
|
self.scopes
|
||||||
.and_then(|scopes| scopes.deref().get(index).cloned())
|
.and_then(|scopes| scopes.read().get(index).cloned())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.scopes.map(|scopes| scopes.is_empty()).unwrap_or(true)
|
self.scopes
|
||||||
|
.map(|scopes| scopes.read().is_empty())
|
||||||
|
.unwrap_or(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the domain associated with this ScopeChain.
|
/// Returns the domain associated with this ScopeChain.
|
||||||
|
@ -125,7 +137,7 @@ impl<'gc> ScopeChain<'gc> {
|
||||||
) -> Result<Option<Object<'gc>>, Error> {
|
) -> Result<Option<Object<'gc>>, Error> {
|
||||||
// First search our scopes
|
// First search our scopes
|
||||||
if let Some(scopes) = self.scopes {
|
if let Some(scopes) = self.scopes {
|
||||||
for (depth, scope) in scopes.iter().enumerate().rev() {
|
for (depth, scope) in scopes.read().iter().enumerate().rev() {
|
||||||
let values = scope.values();
|
let values = scope.values();
|
||||||
if let Some(qname) = values.resolve_multiname(name)? {
|
if let Some(qname) = values.resolve_multiname(name)? {
|
||||||
// We search the dynamic properties if either conditions are met:
|
// We search the dynamic properties if either conditions are met:
|
||||||
|
|
|
@ -342,11 +342,7 @@ impl<'gc> Script<'gc> {
|
||||||
let script = script?;
|
let script = script?;
|
||||||
|
|
||||||
for abc_trait in script.traits.iter() {
|
for abc_trait in script.traits.iter() {
|
||||||
drop(write);
|
|
||||||
|
|
||||||
let newtrait = Trait::from_abc_trait(unit, abc_trait, activation)?;
|
let newtrait = Trait::from_abc_trait(unit, abc_trait, activation)?;
|
||||||
|
|
||||||
write = self.0.write(activation.context.gc_context);
|
|
||||||
write.domain.export_definition(
|
write.domain.export_definition(
|
||||||
newtrait.name().clone(),
|
newtrait.name().clone(),
|
||||||
*self,
|
*self,
|
||||||
|
|
Loading…
Reference in New Issue