@@ -24,8 +24,7 @@ pub(crate) enum BuiltinKind {
2424 Ordinary ,
2525}
2626
27- /// A builtin function. Used for lazy initialization of builtins.
28-
27+ /// A Lazy Built-in data structure. Used for lazy initialization of builtins.
2928#[ derive( Clone , Finalize , Debug ) ]
3029#[ allow( clippy:: type_complexity) ]
3130pub struct LazyBuiltIn {
@@ -44,8 +43,9 @@ impl LazyBuiltIn {
4443 }
4544 }
4645
47- pub ( crate ) fn ensure_init ( mut built_in : Self ) {
48- if let Some ( ( init, realm_inner) ) = built_in. init_and_realm . take ( ) {
46+ pub ( crate ) fn ensure_init ( built_in : & JsObject < LazyBuiltIn > ) {
47+ let borrowed_built_in = built_in. borrow_mut ( ) . data . init_and_realm . take ( ) ;
48+ if let Some ( ( init, realm_inner) ) = borrowed_built_in {
4949 let realm = & Realm {
5050 inner : realm_inner. upgrade ( ) . expect ( "realm_inner not set" ) ,
5151 } ;
@@ -100,7 +100,7 @@ pub(crate) fn lazy_get_prototype_of(
100100 context : & mut Context ,
101101) -> JsResult < JsPrototype > {
102102 let builtin: JsObject < LazyBuiltIn > = obj. clone ( ) . downcast ( ) . expect ( "obj is not a Builtin" ) ;
103- LazyBuiltIn :: ensure_init ( builtin. borrow_mut ( ) . data . clone ( ) ) ;
103+ LazyBuiltIn :: ensure_init ( & builtin) ;
104104 ordinary_get_prototype_of ( obj, context)
105105}
106106
@@ -110,18 +110,18 @@ pub(crate) fn lazy_set_prototype_of(
110110 context : & mut Context ,
111111) -> JsResult < bool > {
112112 let builtin: JsObject < LazyBuiltIn > = obj. clone ( ) . downcast ( ) . expect ( "obj is not a Builtin" ) ;
113- LazyBuiltIn :: ensure_init ( builtin. borrow_mut ( ) . data . clone ( ) ) ;
113+ LazyBuiltIn :: ensure_init ( & builtin) ;
114114 ordinary_set_prototype_of ( obj, prototype, context)
115115}
116116pub ( crate ) fn lazy_is_extensible ( obj : & JsObject , context : & mut Context ) -> JsResult < bool > {
117117 let builtin: JsObject < LazyBuiltIn > = obj. clone ( ) . downcast ( ) . expect ( "obj is not a Builtin" ) ;
118- LazyBuiltIn :: ensure_init ( builtin. borrow_mut ( ) . data . clone ( ) ) ;
118+ LazyBuiltIn :: ensure_init ( & builtin) ;
119119 ordinary_is_extensible ( obj, context)
120120}
121121
122122pub ( crate ) fn lazy_prevent_extensions ( obj : & JsObject , context : & mut Context ) -> JsResult < bool > {
123123 let builtin: JsObject < LazyBuiltIn > = obj. clone ( ) . downcast ( ) . expect ( "obj is not a Builtin" ) ;
124- LazyBuiltIn :: ensure_init ( builtin. borrow_mut ( ) . data . clone ( ) ) ;
124+ LazyBuiltIn :: ensure_init ( & builtin) ;
125125 ordinary_prevent_extensions ( obj, context)
126126}
127127
@@ -131,7 +131,7 @@ pub(crate) fn lazy_get_own_property(
131131 context : & mut InternalMethodContext < ' _ > ,
132132) -> JsResult < Option < PropertyDescriptor > > {
133133 let builtin: JsObject < LazyBuiltIn > = obj. clone ( ) . downcast ( ) . expect ( "obj is not a Builtin" ) ;
134- LazyBuiltIn :: ensure_init ( builtin. borrow_mut ( ) . data . clone ( ) ) ;
134+ LazyBuiltIn :: ensure_init ( & builtin) ;
135135 ordinary_get_own_property ( obj, key, context)
136136}
137137
@@ -142,7 +142,7 @@ pub(crate) fn lazy_define_own_property(
142142 context : & mut InternalMethodContext < ' _ > ,
143143) -> JsResult < bool > {
144144 let builtin: JsObject < LazyBuiltIn > = obj. clone ( ) . downcast ( ) . expect ( "obj is not a Builtin" ) ;
145- LazyBuiltIn :: ensure_init ( builtin. borrow_mut ( ) . data . clone ( ) ) ;
145+ LazyBuiltIn :: ensure_init ( & builtin) ;
146146
147147 ordinary_define_own_property ( obj, key, desc, context)
148148}
@@ -153,7 +153,7 @@ pub(crate) fn lazy_has_property(
153153 context : & mut InternalMethodContext < ' _ > ,
154154) -> JsResult < bool > {
155155 let builtin: JsObject < LazyBuiltIn > = obj. clone ( ) . downcast ( ) . expect ( "obj is not a Builtin" ) ;
156- LazyBuiltIn :: ensure_init ( builtin. borrow_mut ( ) . data . clone ( ) ) ;
156+ LazyBuiltIn :: ensure_init ( & builtin) ;
157157 ordinary_has_property ( obj, key, context)
158158}
159159
@@ -164,7 +164,7 @@ pub(crate) fn lazy_try_get(
164164 context : & mut InternalMethodContext < ' _ > ,
165165) -> JsResult < Option < JsValue > > {
166166 let builtin: JsObject < LazyBuiltIn > = obj. clone ( ) . downcast ( ) . expect ( "obj is not a Builtin" ) ;
167- LazyBuiltIn :: ensure_init ( builtin. borrow_mut ( ) . data . clone ( ) ) ;
167+ LazyBuiltIn :: ensure_init ( & builtin) ;
168168
169169 ordinary_try_get ( obj, key, receiver, context)
170170}
@@ -176,7 +176,7 @@ pub(crate) fn lazy_get(
176176 context : & mut InternalMethodContext < ' _ > ,
177177) -> JsResult < JsValue > {
178178 let builtin: JsObject < LazyBuiltIn > = obj. clone ( ) . downcast ( ) . expect ( "obj is not a Builtin" ) ;
179- LazyBuiltIn :: ensure_init ( builtin. borrow_mut ( ) . data . clone ( ) ) ;
179+ LazyBuiltIn :: ensure_init ( & builtin) ;
180180 ordinary_get ( obj, key, receiver, context)
181181}
182182
@@ -188,7 +188,7 @@ pub(crate) fn lazy_set(
188188 context : & mut InternalMethodContext < ' _ > ,
189189) -> JsResult < bool > {
190190 let builtin: JsObject < LazyBuiltIn > = obj. clone ( ) . downcast ( ) . expect ( "obj is not a Builtin" ) ;
191- LazyBuiltIn :: ensure_init ( builtin. borrow_mut ( ) . data . clone ( ) ) ;
191+ LazyBuiltIn :: ensure_init ( & builtin) ;
192192 ordinary_set ( obj, key, value, receiver, context)
193193}
194194
@@ -198,7 +198,7 @@ pub(crate) fn lazy_delete(
198198 context : & mut InternalMethodContext < ' _ > ,
199199) -> JsResult < bool > {
200200 let builtin: JsObject < LazyBuiltIn > = obj. clone ( ) . downcast ( ) . expect ( "obj is not a Builtin" ) ;
201- LazyBuiltIn :: ensure_init ( builtin. borrow_mut ( ) . data . clone ( ) ) ;
201+ LazyBuiltIn :: ensure_init ( & builtin) ;
202202 ordinary_delete ( obj, key, context)
203203}
204204
@@ -207,7 +207,7 @@ pub(crate) fn lazy_own_property_keys(
207207 context : & mut Context ,
208208) -> JsResult < Vec < PropertyKey > > {
209209 let builtin: JsObject < LazyBuiltIn > = obj. clone ( ) . downcast ( ) . expect ( "obj is not a Builtin" ) ;
210- LazyBuiltIn :: ensure_init ( builtin. borrow_mut ( ) . data . clone ( ) ) ;
210+ LazyBuiltIn :: ensure_init ( & builtin) ;
211211
212212 ordinary_own_property_keys ( obj, context)
213213}
@@ -218,19 +218,20 @@ pub(crate) fn lazy_construct(
218218 context : & mut Context ,
219219) -> JsResult < CallValue > {
220220 let builtin: JsObject < LazyBuiltIn > = obj. clone ( ) . downcast ( ) . expect ( "obj is not a Builtin" ) ;
221- let kind = & builtin. borrow ( ) . data . kind ;
222- LazyBuiltIn :: ensure_init ( builtin. borrow_mut ( ) . data . clone ( ) ) ;
221+ LazyBuiltIn :: ensure_init ( & builtin) ;
222+ let kind = & builtin. borrow ( ) . data . kind . clone ( ) ;
223223
224224 match kind {
225225 BuiltinKind :: Ordinary => Err ( JsNativeError :: typ ( )
226226 . with_message ( "not a constructor" )
227227 . with_realm ( context. realm ( ) . clone ( ) )
228228 . into ( ) ) ,
229- BuiltinKind :: Function ( constructor) => Ok ( ( constructor. internal_methods ( ) . __construct__ ) (
230- obj,
231- argument_count,
232- context,
233- ) ?) ,
229+ BuiltinKind :: Function ( constructor) => {
230+ let construct = constructor. internal_methods ( ) . __construct__ ;
231+ // builtin needs to be dropped before calling the constructor to avoid a double borrow
232+ drop ( builtin) ;
233+ Ok ( construct ( obj, argument_count, context) ?)
234+ }
234235 }
235236}
236237
@@ -240,19 +241,18 @@ pub(crate) fn lazy_call(
240241 context : & mut Context ,
241242) -> JsResult < CallValue > {
242243 let builtin: JsObject < LazyBuiltIn > = obj. clone ( ) . downcast ( ) . expect ( "obj is not a Builtin" ) ;
243- let kind = & builtin. borrow ( ) . data . kind ;
244-
245- LazyBuiltIn :: ensure_init ( builtin. borrow_mut ( ) . data . clone ( ) ) ;
246-
244+ LazyBuiltIn :: ensure_init ( & builtin) ;
245+ let kind = & builtin. borrow ( ) . data . kind . clone ( ) ;
247246 match kind {
248247 BuiltinKind :: Ordinary => Err ( JsNativeError :: typ ( )
249248 . with_message ( "not a constructor" )
250249 . with_realm ( context. realm ( ) . clone ( ) )
251250 . into ( ) ) ,
252- BuiltinKind :: Function ( function) => Ok ( ( function. internal_methods ( ) . __call__ ) (
253- obj,
254- argument_count,
255- context,
256- ) ?) ,
251+ BuiltinKind :: Function ( function) => {
252+ let call = function. internal_methods ( ) . __call__ ;
253+ // builtin needs to be dropped before calling the constructor to avoid a double borrow
254+ drop ( builtin) ;
255+ Ok ( call ( obj, argument_count, context) ?)
256+ }
257257 }
258258}
0 commit comments