From 713ab3e95cae7f38581a8fa74c614e64eb505f4b Mon Sep 17 00:00:00 2001 From: David Wendt Date: Tue, 1 Jun 2021 23:09:54 -0400 Subject: [PATCH] avm2: Remove all remaining accesses to `SystemPrototypes`, save for one technicality with the global scope prototype. --- core/src/avm2/activation.rs | 23 +++++----------- .../avm2/globals/flash/display/loaderinfo.rs | 12 ++++----- core/src/avm2/object.rs | 14 +--------- core/src/avm2/object/function_object.rs | 26 ++++++++++++++++++- 4 files changed, 39 insertions(+), 36 deletions(-) diff --git a/core/src/avm2/activation.rs b/core/src/avm2/activation.rs index 0eef51fa0..5e4dada44 100644 --- a/core/src/avm2/activation.rs +++ b/core/src/avm2/activation.rs @@ -1472,10 +1472,12 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> { } fn op_new_object(&mut self, num_args: u32) -> Result, Error> { - let mut object = ScriptObject::object( - self.context.gc_context, - self.context.avm2.prototypes().object, - ); + let mut object = self + .context + .avm2 + .constructors() + .object + .construct(self, &[])?; for _ in 0..num_args { let value = self.context.avm2.pop(); @@ -1502,18 +1504,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> { let method_entry = self.table_method(method, index, self.context.gc_context)?; let scope = self.scope(); - let mut new_fn = FunctionObject::from_method(self, method_entry.into(), scope, None); - let es3_proto = ScriptObject::object( - self.context.gc_context, - self.context.avm2.prototypes().object, - ); - - new_fn.install_slot( - self.context.gc_context, - QName::new(Namespace::public(), "prototype"), - 0, - es3_proto.into(), - ); + let new_fn = FunctionObject::from_function(self, method_entry.into(), scope)?; self.context.avm2.push(new_fn); diff --git a/core/src/avm2/globals/flash/display/loaderinfo.rs b/core/src/avm2/globals/flash/display/loaderinfo.rs index 231bfb0dc..55165f96d 100644 --- a/core/src/avm2/globals/flash/display/loaderinfo.rs +++ b/core/src/avm2/globals/flash/display/loaderinfo.rs @@ -5,9 +5,7 @@ use crate::avm2::bytearray::Endian; use crate::avm2::class::{Class, ClassAttributes}; use crate::avm2::method::{Method, NativeMethod}; use crate::avm2::names::{Namespace, QName}; -use crate::avm2::object::{ - loaderinfo_deriver, DomainObject, LoaderStream, Object, ScriptObject, TObject, -}; +use crate::avm2::object::{loaderinfo_deriver, DomainObject, LoaderStream, Object, TObject}; use crate::avm2::value::Value; use crate::avm2::{AvmString, Error}; use crate::display_object::TDisplayObject; @@ -378,9 +376,11 @@ pub fn parameters<'gc>( return Err("Error: The stage's loader info does not have parameters".into()) } LoaderStream::Swf(root, _) => { - let object_proto = activation.context.avm2.prototypes().object; - let mut params_obj = - ScriptObject::object(activation.context.gc_context, object_proto); + let mut params_obj = activation + .avm2() + .constructors() + .object + .construct(activation, &[])?; let parameters = root.parameters(); for (k, v) in parameters.iter() { diff --git a/core/src/avm2/object.rs b/core/src/avm2/object.rs index de348eb86..d10390755 100644 --- a/core/src/avm2/object.rs +++ b/core/src/avm2/object.rs @@ -634,19 +634,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into> + Clone + Copy TraitKind::Function { slot_id, function, .. } => { - let mut fobject = - FunctionObject::from_method(activation, function.clone(), scope, None); - let es3_proto = ScriptObject::object( - activation.context.gc_context, - activation.avm2().prototypes().object, - ); - - fobject.install_slot( - activation.context.gc_context, - QName::new(Namespace::public(), "prototype"), - 0, - es3_proto.into(), - ); + let fobject = FunctionObject::from_function(activation, function.clone(), scope)?; self.install_const( activation.context.gc_context, trait_name, diff --git a/core/src/avm2/object/function_object.rs b/core/src/avm2/object/function_object.rs index fd1e33602..b45435caa 100644 --- a/core/src/avm2/object/function_object.rs +++ b/core/src/avm2/object/function_object.rs @@ -5,7 +5,7 @@ use crate::avm2::class::Class; use crate::avm2::function::Executable; use crate::avm2::method::Method; use crate::avm2::names::{Namespace, QName}; -use crate::avm2::object::script_object::{ScriptObjectClass, ScriptObjectData}; +use crate::avm2::object::script_object::{ScriptObject, ScriptObjectClass, ScriptObjectData}; use crate::avm2::object::{Object, ObjectPtr, TObject}; use crate::avm2::scope::Scope; use crate::avm2::string::AvmString; @@ -33,6 +33,30 @@ pub struct FunctionObjectData<'gc> { impl<'gc> FunctionObject<'gc> { /// Construct a function from an ABC method and the current closure scope. /// + /// This associated constructor will also create and initialize an empty + /// `Object` prototype for the function. + pub fn from_function( + activation: &mut Activation<'_, 'gc, '_>, + method: Method<'gc>, + scope: Option>>, + ) -> Result, Error> { + let mut this = Self::from_method(activation, method, scope, None); + let es3_proto = ScriptObject::object( + activation.context.gc_context, + activation.avm2().prototypes().object, + ); + + this.install_slot( + activation.context.gc_context, + QName::new(Namespace::public(), "prototype"), + 0, + es3_proto.into(), + ); + + Ok(this) + } + /// Construct a method from an ABC method and the current closure scope. + /// /// The given `reciever`, if supplied, will override any user-specified /// `this` parameter. pub fn from_method(