avm2: Create a separate domain for each loaded movie and pull symbols out of each.

This commit is contained in:
David Wendt 2020-10-06 23:48:43 -04:00 committed by Mike Welsh
parent cdab885979
commit 0d1676afda
5 changed files with 40 additions and 10 deletions

View File

@ -1,6 +1,5 @@
//! ActionScript Virtual Machine 2 (AS3) support //! ActionScript Virtual Machine 2 (AS3) support
use crate::avm2::domain::Domain;
use crate::avm2::globals::SystemPrototypes; use crate::avm2::globals::SystemPrototypes;
use crate::avm2::scope::Scope; use crate::avm2::scope::Scope;
use crate::avm2::script::{Script, TranslationUnit}; use crate::avm2::script::{Script, TranslationUnit};
@ -39,6 +38,7 @@ mod traits;
mod value; mod value;
pub use crate::avm2::activation::Activation; pub use crate::avm2::activation::Activation;
pub use crate::avm2::domain::Domain;
pub use crate::avm2::names::{Namespace, QName}; pub use crate::avm2::names::{Namespace, QName};
pub use crate::avm2::object::{Object, StageObject, TObject}; pub use crate::avm2::object::{Object, StageObject, TObject};
pub use crate::avm2::value::Value; pub use crate::avm2::value::Value;
@ -129,11 +129,11 @@ impl<'gc> Avm2<'gc> {
_abc_name: &str, _abc_name: &str,
_lazy_init: bool, _lazy_init: bool,
context: &mut UpdateContext<'_, 'gc, '_>, context: &mut UpdateContext<'_, 'gc, '_>,
domain: GcCell<'gc, Domain<'gc>>,
) -> Result<(), Error> { ) -> Result<(), Error> {
let mut read = Reader::new(abc.as_ref()); let mut read = Reader::new(abc.as_ref());
let abc_file = Rc::new(read.read()?); let abc_file = Rc::new(read.read()?);
let domain = Domain::movie_domain(context.gc_context, context.avm2.globals);
let tunit = TranslationUnit::from_abc(abc_file.clone(), domain, context.gc_context); let tunit = TranslationUnit::from_abc(abc_file.clone(), domain, context.gc_context);
for i in (0..abc_file.scripts.len()).rev() { for i in (0..abc_file.scripts.len()).rev() {

View File

@ -466,6 +466,7 @@ impl<'gc> MovieClip<'gc> {
let flags = reader.read_u32()?; let flags = reader.read_u32()?;
let name = reader.read_c_string()?; let name = reader.read_c_string()?;
let is_lazy_initialize = flags & 1 != 0; let is_lazy_initialize = flags & 1 != 0;
let domain = library.avm2_domain();
// The rest of the tag is an ABC file so we can take our SwfSlice now. // The rest of the tag is an ABC file so we can take our SwfSlice now.
let slice = self let slice = self
@ -481,7 +482,7 @@ impl<'gc> MovieClip<'gc> {
) )
})?; })?;
if let Err(e) = Avm2::load_abc(slice, &name, is_lazy_initialize, context) { if let Err(e) = Avm2::load_abc(slice, &name, is_lazy_initialize, context, domain) {
log::warn!("Error loading ABC file: {}", e); log::warn!("Error loading ABC file: {}", e);
} }
@ -508,9 +509,12 @@ impl<'gc> MovieClip<'gc> {
if let Some(name) = if let Some(name) =
Avm2QName::from_symbol_class(&class_name, activation.context.gc_context) Avm2QName::from_symbol_class(&class_name, activation.context.gc_context)
{ {
//TODO: Store a domain per movie & grab symbols out of that let library = activation
let globals = activation.context.avm2.global_domain(); .context
let proto = globals .library
.library_for_movie_mut(movie.clone());
let domain = library.avm2_domain();
let proto = domain
.read() .read()
.get_defined_value(&mut activation, name.clone()) .get_defined_value(&mut activation, name.clone())
.and_then(|v| v.coerce_to_object(&mut activation)); .and_then(|v| v.coerce_to_object(&mut activation));

View File

@ -1,3 +1,4 @@
use crate::avm2::Domain as Avm2Domain;
use crate::backend::audio::SoundHandle; use crate::backend::audio::SoundHandle;
use crate::character::Character; use crate::character::Character;
use crate::display_object::TDisplayObject; use crate::display_object::TDisplayObject;
@ -5,7 +6,7 @@ use crate::font::{Font, FontDescriptor};
use crate::prelude::*; use crate::prelude::*;
use crate::tag_utils::{SwfMovie, SwfSlice}; use crate::tag_utils::{SwfMovie, SwfSlice};
use crate::vminterface::AvmType; use crate::vminterface::AvmType;
use gc_arena::{Collect, MutationContext}; use gc_arena::{Collect, GcCell, MutationContext};
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
use swf::{CharacterId, TagCode}; use swf::{CharacterId, TagCode};
@ -24,6 +25,7 @@ pub struct MovieLibrary<'gc> {
device_font: Option<Font<'gc>>, device_font: Option<Font<'gc>>,
fonts: HashMap<FontDescriptor, Font<'gc>>, fonts: HashMap<FontDescriptor, Font<'gc>>,
avm_type: AvmType, avm_type: AvmType,
avm2_domain: Option<GcCell<'gc, Avm2Domain<'gc>>>,
} }
impl<'gc> MovieLibrary<'gc> { impl<'gc> MovieLibrary<'gc> {
@ -35,6 +37,7 @@ impl<'gc> MovieLibrary<'gc> {
device_font: None, device_font: None,
fonts: HashMap::new(), fonts: HashMap::new(),
avm_type, avm_type,
avm2_domain: None,
} }
} }
@ -220,6 +223,20 @@ impl<'gc> MovieLibrary<'gc> {
pub fn avm_type(&self) -> AvmType { pub fn avm_type(&self) -> AvmType {
self.avm_type self.avm_type
} }
pub fn set_avm2_domain(&mut self, avm2_domain: GcCell<'gc, Avm2Domain<'gc>>) {
self.avm2_domain = Some(avm2_domain);
}
/// Get the AVM2 domain this movie runs under.
///
/// Note that the presence of an AVM2 domain does *not* indicate that this
/// movie provides AVM2 code. For example, a movie may have been loaded by
/// AVM2 code into a particular domain, even though it turned out to be
/// an AVM1 movie, and thus this domain is unused.
pub fn avm2_domain(&self) -> GcCell<'gc, Avm2Domain<'gc>> {
self.avm2_domain.unwrap()
}
} }
/// Symbol library for multiple movies. /// Symbol library for multiple movies.

View File

@ -2,6 +2,7 @@
use crate::avm1::activation::{Activation, ActivationIdentifier}; use crate::avm1::activation::{Activation, ActivationIdentifier};
use crate::avm1::{Avm1, AvmString, Object, TObject, Value}; use crate::avm1::{Avm1, AvmString, Object, TObject, Value};
use crate::avm2::Domain as Avm2Domain;
use crate::backend::navigator::OwnedFuture; use crate::backend::navigator::OwnedFuture;
use crate::context::{ActionQueue, ActionType}; use crate::context::{ActionQueue, ActionType};
use crate::display_object::{DisplayObject, MorphShape, TDisplayObject}; use crate::display_object::{DisplayObject, MorphShape, TDisplayObject};
@ -467,7 +468,11 @@ impl<'gc> Loader<'gc> {
.lock() .lock()
.expect("Could not lock player!!") .expect("Could not lock player!!")
.update(|uc| { .update(|uc| {
uc.library.library_for_movie_mut(movie.clone()); let domain =
Avm2Domain::movie_domain(uc.gc_context, uc.avm2.global_domain());
uc.library
.library_for_movie_mut(movie.clone())
.set_avm2_domain(domain);
let (clip, broadcaster) = match uc.load_manager.get_loader(handle) { let (clip, broadcaster) = match uc.load_manager.get_loader(handle) {
Some(Loader::Movie { Some(Loader::Movie {

View File

@ -3,7 +3,7 @@ use crate::avm1::debug::VariableDumper;
use crate::avm1::globals::system::SystemProperties; use crate::avm1::globals::system::SystemProperties;
use crate::avm1::object::Object; use crate::avm1::object::Object;
use crate::avm1::{Avm1, AvmString, ScriptObject, TObject, Timers, Value}; use crate::avm1::{Avm1, AvmString, ScriptObject, TObject, Timers, Value};
use crate::avm2::Avm2; use crate::avm2::{Avm2, Domain as Avm2Domain};
use crate::backend::input::{InputBackend, MouseCursor}; use crate::backend::input::{InputBackend, MouseCursor};
use crate::backend::locale::LocaleBackend; use crate::backend::locale::LocaleBackend;
use crate::backend::navigator::{NavigatorBackend, RequestOptions}; use crate::backend::navigator::{NavigatorBackend, RequestOptions};
@ -347,7 +347,11 @@ impl Player {
self.instance_counter = 0; self.instance_counter = 0;
self.mutate_with_update_context(|context| { self.mutate_with_update_context(|context| {
context.library.library_for_movie_mut(context.swf.clone()); let domain = Avm2Domain::movie_domain(context.gc_context, context.avm2.global_domain());
context
.library
.library_for_movie_mut(context.swf.clone())
.set_avm2_domain(domain);
let root: DisplayObject = let root: DisplayObject =
MovieClip::from_movie(context.gc_context, context.swf.clone()).into(); MovieClip::from_movie(context.gc_context, context.swf.clone()).into();