diff --git a/core/src/avm2/activation.rs b/core/src/avm2/activation.rs index 2e811a3f7c1f..74db2d049353 100644 --- a/core/src/avm2/activation.rs +++ b/core/src/avm2/activation.rs @@ -1696,8 +1696,7 @@ impl<'a, 'gc> Activation<'a, 'gc> { let multiname = multiname.fill_with_runtime_params(self)?; let source = self.pop_stack().null_check(self, Some(&multiname))?; - let ctor = source.get_property(&multiname, self)?; - let constructed_object = ctor.construct(self, args)?; + let constructed_object = source.construct_property(&multiname, args, self)?; self.push_stack(constructed_object); diff --git a/core/src/avm2/value.rs b/core/src/avm2/value.rs index f2177e399da8..4cdab2af68bf 100644 --- a/core/src/avm2/value.rs +++ b/core/src/avm2/value.rs @@ -1217,6 +1217,32 @@ impl<'gc> Value<'gc> { ) } + /// Get a property and use it as a constructor + /// + /// This method will panic if called on null or undefined. + pub fn construct_property( + &self, + multiname: &Multiname<'gc>, + arguments: FunctionArgs<'_, 'gc>, + activation: &mut Activation<'_, 'gc>, + ) -> Result, Error<'gc>> { + let ctor = match self { + Value::Object(obj) if obj.as_namespace_object().is_none() => { + self.get_property(multiname, activation)? + } + _ => self + .get_property(multiname, activation) + .unwrap_or_else(|_| { + // This can only ever run for primitives and namespaces objects, so it should never panic + let proto = self.proto(activation).unwrap(); + + Value::from(proto) + }), + }; + + ctor.construct(activation, arguments) + } + /// Call a method by its index. /// /// This directly corresponds with the AVM2 operation `callmethod`. diff --git a/tests/tests/swfs/from_avmplus/regress/bug_638233/test.toml b/tests/tests/swfs/from_avmplus/regress/bug_638233/test.toml index 29f3cef79022..cf6123969a1d 100644 --- a/tests/tests/swfs/from_avmplus/regress/bug_638233/test.toml +++ b/tests/tests/swfs/from_avmplus/regress/bug_638233/test.toml @@ -1,2 +1 @@ num_ticks = 1 -known_failure = true