@@ -1146,6 +1146,8 @@ pub fn evaluate_expr<'gc>(mc: &MutationContext<'gc>, env: &JSObjectDataPtr<'gc>,
11461146 let key_val_res = evaluate_expr ( mc, env, key_expr) ?;
11471147
11481148 let key = match key_val_res {
1149+ Value :: String ( s) => PropertyKey :: String ( utf16_to_utf8 ( & s) ) ,
1150+ Value :: Number ( n) => PropertyKey :: String ( n. to_string ( ) ) ,
11491151 Value :: Symbol ( s) => PropertyKey :: Symbol ( s) ,
11501152 _ => PropertyKey :: from ( value_to_string ( & key_val_res) ) ,
11511153 } ;
@@ -1704,15 +1706,19 @@ pub fn evaluate_expr<'gc>(mc: &MutationContext<'gc>, env: &JSObjectDataPtr<'gc>,
17041706 if let Some ( method) = name. strip_prefix ( "Object.prototype." ) {
17051707 let this_v = this_val. clone ( ) . unwrap_or ( Value :: Undefined ) ;
17061708 match method {
1707- "valueOf" => Ok ( crate :: js_object:: handle_value_of_method ( mc, & this_v, args, env) . map_err ( EvalError :: Js ) ?) ,
1708- "toString" => Ok ( crate :: js_object:: handle_to_string_method ( mc, & this_v, args, env) . map_err ( EvalError :: Js ) ?) ,
1709+ "valueOf" => {
1710+ Ok ( crate :: js_object:: handle_value_of_method ( mc, & this_v, & eval_args, env) . map_err ( EvalError :: Js ) ?)
1711+ }
1712+ "toString" => {
1713+ Ok ( crate :: js_object:: handle_to_string_method ( mc, & this_v, & eval_args, env) . map_err ( EvalError :: Js ) ?)
1714+ }
17091715 "toLocaleString" => {
1710- Ok ( crate :: js_object:: handle_to_string_method ( mc, & this_v, args , env) . map_err ( EvalError :: Js ) ?)
1716+ Ok ( crate :: js_object:: handle_to_string_method ( mc, & this_v, & eval_args , env) . map_err ( EvalError :: Js ) ?)
17111717 }
17121718 "hasOwnProperty" | "isPrototypeOf" | "propertyIsEnumerable" => {
17131719 // Need object wrapper
17141720 if let Value :: Object ( o) = this_v {
1715- let res_opt = crate :: js_object:: handle_object_prototype_builtin ( mc, & name, & o, args , env)
1721+ let res_opt = crate :: js_object:: handle_object_prototype_builtin ( mc, & name, & o, & eval_args , env)
17161722 . map_err ( EvalError :: Js ) ?;
17171723 Ok ( res_opt. unwrap_or ( Value :: Undefined ) )
17181724 } else {
@@ -1725,7 +1731,7 @@ pub fn evaluate_expr<'gc>(mc: &MutationContext<'gc>, env: &JSObjectDataPtr<'gc>,
17251731 }
17261732 } else {
17271733 let method = & name[ 7 ..] ;
1728- Ok ( crate :: js_object:: handle_object_method ( mc, method, args , env) . map_err ( EvalError :: Js ) ?)
1734+ Ok ( crate :: js_object:: handle_object_method ( mc, method, & eval_args , env) . map_err ( EvalError :: Js ) ?)
17291735 }
17301736 } else if name. starts_with ( "Array." ) {
17311737 if let Some ( method) = name. strip_prefix ( "Array.prototype." ) {
@@ -2078,11 +2084,10 @@ pub fn evaluate_expr<'gc>(mc: &MutationContext<'gc>, env: &JSObjectDataPtr<'gc>,
20782084 }
20792085 }
20802086 let mut body_clone = cl. body . clone ( ) ;
2081- let result = evaluate_statements ( mc, & call_env, & mut body_clone) ?;
2082- if let Value :: Object ( _) = result {
2083- Ok ( result)
2084- } else {
2085- Ok ( Value :: Object ( instance) )
2087+ match evaluate_statements_with_labels ( mc, & call_env, & mut body_clone, & [ ] , & [ ] ) ? {
2088+ ControlFlow :: Return ( Value :: Object ( obj) ) => Ok ( Value :: Object ( obj) ) ,
2089+ ControlFlow :: Throw ( val, line, col) => Err ( EvalError :: Throw ( val, line, col) ) ,
2090+ _ => Ok ( Value :: Object ( instance) ) ,
20862091 }
20872092 }
20882093 _ => Err ( EvalError :: Js ( raise_eval_error ! ( "Not a constructor" ) ) ) ,
@@ -2330,6 +2335,143 @@ pub fn evaluate_expr<'gc>(mc: &MutationContext<'gc>, env: &JSObjectDataPtr<'gc>,
23302335 Ok ( crate :: js_class:: evaluate_super_method ( mc, env, prop, & eval_args) . map_err ( EvalError :: Js ) ?)
23312336 }
23322337 Expr :: Super => Ok ( crate :: js_class:: evaluate_super ( mc, env) . map_err ( EvalError :: Js ) ?) ,
2338+ Expr :: OptionalProperty ( lhs, prop) => {
2339+ let left_val = evaluate_expr ( mc, env, lhs) ?;
2340+ if left_val. is_null_or_undefined ( ) {
2341+ Ok ( Value :: Undefined )
2342+ } else {
2343+ if let Value :: Object ( obj) = & left_val {
2344+ if let Some ( val_rc) = crate :: core:: obj_get_key_value ( & obj, & prop. into ( ) ) . map_err ( EvalError :: Js ) ? {
2345+ Ok ( val_rc. borrow ( ) . clone ( ) )
2346+ } else {
2347+ Ok ( Value :: Undefined )
2348+ }
2349+ } else {
2350+ get_primitive_prototype_property ( mc, env, & left_val, & prop. into ( ) )
2351+ }
2352+ }
2353+ }
2354+ Expr :: OptionalIndex ( lhs, index_expr) => {
2355+ let left_val = evaluate_expr ( mc, env, lhs) ?;
2356+ if left_val. is_null_or_undefined ( ) {
2357+ Ok ( Value :: Undefined )
2358+ } else {
2359+ let index_val = evaluate_expr ( mc, env, index_expr) ?;
2360+ let prop_key = match index_val {
2361+ Value :: Symbol ( s) => crate :: core:: PropertyKey :: Symbol ( s) ,
2362+ Value :: String ( s) => crate :: core:: PropertyKey :: String ( crate :: unicode:: utf16_to_utf8 ( & s) ) ,
2363+ val => {
2364+ let s = match val {
2365+ Value :: Number ( n) => n. to_string ( ) ,
2366+ Value :: Boolean ( b) => b. to_string ( ) ,
2367+ Value :: Undefined => "undefined" . to_string ( ) ,
2368+ Value :: Null => "null" . to_string ( ) ,
2369+ _ => crate :: core:: value_to_string ( & val) ,
2370+ } ;
2371+ crate :: core:: PropertyKey :: String ( s)
2372+ }
2373+ } ;
2374+ if let Value :: Object ( obj) = & left_val {
2375+ if let Some ( val_rc) = crate :: core:: obj_get_key_value ( & obj, & prop_key) . map_err ( EvalError :: Js ) ? {
2376+ Ok ( val_rc. borrow ( ) . clone ( ) )
2377+ } else {
2378+ Ok ( Value :: Undefined )
2379+ }
2380+ } else {
2381+ get_primitive_prototype_property ( mc, env, & left_val, & prop_key)
2382+ }
2383+ }
2384+ }
2385+ Expr :: OptionalCall ( lhs, args) => {
2386+ let left_val = evaluate_expr ( mc, env, lhs) ?;
2387+ if left_val. is_null_or_undefined ( ) {
2388+ Ok ( Value :: Undefined )
2389+ } else {
2390+ let mut eval_args = Vec :: new ( ) ;
2391+ for arg in args {
2392+ eval_args. push ( evaluate_expr ( mc, env, arg) ?) ;
2393+ }
2394+ match left_val {
2395+ Value :: Function ( name) => {
2396+ crate :: js_function:: handle_global_function ( mc, & name, & eval_args, & env. clone ( ) ) . map_err ( EvalError :: Js )
2397+ }
2398+ Value :: Closure ( c) => call_closure ( mc, & c, None , & eval_args, env) ,
2399+ _ => Err ( EvalError :: Js ( crate :: raise_type_error!( "OptionalCall target is not a function" ) ) ) ,
2400+ }
2401+ }
2402+ }
2403+ Expr :: Delete ( target) => match & * * target {
2404+ Expr :: Property ( obj_expr, key) => {
2405+ let obj_val = evaluate_expr ( mc, env, obj_expr) ?;
2406+ if let Value :: Object ( obj) = obj_val {
2407+ let key_val = PropertyKey :: from ( key. to_string ( ) ) ;
2408+ let removed = obj. borrow_mut ( mc) . properties . shift_remove ( & key_val) . is_some ( ) ;
2409+ Ok ( Value :: Boolean ( removed) )
2410+ } else {
2411+ Ok ( Value :: Boolean ( true ) )
2412+ }
2413+ }
2414+ Expr :: Index ( obj_expr, key_expr) => {
2415+ let obj_val = evaluate_expr ( mc, env, obj_expr) ?;
2416+ let key_val_res = evaluate_expr ( mc, env, key_expr) ?;
2417+ let key = match key_val_res {
2418+ Value :: String ( s) => PropertyKey :: String ( utf16_to_utf8 ( & s) ) ,
2419+ Value :: Number ( n) => PropertyKey :: String ( n. to_string ( ) ) ,
2420+ Value :: Symbol ( s) => PropertyKey :: Symbol ( s) ,
2421+ _ => PropertyKey :: from ( value_to_string ( & key_val_res) ) ,
2422+ } ;
2423+ if let Value :: Object ( obj) = obj_val {
2424+ let removed = obj. borrow_mut ( mc) . properties . shift_remove ( & key) . is_some ( ) ;
2425+ Ok ( Value :: Boolean ( removed) )
2426+ } else {
2427+ Ok ( Value :: Boolean ( true ) )
2428+ }
2429+ }
2430+ Expr :: Var ( _name, _, _) => Ok ( Value :: Boolean ( false ) ) ,
2431+ _ => Ok ( Value :: Boolean ( true ) ) ,
2432+ } ,
2433+ Expr :: Getter ( func_expr) => {
2434+ let val = evaluate_expr ( mc, env, func_expr) ?;
2435+ let closure = match & val {
2436+ Value :: Object ( obj) => {
2437+ let c_val = obj_get_key_value ( obj, & "__closure__" . into ( ) ) ?;
2438+ if let Some ( c_ptr) = c_val {
2439+ let c_ref = c_ptr. borrow ( ) ;
2440+ if let Value :: Closure ( c) = & * c_ref {
2441+ * c
2442+ } else {
2443+ panic ! ( "Getter function missing __closure__ (not a closure)" ) ;
2444+ }
2445+ } else {
2446+ panic ! ( "Getter function missing __closure__" ) ;
2447+ }
2448+ }
2449+ Value :: Closure ( c) => * c,
2450+ _ => panic ! ( "Expr::Getter evaluated to invalid value: {:?}" , val) ,
2451+ } ;
2452+ Ok ( Value :: Getter ( closure. body . clone ( ) , closure. env , None ) )
2453+ }
2454+ Expr :: Setter ( func_expr) => {
2455+ let val = evaluate_expr ( mc, env, func_expr) ?;
2456+ let closure = match & val {
2457+ Value :: Object ( obj) => {
2458+ let c_val = obj_get_key_value ( obj, & "__closure__" . into ( ) ) ?;
2459+ if let Some ( c_ptr) = c_val {
2460+ let c_ref = c_ptr. borrow ( ) ;
2461+ if let Value :: Closure ( c) = & * c_ref {
2462+ * c
2463+ } else {
2464+ panic ! ( "Setter function missing __closure__ (not a closure)" ) ;
2465+ }
2466+ } else {
2467+ panic ! ( "Setter function missing __closure__" ) ;
2468+ }
2469+ }
2470+ Value :: Closure ( c) => * c,
2471+ _ => panic ! ( "Expr::Setter evaluated to invalid value: {:?}" , val) ,
2472+ } ;
2473+ Ok ( Value :: Setter ( closure. params . clone ( ) , closure. body . clone ( ) , closure. env , None ) )
2474+ }
23332475 _ => todo ! ( "{expr:?}" ) ,
23342476 }
23352477}
@@ -2605,6 +2747,16 @@ fn call_accessor<'gc>(
26052747 let mut body_clone = cl_data. body . clone ( ) ;
26062748 evaluate_statements ( mc, & call_env, & mut body_clone)
26072749 }
2750+ Value :: Object ( obj) => {
2751+ // Check for __closure__
2752+ let cl_val_opt = crate :: core:: obj_get_key_value ( obj, & "__closure__" . into ( ) ) . map_err ( EvalError :: Js ) ?;
2753+ if let Some ( cl_val) = cl_val_opt {
2754+ if let Value :: Closure ( cl) = & * cl_val. borrow ( ) {
2755+ return call_accessor ( mc, env, receiver, & Value :: Closure ( * cl) ) ;
2756+ }
2757+ }
2758+ Err ( EvalError :: Js ( crate :: raise_type_error!( "Accessor is not a function" ) ) )
2759+ }
26082760 _ => Err ( EvalError :: Js ( crate :: raise_type_error!( "Accessor is not a function" ) ) ) ,
26092761 }
26102762}
@@ -2632,6 +2784,16 @@ fn call_setter<'gc>(
26322784 let mut body_clone = cl_data. body . clone ( ) ;
26332785 evaluate_statements ( mc, & call_env, & mut body_clone) . map ( |_| ( ) )
26342786 }
2787+ Value :: Object ( obj) => {
2788+ // Check for __closure__
2789+ let cl_val_opt = crate :: core:: obj_get_key_value ( obj, & "__closure__" . into ( ) ) . map_err ( EvalError :: Js ) ?;
2790+ if let Some ( cl_val) = cl_val_opt {
2791+ if let Value :: Closure ( cl) = & * cl_val. borrow ( ) {
2792+ return call_setter ( mc, receiver, & Value :: Closure ( * cl) , val) ;
2793+ }
2794+ }
2795+ Err ( EvalError :: Js ( crate :: raise_type_error!( "Setter is not a function" ) ) )
2796+ }
26352797 _ => Err ( EvalError :: Js ( crate :: raise_type_error!( "Setter is not a function" ) ) ) ,
26362798 }
26372799}
0 commit comments