@@ -4,6 +4,7 @@ use crate::core::{Gc, GcCell, MutationContext};
44use crate :: js_array:: handle_array_static_method;
55use crate :: js_bigint:: bigint_constructor;
66use crate :: js_date:: { handle_date_method, handle_date_static_method} ;
7+ use crate :: js_number:: { handle_number_instance_method, handle_number_prototype_method, handle_number_static_method, number_constructor} ;
78use crate :: js_os:: handle_os_method;
89use crate :: js_string:: { string_from_char_code, string_from_code_point, string_raw} ;
910use crate :: {
@@ -503,6 +504,8 @@ pub fn evaluate_expr<'gc>(mc: &MutationContext<'gc>, env: &JSObjectDataPtr<'gc>,
503504 Expr :: Number ( n) => Ok ( Value :: Number ( * n) ) ,
504505 Expr :: StringLit ( s) => Ok ( Value :: String ( s. clone ( ) ) ) ,
505506 Expr :: Boolean ( b) => Ok ( Value :: Boolean ( * b) ) ,
507+ Expr :: Null => Ok ( Value :: Null ) ,
508+ Expr :: Undefined => Ok ( Value :: Undefined ) ,
506509 Expr :: Var ( name, _, _) => Ok ( evaluate_var ( mc, env, name) ?) ,
507510 Expr :: Assign ( target, value_expr) => {
508511 let val = evaluate_expr ( mc, env, value_expr) ?;
@@ -737,6 +740,10 @@ pub fn evaluate_expr<'gc>(mc: &MutationContext<'gc>, env: &JSObjectDataPtr<'gc>,
737740 Ok ( crate :: js_bigint:: handle_bigint_object_method ( this_v, method, & eval_args) . map_err ( EvalError :: Js ) ?)
738741 } else if let Some ( method) = name. strip_prefix ( "BigInt." ) {
739742 Ok ( crate :: js_bigint:: handle_bigint_static_method ( method, & eval_args, env) . map_err ( EvalError :: Js ) ?)
743+ } else if let Some ( method) = name. strip_prefix ( "Number.prototype." ) {
744+ Ok ( handle_number_prototype_method ( this_val. clone ( ) , method, & eval_args) . map_err ( EvalError :: Js ) ?)
745+ } else if let Some ( method) = name. strip_prefix ( "Number." ) {
746+ Ok ( handle_number_static_method ( method, & eval_args) . map_err ( EvalError :: Js ) ?)
740747 } else if let Some ( method) = name. strip_prefix ( "Math." ) {
741748 Ok ( handle_math_call ( mc, method, & eval_args, env) . map_err ( EvalError :: Js ) ?)
742749 } else if let Some ( method) = name. strip_prefix ( "Date.prototype." ) {
@@ -877,6 +884,8 @@ pub fn evaluate_expr<'gc>(mc: &MutationContext<'gc>, env: &JSObjectDataPtr<'gc>,
877884 Value :: String ( name) => {
878885 if name == & crate :: unicode:: utf8_to_utf16 ( "String" ) {
879886 Ok ( crate :: js_string:: string_constructor ( mc, & eval_args, env) ?)
887+ } else if name == & crate :: unicode:: utf8_to_utf16 ( "Number" ) {
888+ Ok ( number_constructor ( & eval_args, env) . map_err ( EvalError :: Js ) ?)
880889 } else if name == & crate :: unicode:: utf8_to_utf16 ( "BigInt" ) {
881890 Ok ( bigint_constructor ( & eval_args, env) ?)
882891 } else {
@@ -933,6 +942,21 @@ pub fn evaluate_expr<'gc>(mc: &MutationContext<'gc>, env: &JSObjectDataPtr<'gc>,
933942 } ;
934943
935944 return Ok ( crate :: core:: js_error:: create_error ( mc, prototype, msg) ?) ;
945+ } else if name == & crate :: unicode:: utf8_to_utf16 ( "Number" ) {
946+ let val = match number_constructor ( & eval_args, env) . map_err ( EvalError :: Js ) ? {
947+ Value :: Number ( n) => n,
948+ _ => f64:: NAN ,
949+ } ;
950+ let new_obj = crate :: core:: new_js_object_data ( mc) ;
951+ obj_set_key_value ( mc, & new_obj, & "__value__" . into ( ) , Value :: Number ( val) ) ?;
952+
953+ if let Some ( proto_val) = obj_get_key_value ( & obj, & "prototype" . into ( ) ) ?
954+ && let Value :: Object ( proto_obj) = & * proto_val. borrow ( )
955+ {
956+ new_obj. borrow_mut ( mc) . prototype = Some ( * proto_obj) ;
957+ }
958+
959+ return Ok ( Value :: Object ( new_obj) ) ;
936960 } else if name == & crate :: unicode:: utf8_to_utf16 ( "Date" ) {
937961 return Ok ( crate :: js_date:: handle_date_constructor ( mc, & eval_args, env) ?) ;
938962 }
@@ -1023,6 +1047,50 @@ pub fn evaluate_expr<'gc>(mc: &MutationContext<'gc>, env: &JSObjectDataPtr<'gc>,
10231047 Err ( EvalError :: Js ( raise_eval_error ! ( "Unary Negation only for numbers" ) ) )
10241048 }
10251049 }
1050+ Expr :: TypeOf ( expr) => {
1051+ // typeof handles ReferenceError for undeclared variables
1052+ let val_result = evaluate_expr ( mc, env, expr) ;
1053+ let val = match val_result {
1054+ Ok ( v) => v,
1055+ Err ( e) => {
1056+ // Check if it is a ReferenceError (simplistic check for now, assuming EvalError could be it)
1057+ // Ideally we check if the error kind is ReferenceError.
1058+ // For now, if evaluation fails, return undefined (as string "undefined")
1059+ // This covers `typeof nonExistentVar` -> "undefined"
1060+ Value :: Undefined
1061+ }
1062+ } ;
1063+
1064+ let type_str = match val {
1065+ Value :: Number ( _) => "number" ,
1066+ Value :: String ( _) => "string" ,
1067+ Value :: Boolean ( _) => "boolean" ,
1068+ Value :: Undefined | Value :: Uninitialized => "undefined" ,
1069+ Value :: Null => "object" ,
1070+ Value :: Symbol ( _) => "symbol" ,
1071+ Value :: BigInt ( _) => "bigint" ,
1072+ Value :: Function ( _)
1073+ | Value :: Closure ( _)
1074+ | Value :: AsyncClosure ( _)
1075+ | Value :: GeneratorFunction ( ..)
1076+ | Value :: ClassDefinition ( _) => "function" ,
1077+ Value :: Object ( obj) => {
1078+ if obj_get_key_value ( & obj, & "__closure__" . into ( ) ) . unwrap_or ( None ) . is_some ( ) {
1079+ "function"
1080+ } else if let Some ( is_ctor) = obj_get_key_value ( & obj, & "__is_constructor" . into ( ) ) . unwrap_or ( None ) {
1081+ if matches ! ( * is_ctor. borrow( ) , Value :: Boolean ( true ) ) {
1082+ "function"
1083+ } else {
1084+ "object"
1085+ }
1086+ } else {
1087+ "object"
1088+ }
1089+ }
1090+ _ => "undefined" ,
1091+ } ;
1092+ Ok ( Value :: String ( utf8_to_utf16 ( type_str) ) )
1093+ }
10261094 _ => Ok ( Value :: Undefined ) ,
10271095 }
10281096}
0 commit comments