From 69a4d103386c3026f39b50d511c0e2ec3f7b1bd6 Mon Sep 17 00:00:00 2001 From: Nathan Adams Date: Mon, 27 Jul 2020 23:02:35 +0200 Subject: [PATCH] avm1: Replace manual constructor calling with Function::construct, to ensure we set __constructor__ --- core/src/avm1/globals.rs | 42 ++++++++++++++-------- core/src/avm1/globals/array.rs | 3 +- core/src/avm1/globals/context_menu.rs | 10 ++++-- core/src/avm1/globals/context_menu_item.rs | 5 +-- core/src/avm1/globals/matrix.rs | 6 ++-- core/src/avm1/globals/point.rs | 6 ++-- core/src/avm1/globals/rectangle.rs | 9 +++-- core/src/avm1/globals/shared_object.rs | 10 +++--- 8 files changed, 60 insertions(+), 31 deletions(-) diff --git a/core/src/avm1/globals.rs b/core/src/avm1/globals.rs index a93f2cd40..4b307c462 100644 --- a/core/src/avm1/globals.rs +++ b/core/src/avm1/globals.rs @@ -207,24 +207,31 @@ pub fn update_after_event<'a, 'gc>( pub struct SystemPrototypes<'gc> { pub button: Object<'gc>, pub object: Object<'gc>, + pub object_constructor: Object<'gc>, pub function: Object<'gc>, pub movie_clip: Object<'gc>, pub sound: Object<'gc>, pub text_field: Object<'gc>, pub text_format: Object<'gc>, pub array: Object<'gc>, + pub array_constructor: Object<'gc>, pub xml_node: Object<'gc>, pub string: Object<'gc>, pub number: Object<'gc>, pub boolean: Object<'gc>, pub matrix: Object<'gc>, + pub matrix_constructor: Object<'gc>, pub point: Object<'gc>, + pub point_constructor: Object<'gc>, pub rectangle: Object<'gc>, pub rectangle_constructor: Object<'gc>, pub shared_object: Object<'gc>, + pub shared_object_constructor: Object<'gc>, pub color_transform: Object<'gc>, pub context_menu: Object<'gc>, + pub context_menu_constructor: Object<'gc>, pub context_menu_item: Object<'gc>, + pub context_menu_item_constructor: Object<'gc>, } /// Initialize default global scope and builtins for an AVM1 instance. @@ -442,29 +449,29 @@ pub fn create_globals<'gc>( DontEnum.into(), ); + let context_menu = FunctionObject::constructor( + gc_context, + Executable::Native(context_menu::constructor), + Some(function_proto), + Some(context_menu_proto), + ); globals.define_value( gc_context, "ContextMenu", - FunctionObject::constructor( - gc_context, - Executable::Native(context_menu::constructor), - Some(function_proto), - Some(context_menu_proto), - ) - .into(), + context_menu.into(), DontEnum.into(), ); + let context_menu_item = FunctionObject::constructor( + gc_context, + Executable::Native(context_menu_item::constructor), + Some(function_proto), + Some(context_menu_item_proto), + ); globals.define_value( gc_context, "ContextMenuItem", - FunctionObject::constructor( - gc_context, - Executable::Native(context_menu_item::constructor), - Some(function_proto), - Some(context_menu_item_proto), - ) - .into(), + context_menu_item.into(), DontEnum.into(), ); @@ -610,24 +617,31 @@ pub fn create_globals<'gc>( SystemPrototypes { button: button_proto, object: object_proto, + object_constructor: object, function: function_proto, movie_clip: movie_clip_proto, sound: sound_proto, text_field: text_field_proto, text_format: text_format_proto, array: array_proto, + array_constructor: array, xml_node: xmlnode_proto, string: string_proto, number: number_proto, boolean: boolean_proto, matrix: matrix_proto, + matrix_constructor: matrix, point: point_proto, + point_constructor: point, rectangle: rectangle_proto, rectangle_constructor: rectangle, shared_object: shared_object_proto, + shared_object_constructor: shared_obj, color_transform: color_transform_proto, context_menu: context_menu_proto, + context_menu_constructor: context_menu, context_menu_item: context_menu_item_proto, + context_menu_item_constructor: context_menu_item, }, globals.into(), broadcaster_functions, diff --git a/core/src/avm1/globals/array.rs b/core/src/avm1/globals/array.rs index b1ef72393..575351706 100644 --- a/core/src/avm1/globals/array.rs +++ b/core/src/avm1/globals/array.rs @@ -138,7 +138,8 @@ pub fn array_function<'gc>( let p = activation.avm.prototypes.array; let array_obj = p.new(activation, context, p, &[])?; - let _ = constructor(activation, context, array_obj, args)?; + let constructor = activation.avm.prototypes.array_constructor; + constructor.construct(activation, context, array_obj, args)?; if args.len() == 1 { let arg = args.get(0).unwrap(); diff --git a/core/src/avm1/globals/context_menu.rs b/core/src/avm1/globals/context_menu.rs index bd9b6ad9a..f71528348 100644 --- a/core/src/avm1/globals/context_menu.rs +++ b/core/src/avm1/globals/context_menu.rs @@ -22,7 +22,9 @@ pub fn constructor<'gc>( let obj_proto = activation.avm.prototypes.object; let built_in_items = obj_proto.new(activation, context, obj_proto, &[])?; - let _ = crate::avm1::globals::object::constructor(activation, context, built_in_items, &[]); + let constructor = activation.avm.prototypes.object_constructor; + constructor.construct(activation, context, built_in_items, &[])?; + built_in_items.set("print", true.into(), activation, context)?; built_in_items.set("forward_back", true.into(), activation, context)?; built_in_items.set("rewind", true.into(), activation, context)?; @@ -36,7 +38,8 @@ pub fn constructor<'gc>( let array_proto = activation.avm.prototypes.array; let custom_items = array_proto.new(activation, context, array_proto, &[])?; - let _ = crate::avm1::globals::array::constructor(activation, context, custom_items, &[]); + let constructor = activation.avm.prototypes.array_constructor; + constructor.construct(activation, context, custom_items, &[])?; this.set("customItems", custom_items.into(), activation, context)?; @@ -55,7 +58,8 @@ pub fn copy<'gc>( let context_menu_proto = activation.avm.prototypes.context_menu; let copy = context_menu_proto.new(activation, context, context_menu_proto, &[])?; - let _ = constructor(activation, context, copy, &[callback.into()]); + let constructor = activation.avm.prototypes.context_menu_constructor; + constructor.construct(activation, context, copy, &[callback.into()])?; let built_in = this .get("builtInItems", activation, context)? diff --git a/core/src/avm1/globals/context_menu_item.rs b/core/src/avm1/globals/context_menu_item.rs index bb6ab007f..1d9bc8013 100644 --- a/core/src/avm1/globals/context_menu_item.rs +++ b/core/src/avm1/globals/context_menu_item.rs @@ -87,7 +87,8 @@ pub fn copy<'gc>( let context_menu_item_proto = activation.avm.prototypes.context_menu_item; let copy = context_menu_item_proto.new(activation, context, context_menu_item_proto, &[])?; - let _ = constructor( + let constructor = activation.avm.prototypes.context_menu_item_constructor; + constructor.construct( activation, context, copy, @@ -98,7 +99,7 @@ pub fn copy<'gc>( enabled.into(), visible.into(), ], - ); + )?; Ok(copy.into()) } diff --git a/core/src/avm1/globals/matrix.rs b/core/src/avm1/globals/matrix.rs index 2089dc2cb..de0bf9ef7 100644 --- a/core/src/avm1/globals/matrix.rs +++ b/core/src/avm1/globals/matrix.rs @@ -132,7 +132,8 @@ pub fn matrix_to_object<'gc>( matrix.ty.to_pixels().into(), ]; let object = proto.new(activation, context, proto, &args)?; - let _ = constructor(activation, context, object, &args)?; + let constructor = activation.avm.prototypes.matrix_constructor; + constructor.construct(activation, context, object, &args)?; Ok(object) } @@ -209,7 +210,8 @@ fn clone<'gc>( this.get("ty", activation, context)?, ]; let cloned = proto.new(activation, context, proto, &args)?; - let _ = constructor(activation, context, cloned, &args)?; + let constructor = activation.avm.prototypes.matrix_constructor; + constructor.construct(activation, context, cloned, &args)?; Ok(cloned.into()) } diff --git a/core/src/avm1/globals/point.rs b/core/src/avm1/globals/point.rs index bedbde081..ed9c6b19e 100644 --- a/core/src/avm1/globals/point.rs +++ b/core/src/avm1/globals/point.rs @@ -26,7 +26,8 @@ pub fn construct_new_point<'gc>( ) -> Result, Error<'gc>> { let proto = context.system_prototypes.point; let object = proto.new(activation, context, proto, &args)?; - let _ = constructor(activation, context, object, &args)?; + let constructor = activation.avm.prototypes.point_constructor; + constructor.construct(activation, context, object, &args)?; Ok(object) } @@ -99,7 +100,8 @@ fn clone<'gc>( this.get("y", activation, context)?, ]; let cloned = proto.new(activation, context, proto, &args)?; - let _ = constructor(activation, context, cloned, &args)?; + let constructor = activation.avm.prototypes.point_constructor; + constructor.construct(activation, context, proto, &args)?; Ok(cloned.into()) } diff --git a/core/src/avm1/globals/rectangle.rs b/core/src/avm1/globals/rectangle.rs index 6f7a191dd..39197c198 100644 --- a/core/src/avm1/globals/rectangle.rs +++ b/core/src/avm1/globals/rectangle.rs @@ -131,7 +131,8 @@ fn clone<'gc>( this.get("height", activation, context)?, ]; let cloned = proto.new(activation, context, proto, &args)?; - let _ = constructor(activation, context, cloned, &args)?; + let constructor = activation.avm.prototypes.rectangle_constructor; + constructor.construct(activation, context, cloned, &args)?; Ok(cloned.into()) } @@ -390,7 +391,8 @@ fn union<'gc>( Value::Number(height), ]; let result = proto.new(activation, context, proto, &args)?; - let _ = constructor(activation, context, result, &args)?; + let constructor = activation.avm.prototypes.rectangle_constructor; + constructor.construct(activation, context, result, &args)?; Ok(result.into()) } @@ -613,7 +615,8 @@ fn intersection<'gc>( Value::Number(bottom - top), ]; let result = proto.new(activation, context, proto, &args)?; - let _ = constructor(activation, context, result, &args)?; + let constructor = activation.avm.prototypes.rectangle_constructor; + constructor.construct(activation, context, result, &args)?; Ok(result.into()) } diff --git a/core/src/avm1/globals/shared_object.rs b/core/src/avm1/globals/shared_object.rs index 779c61a55..9ac8c4fd0 100644 --- a/core/src/avm1/globals/shared_object.rs +++ b/core/src/avm1/globals/shared_object.rs @@ -116,8 +116,8 @@ fn recursive_deserialize<'gc>( JsonValue::Object(o) => { let so = activation.avm.prototypes.object; let obj = so.new(activation, context, so, &[]).unwrap(); - let _ = crate::avm1::globals::object::constructor(activation, context, obj, &[]) - .unwrap(); + let constructor = activation.avm.prototypes.object_constructor; + let _ = constructor.construct(activation, context, obj, &[]); recursive_deserialize(JsonValue::Object(o.clone()), activation, obj, context); object.define_value( @@ -160,7 +160,8 @@ pub fn get_local<'gc>( // Data property only should exist when created with getLocal/Remote let so = activation.avm.prototypes.shared_object; let this = so.new(activation, action_context, so, &[])?; - let _ = constructor(activation, action_context, this, &[])?; + let constructor = activation.avm.prototypes.shared_object_constructor; + constructor.construct(activation, action_context, this, &[])?; // Set the internal name let obj_so = this.as_shared_object().unwrap(); @@ -169,7 +170,8 @@ pub fn get_local<'gc>( // Create the data object let data_proto = activation.avm.prototypes.object; let data = data_proto.new(activation, action_context, so, &[])?; - let _ = crate::avm1::globals::object::constructor(activation, action_context, data, &[])?; + let constructor = activation.avm.prototypes.object_constructor; + constructor.construct(activation, action_context, data, &[])?; // Load the data object from storage if it existed prior if let Some(saved) = action_context.storage.get_string(&name) {