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
use crate::avm2::domain::Domain;
use crate::avm2::globals::SystemPrototypes;
use crate::avm2::scope::Scope;
use crate::avm2::script::{Script, TranslationUnit};
@ -39,6 +38,7 @@ mod traits;
mod value;
pub use crate::avm2::activation::Activation;
pub use crate::avm2::domain::Domain;
pub use crate::avm2::names::{Namespace, QName};
pub use crate::avm2::object::{Object, StageObject, TObject};
pub use crate::avm2::value::Value;
@ -129,11 +129,11 @@ impl<'gc> Avm2<'gc> {
_abc_name: &str,
_lazy_init: bool,
context: &mut UpdateContext<'_, 'gc, '_>,
domain: GcCell<'gc, Domain<'gc>>,
) -> Result<(), Error> {
let mut read = Reader::new(abc.as_ref());
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);
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 name = reader.read_c_string()?;
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.
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);
}
@ -508,9 +509,12 @@ impl<'gc> MovieClip<'gc> {
if let Some(name) =
Avm2QName::from_symbol_class(&class_name, activation.context.gc_context)
{
//TODO: Store a domain per movie & grab symbols out of that
let globals = activation.context.avm2.global_domain();
let proto = globals
let library = activation
.context
.library
.library_for_movie_mut(movie.clone());
let domain = library.avm2_domain();
let proto = domain
.read()
.get_defined_value(&mut activation, name.clone())
.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::character::Character;
use crate::display_object::TDisplayObject;
@ -5,7 +6,7 @@ use crate::font::{Font, FontDescriptor};
use crate::prelude::*;
use crate::tag_utils::{SwfMovie, SwfSlice};
use crate::vminterface::AvmType;
use gc_arena::{Collect, MutationContext};
use gc_arena::{Collect, GcCell, MutationContext};
use std::collections::HashMap;
use std::sync::{Arc, Weak};
use swf::{CharacterId, TagCode};
@ -24,6 +25,7 @@ pub struct MovieLibrary<'gc> {
device_font: Option<Font<'gc>>,
fonts: HashMap<FontDescriptor, Font<'gc>>,
avm_type: AvmType,
avm2_domain: Option<GcCell<'gc, Avm2Domain<'gc>>>,
}
impl<'gc> MovieLibrary<'gc> {
@ -35,6 +37,7 @@ impl<'gc> MovieLibrary<'gc> {
device_font: None,
fonts: HashMap::new(),
avm_type,
avm2_domain: None,
}
}
@ -220,6 +223,20 @@ impl<'gc> MovieLibrary<'gc> {
pub fn avm_type(&self) -> AvmType {
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.

View File

@ -2,6 +2,7 @@
use crate::avm1::activation::{Activation, ActivationIdentifier};
use crate::avm1::{Avm1, AvmString, Object, TObject, Value};
use crate::avm2::Domain as Avm2Domain;
use crate::backend::navigator::OwnedFuture;
use crate::context::{ActionQueue, ActionType};
use crate::display_object::{DisplayObject, MorphShape, TDisplayObject};
@ -467,7 +468,11 @@ impl<'gc> Loader<'gc> {
.lock()
.expect("Could not lock player!!")
.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) {
Some(Loader::Movie {

View File

@ -3,7 +3,7 @@ use crate::avm1::debug::VariableDumper;
use crate::avm1::globals::system::SystemProperties;
use crate::avm1::object::Object;
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::locale::LocaleBackend;
use crate::backend::navigator::{NavigatorBackend, RequestOptions};
@ -347,7 +347,11 @@ impl Player {
self.instance_counter = 0;
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 =
MovieClip::from_movie(context.gc_context, context.swf.clone()).into();