@@ -15,19 +15,45 @@ mod tests;
1515use super :: function:: { make_builtin_fn, make_constructor_fn} ;
1616use crate :: {
1717 builtins:: {
18- object:: { internal_methods_trait :: ObjectInternalMethods , ObjectKind } ,
18+ object:: ObjectData ,
1919 value:: { ResultValue , Value , ValueData } ,
2020 } ,
2121 exec:: Interpreter ,
2222 BoaProfiler ,
2323} ;
24- use std:: { borrow:: Borrow , ops:: Deref } ;
2524
2625/// Boolean implementation.
2726#[ derive( Debug , Clone , Copy ) ]
2827pub ( crate ) struct Boolean ;
2928
3029impl Boolean {
30+ /// The name of the object.
31+ pub ( crate ) const NAME : & ' static str = "Boolean" ;
32+
33+ /// The amount of arguments this function object takes.
34+ pub ( crate ) const LENGTH : usize = 1 ;
35+
36+ /// An Utility function used to get the internal [[BooleanData]].
37+ ///
38+ /// More information:
39+ /// - [ECMAScript reference][spec]
40+ ///
41+ /// [spec]: https://tc39.es/ecma262/#sec-thisbooleanvalue
42+ fn this_boolean_value ( value : & Value , ctx : & mut Interpreter ) -> Result < bool , Value > {
43+ match value. data ( ) {
44+ ValueData :: Boolean ( boolean) => return Ok ( * boolean) ,
45+ ValueData :: Object ( ref object) => {
46+ let object = object. borrow ( ) ;
47+ if let Some ( boolean) = object. as_boolean ( ) {
48+ return Ok ( boolean) ;
49+ }
50+ }
51+ _ => { }
52+ }
53+
54+ Err ( ctx. construct_type_error ( "'this' is not a boolean" ) )
55+ }
56+
3157 /// `[[Construct]]` Create a new boolean object
3258 ///
3359 /// `[[Call]]` Creates a new boolean primitive
@@ -36,19 +62,11 @@ impl Boolean {
3662 args : & [ Value ] ,
3763 _: & mut Interpreter ,
3864 ) -> ResultValue {
39- this. set_kind ( ObjectKind :: Boolean ) ;
40-
4165 // Get the argument, if any
42- if let Some ( ref value) = args. get ( 0 ) {
43- this. set_internal_slot ( "BooleanData" , Self :: to_boolean ( value) ) ;
44- } else {
45- this. set_internal_slot ( "BooleanData" , Self :: to_boolean ( & Value :: from ( false ) ) ) ;
46- }
66+ let data = args. get ( 0 ) . map ( |x| x. to_boolean ( ) ) . unwrap_or ( false ) ;
67+ this. set_data ( ObjectData :: Boolean ( data) ) ;
4768
48- match args. get ( 0 ) {
49- Some ( ref value) => Ok ( Self :: to_boolean ( value) ) ,
50- None => Ok ( Self :: to_boolean ( & Value :: from ( false ) ) ) ,
51- }
69+ Ok ( Value :: from ( data) )
5270 }
5371
5472 /// The `toString()` method returns a string representing the specified `Boolean` object.
@@ -60,9 +78,9 @@ impl Boolean {
6078 /// [spec]: https://tc39.es/ecma262/#sec-boolean-object
6179 /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean/toString
6280 #[ allow( clippy:: wrong_self_convention) ]
63- pub ( crate ) fn to_string ( this : & mut Value , _: & [ Value ] , _ : & mut Interpreter ) -> ResultValue {
64- let b = Self :: this_boolean_value ( this) ;
65- Ok ( Value :: from ( b . to_string ( ) ) )
81+ pub ( crate ) fn to_string ( this : & mut Value , _: & [ Value ] , ctx : & mut Interpreter ) -> ResultValue {
82+ let boolean = Self :: this_boolean_value ( this, ctx ) ? ;
83+ Ok ( Value :: from ( boolean . to_string ( ) ) )
6684 }
6785
6886 /// The valueOf() method returns the primitive value of a `Boolean` object.
@@ -73,52 +91,23 @@ impl Boolean {
7391 ///
7492 /// [spec]: https://tc39.es/ecma262/#sec-boolean.prototype.valueof
7593 /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean/valueOf
76- pub ( crate ) fn value_of ( this : & mut Value , _: & [ Value ] , _: & mut Interpreter ) -> ResultValue {
77- Ok ( Self :: this_boolean_value ( this) )
78- }
79-
80- // === Utility Functions ===
81- /// [toBoolean](https://tc39.es/ecma262/#sec-toboolean)
82- /// Creates a new boolean value from the input
83- #[ allow( clippy:: wrong_self_convention) ]
84- pub ( crate ) fn to_boolean ( value : & Value ) -> Value {
85- match * value. deref ( ) . borrow ( ) {
86- ValueData :: Object ( _) => Value :: from ( true ) ,
87- ValueData :: String ( ref s) if !s. is_empty ( ) => Value :: from ( true ) ,
88- ValueData :: Rational ( n) if n != 0.0 && !n. is_nan ( ) => Value :: from ( true ) ,
89- ValueData :: Integer ( n) if n != 0 => Value :: from ( true ) ,
90- ValueData :: Boolean ( v) => Value :: from ( v) ,
91- _ => Value :: from ( false ) ,
92- }
93- }
94-
95- /// An Utility function used to get the internal BooleanData.
96- ///
97- /// More information:
98- /// - [ECMAScript reference][spec]
99- ///
100- /// [spec]: https://tc39.es/ecma262/#sec-thisbooleanvalue
101- pub ( crate ) fn this_boolean_value ( value : & Value ) -> Value {
102- match * value. deref ( ) . borrow ( ) {
103- ValueData :: Boolean ( v) => Value :: from ( v) ,
104- ValueData :: Object ( ref v) => ( v) . deref ( ) . borrow ( ) . get_internal_slot ( "BooleanData" ) ,
105- _ => Value :: from ( false ) ,
106- }
94+ #[ inline]
95+ pub ( crate ) fn value_of ( this : & mut Value , _: & [ Value ] , ctx : & mut Interpreter ) -> ResultValue {
96+ Ok ( Value :: from ( Self :: this_boolean_value ( this, ctx) ?) )
10797 }
10898
10999 /// Create a new `Boolean` object.
110100 pub ( crate ) fn create ( global : & Value ) -> Value {
111101 // Create Prototype
112102 // https://tc39.es/ecma262/#sec-properties-of-the-boolean-prototype-object
113103 let prototype = Value :: new_object ( Some ( global) ) ;
114- prototype. set_internal_slot ( "BooleanData" , Self :: to_boolean ( & Value :: from ( false ) ) ) ;
115104
116105 make_builtin_fn ( Self :: to_string, "toString" , & prototype, 0 ) ;
117106 make_builtin_fn ( Self :: value_of, "valueOf" , & prototype, 0 ) ;
118107
119108 make_constructor_fn (
120- "Boolean" ,
121- 1 ,
109+ Self :: NAME ,
110+ Self :: LENGTH ,
122111 Self :: construct_boolean,
123112 global,
124113 prototype,
@@ -128,8 +117,9 @@ impl Boolean {
128117
129118 /// Initialise the `Boolean` object on the global object.
130119 #[ inline]
131- pub ( crate ) fn init ( global : & Value ) {
132- let _timer = BoaProfiler :: global ( ) . start_event ( "boolean" , "init" ) ;
133- global. set_field ( "Boolean" , Self :: create ( global) ) ;
120+ pub ( crate ) fn init ( global : & Value ) -> ( & str , Value ) {
121+ let _timer = BoaProfiler :: global ( ) . start_event ( Self :: NAME , "init" ) ;
122+
123+ ( Self :: NAME , Self :: create ( global) )
134124 }
135125}
0 commit comments