From 6bfca1af5f9812c3bdbdb7efa71c39c563d4cacf Mon Sep 17 00:00:00 2001 From: David Wendt Date: Tue, 16 Nov 2021 17:36:55 -0500 Subject: [PATCH] avm2: Expose `Boolean` methods in the `public` namespace via prototypes. --- core/src/avm2/globals/boolean.rs | 49 +++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/core/src/avm2/globals/boolean.rs b/core/src/avm2/globals/boolean.rs index 6e1497607..fd2b523bd 100644 --- a/core/src/avm2/globals/boolean.rs +++ b/core/src/avm2/globals/boolean.rs @@ -4,7 +4,7 @@ use crate::avm2::activation::Activation; use crate::avm2::class::Class; use crate::avm2::method::{Method, NativeMethodImpl}; use crate::avm2::names::{Namespace, QName}; -use crate::avm2::object::{primitive_allocator, Object, TObject}; +use crate::avm2::object::{primitive_allocator, FunctionObject, Object, TObject}; use crate::avm2::value::Value; use crate::avm2::Error; use gc_arena::{GcCell, MutationContext}; @@ -46,10 +46,44 @@ pub fn native_instance_init<'gc>( /// Implements `Boolean`'s class initializer. pub fn class_init<'gc>( - _activation: &mut Activation<'_, 'gc, '_>, - _this: Option>, + activation: &mut Activation<'_, 'gc, '_>, + this: Option>, _args: &[Value<'gc>], ) -> Result, Error> { + if let Some(this) = this { + let mut boolean_proto = this + .get_property(this, &QName::dynamic_name("prototype").into(), activation)? + .coerce_to_object(activation)?; + let scope = activation.create_scopechain(); + let gc_context = activation.context.gc_context; + let this_class = this.as_class_object().unwrap(); + + boolean_proto.install_dynamic_property( + gc_context, + QName::new(Namespace::public(), "toString"), + FunctionObject::from_method( + activation, + Method::from_builtin(to_string, "toString", gc_context), + scope, + None, + Some(this_class), + ) + .into(), + )?; + boolean_proto.install_dynamic_property( + gc_context, + QName::new(Namespace::public(), "valueOf"), + FunctionObject::from_method( + activation, + Method::from_builtin(value_of, "valueOf", gc_context), + scope, + None, + Some(this_class), + ) + .into(), + )?; + } + Ok(Value::Undefined) } @@ -61,14 +95,15 @@ pub fn to_string<'gc>( ) -> Result, Error> { if let Some(this) = this { if let Some(this) = this.as_primitive() { - match this.coerce_to_boolean() { - true => return Ok("true".into()), - false => return Ok("false".into()), + match this.clone() { + Value::Bool(true) => return Ok("true".into()), + Value::Bool(false) => return Ok("false".into()), + _ => {} }; } } - Ok(Value::Undefined) + Err("Boolean.prototype.toString has been called on an incompatible object".into()) } /// Implements `Boolean.valueOf`