1+ use crate :: JsValue ;
12use crate :: value:: JsVariant ;
23use crate :: vm:: opcode:: VaryingOperand ;
34use crate :: {
@@ -9,6 +10,77 @@ use crate::{
910} ;
1011use boa_macros:: js_str;
1112
13+ fn set_by_name (
14+ value : VaryingOperand ,
15+ value_object : & JsValue ,
16+ receiver : & JsValue ,
17+ index : VaryingOperand ,
18+ context : & mut Context ,
19+ ) -> JsResult < ( ) > {
20+ let value = context. vm . get_register ( value. into ( ) ) . clone ( ) ;
21+
22+ let object = value_object. to_object ( context) ?;
23+
24+ let ic = & context. vm . frame ( ) . code_block ( ) . ic [ usize:: from ( index) ] ;
25+
26+ let object_borrowed = object. borrow ( ) ;
27+ if let Some ( ( shape, slot) ) = ic. match_or_reset ( object_borrowed. shape ( ) ) {
28+ let slot_index = slot. index as usize ;
29+
30+ if slot. attributes . is_accessor_descriptor ( ) {
31+ let result = if slot. attributes . contains ( SlotAttributes :: PROTOTYPE ) {
32+ let prototype = shape. prototype ( ) . expect ( "prototype should have value" ) ;
33+ let prototype = prototype. borrow ( ) ;
34+
35+ prototype. properties ( ) . storage [ slot_index + 1 ] . clone ( )
36+ } else {
37+ object_borrowed. properties ( ) . storage [ slot_index + 1 ] . clone ( )
38+ } ;
39+
40+ drop ( object_borrowed) ;
41+ if slot. attributes . has_set ( ) && result. is_object ( ) {
42+ result. as_object ( ) . expect ( "should contain getter" ) . call (
43+ receiver,
44+ std:: slice:: from_ref ( & value) ,
45+ context,
46+ ) ?;
47+ }
48+ } else if slot. attributes . contains ( SlotAttributes :: PROTOTYPE ) {
49+ let prototype = shape. prototype ( ) . expect ( "prototype should have value" ) ;
50+ let mut prototype = prototype. borrow_mut ( ) ;
51+
52+ prototype. properties_mut ( ) . storage [ slot_index] = value. clone ( ) ;
53+ } else {
54+ drop ( object_borrowed) ;
55+ let mut object_borrowed = object. borrow_mut ( ) ;
56+ object_borrowed. properties_mut ( ) . storage [ slot_index] = value. clone ( ) ;
57+ }
58+ return Ok ( ( ) ) ;
59+ }
60+ drop ( object_borrowed) ;
61+
62+ let name: PropertyKey = ic. name . clone ( ) . into ( ) ;
63+
64+ let context = & mut InternalMethodPropertyContext :: new ( context) ;
65+ let succeeded = object. __set__ ( name. clone ( ) , value. clone ( ) , receiver. clone ( ) , context) ?;
66+ if !succeeded && context. vm . frame ( ) . code_block . strict ( ) {
67+ return Err ( JsNativeError :: typ ( )
68+ . with_message ( format ! ( "cannot set non-writable property: {name}" ) )
69+ . into ( ) ) ;
70+ }
71+
72+ // Cache the property.
73+ let slot = * context. slot ( ) ;
74+ if succeeded && slot. is_cachable ( ) {
75+ let ic = & context. vm . frame ( ) . code_block . ic [ usize:: from ( index) ] ;
76+ let object_borrowed = object. borrow ( ) ;
77+ let shape = object_borrowed. shape ( ) ;
78+ ic. set ( shape, slot) ;
79+ }
80+
81+ Ok ( ( ) )
82+ }
83+
1284/// `SetPropertyByName` implements the Opcode Operation for `Opcode::SetPropertyByName`
1385///
1486/// Operation:
@@ -22,68 +94,8 @@ impl SetPropertyByName {
2294 ( value, object, index) : ( VaryingOperand , VaryingOperand , VaryingOperand ) ,
2395 context : & mut Context ,
2496 ) -> JsResult < ( ) > {
25- let value = context. vm . get_register ( value. into ( ) ) . clone ( ) ;
26- let value_object = context. vm . get_register ( object. into ( ) ) . clone ( ) ;
27- let object = value_object. to_object ( context) ?;
28-
29- let ic = & context. vm . frame ( ) . code_block ( ) . ic [ usize:: from ( index) ] ;
30-
31- let object_borrowed = object. borrow ( ) ;
32- if let Some ( ( shape, slot) ) = ic. match_or_reset ( object_borrowed. shape ( ) ) {
33- let slot_index = slot. index as usize ;
34-
35- if slot. attributes . is_accessor_descriptor ( ) {
36- let result = if slot. attributes . contains ( SlotAttributes :: PROTOTYPE ) {
37- let prototype = shape. prototype ( ) . expect ( "prototype should have value" ) ;
38- let prototype = prototype. borrow ( ) ;
39-
40- prototype. properties ( ) . storage [ slot_index + 1 ] . clone ( )
41- } else {
42- object_borrowed. properties ( ) . storage [ slot_index + 1 ] . clone ( )
43- } ;
44-
45- drop ( object_borrowed) ;
46- if slot. attributes . has_set ( ) && result. is_object ( ) {
47- result. as_object ( ) . expect ( "should contain getter" ) . call (
48- & value_object,
49- & [ value] ,
50- context,
51- ) ?;
52- }
53- } else if slot. attributes . contains ( SlotAttributes :: PROTOTYPE ) {
54- let prototype = shape. prototype ( ) . expect ( "prototype should have value" ) ;
55- let mut prototype = prototype. borrow_mut ( ) ;
56-
57- prototype. properties_mut ( ) . storage [ slot_index] = value. clone ( ) ;
58- } else {
59- drop ( object_borrowed) ;
60- let mut object_borrowed = object. borrow_mut ( ) ;
61- object_borrowed. properties_mut ( ) . storage [ slot_index] = value. clone ( ) ;
62- }
63- return Ok ( ( ) ) ;
64- }
65- drop ( object_borrowed) ;
66-
67- let name: PropertyKey = ic. name . clone ( ) . into ( ) ;
68-
69- let context = & mut InternalMethodPropertyContext :: new ( context) ;
70- let succeeded = object. __set__ ( name. clone ( ) , value. clone ( ) , value_object, context) ?;
71- if !succeeded && context. vm . frame ( ) . code_block . strict ( ) {
72- return Err ( JsNativeError :: typ ( )
73- . with_message ( format ! ( "cannot set non-writable property: {name}" ) )
74- . into ( ) ) ;
75- }
76-
77- // Cache the property.
78- let slot = * context. slot ( ) ;
79- if succeeded && slot. is_cachable ( ) {
80- let ic = & context. vm . frame ( ) . code_block . ic [ usize:: from ( index) ] ;
81- let object_borrowed = object. borrow ( ) ;
82- let shape = object_borrowed. shape ( ) ;
83- ic. set ( shape, slot) ;
84- }
85-
86- Ok ( ( ) )
97+ let object = context. vm . get_register ( object. into ( ) ) . clone ( ) ;
98+ set_by_name ( value, & object, & object, index, context)
8799 }
88100}
89101
@@ -111,69 +123,9 @@ impl SetPropertyByNameWithThis {
111123 ) ,
112124 context : & mut Context ,
113125 ) -> JsResult < ( ) > {
114- let value = context. vm . get_register ( value. into ( ) ) . clone ( ) ;
115- let receiver = context. vm . get_register ( receiver. into ( ) ) . clone ( ) ;
116126 let value_object = context. vm . get_register ( object. into ( ) ) . clone ( ) ;
117- let object = value_object. to_object ( context) ?;
118-
119- let ic = & context. vm . frame ( ) . code_block ( ) . ic [ usize:: from ( index) ] ;
120-
121- let object_borrowed = object. borrow ( ) ;
122- if let Some ( ( shape, slot) ) = ic. match_or_reset ( object_borrowed. shape ( ) ) {
123- let slot_index = slot. index as usize ;
124-
125- if slot. attributes . is_accessor_descriptor ( ) {
126- let result = if slot. attributes . contains ( SlotAttributes :: PROTOTYPE ) {
127- let prototype = shape. prototype ( ) . expect ( "prototype should have value" ) ;
128- let prototype = prototype. borrow ( ) ;
129-
130- prototype. properties ( ) . storage [ slot_index + 1 ] . clone ( )
131- } else {
132- object_borrowed. properties ( ) . storage [ slot_index + 1 ] . clone ( )
133- } ;
134-
135- drop ( object_borrowed) ;
136- if slot. attributes . has_set ( ) && result. is_object ( ) {
137- result. as_object ( ) . expect ( "should contain getter" ) . call (
138- & receiver,
139- std:: slice:: from_ref ( & value) ,
140- context,
141- ) ?;
142- }
143- } else if slot. attributes . contains ( SlotAttributes :: PROTOTYPE ) {
144- let prototype = shape. prototype ( ) . expect ( "prototype should have value" ) ;
145- let mut prototype = prototype. borrow_mut ( ) ;
146-
147- prototype. properties_mut ( ) . storage [ slot_index] = value. clone ( ) ;
148- } else {
149- drop ( object_borrowed) ;
150- let mut object_borrowed = object. borrow_mut ( ) ;
151- object_borrowed. properties_mut ( ) . storage [ slot_index] = value. clone ( ) ;
152- }
153- return Ok ( ( ) ) ;
154- }
155- drop ( object_borrowed) ;
156-
157- let name: PropertyKey = ic. name . clone ( ) . into ( ) ;
158-
159- let context = & mut InternalMethodPropertyContext :: new ( context) ;
160- let succeeded = object. __set__ ( name. clone ( ) , value. clone ( ) , receiver. clone ( ) , context) ?;
161- if !succeeded && context. vm . frame ( ) . code_block . strict ( ) {
162- return Err ( JsNativeError :: typ ( )
163- . with_message ( format ! ( "cannot set non-writable property: {name}" ) )
164- . into ( ) ) ;
165- }
166-
167- // Cache the property.
168- let slot = * context. slot ( ) ;
169- if succeeded && slot. is_cachable ( ) {
170- let ic = & context. vm . frame ( ) . code_block . ic [ usize:: from ( index) ] ;
171- let object_borrowed = object. borrow ( ) ;
172- let shape = object_borrowed. shape ( ) ;
173- ic. set ( shape, slot) ;
174- }
175-
176- Ok ( ( ) )
127+ let receiver = context. vm . get_register ( receiver. into ( ) ) . clone ( ) ;
128+ set_by_name ( value, & value_object, & receiver, index, context)
177129 }
178130}
179131
0 commit comments