1- use crate :: core:: JSWeakSet ;
2- use crate :: core:: { Collect , Gc , GcCell , GcPtr , MutationContext , Trace } ;
1+ use crate :: core:: { Gc , GcCell , MutationContext } ;
2+ use crate :: core:: { JSWeakSet , PropertyKey } ;
33use crate :: {
4- core:: { Expr , JSObjectDataPtr , Value , evaluate_expr , obj_get_key_value} ,
4+ core:: { JSObjectDataPtr , Value , env_set , new_js_object_data , obj_get_key_value, obj_set_key_value } ,
55 error:: JSError ,
66 unicode:: utf8_to_utf16,
77} ;
8- use std:: rc:: Rc ;
98
109/// Handle WeakSet constructor calls
1110pub ( crate ) fn handle_weakset_constructor < ' gc > (
1211 mc : & MutationContext < ' gc > ,
13- args : & [ Expr ] ,
12+ args : & [ Value < ' gc > ] ,
1413 env : & JSObjectDataPtr < ' gc > ,
1514) -> Result < Value < ' gc > , JSError > {
1615 let weakset = Gc :: new ( mc, GcCell :: new ( JSWeakSet { values : Vec :: new ( ) } ) ) ;
1716
1817 if !args. is_empty ( ) {
1918 if args. len ( ) == 1 {
20- // WeakSet(iterable)
21- initialize_weakset_from_iterable ( mc, & weakset, args, env ) ?;
19+ // WeakSet(iterable) - args are already evaluated values
20+ initialize_weakset_from_iterable ( mc, & weakset, & args[ 0 ] ) ?;
2221 } else {
2322 return Err ( raise_eval_error ! ( "WeakSet constructor takes at most one argument" ) ) ;
2423 }
2524 }
2625
27- Ok ( Value :: WeakSet ( weakset) )
26+ // Create a wrapper object for the WeakSet
27+ let weakset_obj = new_js_object_data ( mc) ;
28+ // Store the actual weakset data
29+ weakset_obj. borrow_mut ( mc) . insert (
30+ PropertyKey :: String ( "__weakset__" . to_string ( ) ) ,
31+ Gc :: new ( mc, GcCell :: new ( Value :: WeakSet ( weakset) ) ) ,
32+ ) ;
33+
34+ // Set prototype to WeakSet.prototype if available
35+ if let Some ( weakset_ctor) = obj_get_key_value ( env, & "WeakSet" . into ( ) ) ?
36+ && let Value :: Object ( ctor) = & * weakset_ctor. borrow ( )
37+ && let Some ( proto) = obj_get_key_value ( ctor, & "prototype" . into ( ) ) ?
38+ && let Value :: Object ( proto_obj) = & * proto. borrow ( )
39+ {
40+ weakset_obj. borrow_mut ( mc) . prototype = Some ( proto_obj. clone ( ) ) ;
41+ }
42+
43+ Ok ( Value :: Object ( weakset_obj) )
2844}
2945
3046/// Initialize WeakSet from an iterable
3147fn initialize_weakset_from_iterable < ' gc > (
3248 mc : & MutationContext < ' gc > ,
3349 weakset : & Gc < ' gc , GcCell < JSWeakSet < ' gc > > > ,
34- args : & [ Expr ] ,
35- env : & JSObjectDataPtr < ' gc > ,
50+ iterable : & Value < ' gc > ,
3651) -> Result < ( ) , JSError > {
37- let iterable = evaluate_expr ( mc, env, & args[ 0 ] ) ?;
3852 match iterable {
3953 Value :: Object ( obj) => {
4054 let mut i = 0 ;
@@ -63,6 +77,46 @@ fn initialize_weakset_from_iterable<'gc>(
6377 Ok ( ( ) )
6478}
6579
80+ /// Initialize WeakSet constructor and prototype
81+ pub fn initialize_weakset < ' gc > ( mc : & MutationContext < ' gc > , env : & JSObjectDataPtr < ' gc > ) -> Result < ( ) , JSError > {
82+ let weakset_ctor = new_js_object_data ( mc) ;
83+ obj_set_key_value ( mc, & weakset_ctor, & "__is_constructor" . into ( ) , Value :: Boolean ( true ) ) ?;
84+ obj_set_key_value ( mc, & weakset_ctor, & "__native_ctor" . into ( ) , Value :: String ( utf8_to_utf16 ( "WeakSet" ) ) ) ?;
85+
86+ // Get Object.prototype
87+ let object_proto = if let Some ( obj_val) = obj_get_key_value ( env, & "Object" . into ( ) ) ?
88+ && let Value :: Object ( obj_ctor) = & * obj_val. borrow ( )
89+ && let Some ( proto_val) = obj_get_key_value ( obj_ctor, & "prototype" . into ( ) ) ?
90+ && let Value :: Object ( proto) = & * proto_val. borrow ( )
91+ {
92+ Some ( * proto)
93+ } else {
94+ None
95+ } ;
96+
97+ let weakset_proto = new_js_object_data ( mc) ;
98+ if let Some ( proto) = object_proto {
99+ weakset_proto. borrow_mut ( mc) . prototype = Some ( proto) ;
100+ }
101+
102+ obj_set_key_value ( mc, & weakset_ctor, & "prototype" . into ( ) , Value :: Object ( weakset_proto. clone ( ) ) ) ?;
103+ obj_set_key_value ( mc, & weakset_proto, & "constructor" . into ( ) , Value :: Object ( weakset_ctor. clone ( ) ) ) ?;
104+
105+ // Register instance methods
106+ let methods = vec ! [ "add" , "has" , "delete" , "toString" ] ;
107+
108+ for method in methods {
109+ let val = Value :: Function ( format ! ( "WeakSet.prototype.{}" , method) ) ;
110+ obj_set_key_value ( mc, & weakset_proto, & method. into ( ) , val) ?;
111+ weakset_proto. borrow_mut ( mc) . set_non_enumerable ( PropertyKey :: from ( method) ) ;
112+ }
113+ // Mark constructor non-enumerable
114+ weakset_proto. borrow_mut ( mc) . set_non_enumerable ( PropertyKey :: from ( "constructor" ) ) ;
115+
116+ env_set ( mc, env, "WeakSet" , Value :: Object ( weakset_ctor) ) ?;
117+ Ok ( ( ) )
118+ }
119+
66120/// Check if WeakSet has a value and clean up dead entries
67121fn weakset_has_value < ' gc > (
68122 mc : & MutationContext < ' gc > ,
@@ -110,15 +164,14 @@ pub(crate) fn handle_weakset_instance_method<'gc>(
110164 mc : & MutationContext < ' gc > ,
111165 weakset : & Gc < ' gc , GcCell < JSWeakSet < ' gc > > > ,
112166 method : & str ,
113- args : & [ Expr ] ,
114- env : & JSObjectDataPtr < ' gc > ,
167+ args : & [ Value < ' gc > ] ,
115168) -> Result < Value < ' gc > , JSError > {
116169 match method {
117170 "add" => {
118171 if args. len ( ) != 1 {
119172 return Err ( raise_eval_error ! ( "WeakSet.prototype.add requires exactly one argument" ) ) ;
120173 }
121- let value = evaluate_expr ( mc , env , & args[ 0 ] ) ? ;
174+ let value = args[ 0 ] . clone ( ) ;
122175
123176 // Check if value is an object
124177 let value_obj_rc = match value {
@@ -146,7 +199,7 @@ pub(crate) fn handle_weakset_instance_method<'gc>(
146199 if args. len ( ) != 1 {
147200 return Err ( raise_eval_error ! ( "WeakSet.prototype.has requires exactly one argument" ) ) ;
148201 }
149- let value = evaluate_expr ( mc , env , & args[ 0 ] ) ? ;
202+ let value = args[ 0 ] . clone ( ) ;
150203
151204 let value_obj_rc = match value {
152205 Value :: Object ( ref obj) => obj,
@@ -159,7 +212,7 @@ pub(crate) fn handle_weakset_instance_method<'gc>(
159212 if args. len ( ) != 1 {
160213 return Err ( raise_eval_error ! ( "WeakSet.prototype.delete requires exactly one argument" ) ) ;
161214 }
162- let value = evaluate_expr ( mc , env , & args[ 0 ] ) ? ;
215+ let value = args[ 0 ] . clone ( ) ;
163216
164217 let value_obj_rc = match value {
165218 Value :: Object ( ref obj) => obj,
0 commit comments