@@ -100,6 +100,12 @@ impl Engine {
100100 }
101101
102102 /// Get the value at the indexed position of a base type.
103+ ///
104+ /// # Panics
105+ ///
106+ /// Panics if the target object is shared.
107+ ///
108+ /// Shared objects should be handled (dereferenced) before calling this method.
103109 fn get_indexed_mut < ' t > (
104110 & self ,
105111 global : & mut GlobalRuntimeState ,
@@ -430,10 +436,10 @@ impl Engine {
430436 let value = self
431437 . eval_expr ( global, caches, scope, this_ptr. as_deref_mut ( ) , lhs_expr) ?
432438 . flatten ( ) ;
433- let obj_ptr = & mut value. into ( ) ;
439+ let item_ptr = & mut value. into ( ) ;
434440
435441 self . eval_dot_index_chain_raw (
436- global, caches, scope2, this_ptr, lhs_expr, expr, obj_ptr , rhs, idx_values,
442+ global, caches, scope2, this_ptr, lhs_expr, expr, item_ptr , rhs, idx_values,
437443 None ,
438444 )
439445 }
@@ -575,19 +581,30 @@ impl Engine {
575581 let idx_pos = x. lhs . start_position ( ) ;
576582
577583 let ( try_setter, result) = {
578- let target = target. as_mut ( ) ;
579- let mut obj = self . get_indexed_mut (
580- global, caches, target, idx_val, idx_pos, op_pos, false , true ,
584+ let obj = target. as_mut ( ) ;
585+
586+ #[ cfg( not( feature = "no_closure" ) ) ]
587+ let mut target_guard;
588+ #[ cfg( not( feature = "no_closure" ) ) ]
589+ let obj = if obj. is_shared ( ) {
590+ target_guard = obj. write_lock :: < Dynamic > ( ) . unwrap ( ) ;
591+ & mut * target_guard
592+ } else {
593+ obj
594+ } ;
595+
596+ let mut item = self . get_indexed_mut (
597+ global, caches, obj, idx_val, idx_pos, op_pos, false , true ,
581598 ) ?;
582- let is_obj_temp_val = obj . is_temp_value ( ) ;
583- let obj_ptr = & mut obj ;
599+ let is_item_temp_val = item . is_temp_value ( ) ;
600+ let item_ptr = & mut item ;
584601
585602 match self . eval_dot_index_chain_raw (
586- global, caches, _scope, this_ptr, root, rhs, obj_ptr , & x. rhs ,
603+ global, caches, _scope, this_ptr, root, rhs, item_ptr , & x. rhs ,
587604 idx_values, new_val,
588605 ) {
589- Ok ( ( result, true ) ) if is_obj_temp_val => {
590- ( Some ( obj . take_or_clone ( ) ) , ( result, true ) )
606+ Ok ( ( result, true ) ) if is_item_temp_val => {
607+ ( Some ( item . take_or_clone ( ) ) , ( result, true ) )
591608 }
592609 Ok ( result) => ( None , result) ,
593610 Err ( err) => return Err ( err) ,
@@ -617,19 +634,30 @@ impl Engine {
617634 #[ cfg( feature = "debugging" ) ]
618635 self . run_debugger ( global, caches, _scope, this_ptr, parent) ?;
619636
620- let target = target. as_mut ( ) ;
637+ let obj = target. as_mut ( ) ;
638+
639+ #[ cfg( not( feature = "no_closure" ) ) ]
640+ let mut target_guard;
641+ #[ cfg( not( feature = "no_closure" ) ) ]
642+ let obj = if obj. is_shared ( ) {
643+ target_guard = obj. write_lock :: < Dynamic > ( ) . unwrap ( ) ;
644+ & mut * target_guard
645+ } else {
646+ obj
647+ } ;
648+
621649 let idx_val = & mut idx_values. pop ( ) . unwrap ( ) ;
622650 let idx = & mut idx_val. clone ( ) ;
623651
624652 let try_setter = match self
625- . get_indexed_mut ( global, caches, target , idx, pos, op_pos, true , false )
653+ . get_indexed_mut ( global, caches, obj , idx, pos, op_pos, true , false )
626654 {
627655 // Indexed value is not a temp value - update directly
628- Ok ( ref mut obj_ptr ) => {
656+ Ok ( ref mut item_ptr ) => {
629657 self . eval_op_assignment (
630- global, caches, op_info, root, obj_ptr , new_val,
658+ global, caches, op_info, root, item_ptr , new_val,
631659 ) ?;
632- self . check_data_size ( obj_ptr . as_ref ( ) , op_info. position ( ) ) ?;
660+ self . check_data_size ( item_ptr . as_ref ( ) , op_info. position ( ) ) ?;
633661 None
634662 }
635663 // Indexed value cannot be referenced - use indexer
@@ -646,7 +674,7 @@ impl Engine {
646674
647675 // Call the index getter to get the current value
648676 if let Ok ( val) =
649- self . call_indexer_get ( global, caches, target , idx, op_pos)
677+ self . call_indexer_get ( global, caches, obj , idx, op_pos)
650678 {
651679 let mut val = val. into ( ) ;
652680 // Run the op-assignment
@@ -663,7 +691,7 @@ impl Engine {
663691 let new_val = & mut new_val;
664692 // The return value of a indexer setter (usually `()`) is thrown away and not used.
665693 let _ = self . call_indexer_set (
666- global, caches, target , idx_val, new_val, is_ref_mut, op_pos,
694+ global, caches, obj , idx_val, new_val, is_ref_mut, op_pos,
667695 ) ?;
668696 }
669697
@@ -674,13 +702,22 @@ impl Engine {
674702 #[ cfg( feature = "debugging" ) ]
675703 self . run_debugger ( global, caches, _scope, this_ptr, parent) ?;
676704
677- let target = target. as_mut ( ) ;
705+ let obj = target. as_mut ( ) ;
706+
707+ #[ cfg( not( feature = "no_closure" ) ) ]
708+ let mut target_guard;
709+ #[ cfg( not( feature = "no_closure" ) ) ]
710+ let obj = if obj. is_shared ( ) {
711+ target_guard = obj. write_lock :: < Dynamic > ( ) . unwrap ( ) ;
712+ & mut * target_guard
713+ } else {
714+ obj
715+ } ;
716+
678717 let idx_val = & mut idx_values. pop ( ) . unwrap ( ) ;
679718
680- self . get_indexed_mut (
681- global, caches, target, idx_val, pos, op_pos, false , true ,
682- )
683- . map ( |v| ( v. take_or_clone ( ) , false ) )
719+ self . get_indexed_mut ( global, caches, obj, idx_val, pos, op_pos, false , true )
720+ . map ( |v| ( v. take_or_clone ( ) , false ) )
684721 }
685722 }
686723 }
@@ -731,13 +768,22 @@ impl Engine {
731768
732769 let index = & mut x. 2 . clone ( ) . into ( ) ;
733770 {
734- let target = target. as_mut ( ) ;
735- let val_target = & mut self . get_indexed_mut (
736- global, caches, target, index, * pos, op_pos, true , false ,
737- ) ?;
738- self . eval_op_assignment (
739- global, caches, op_info, root, val_target, new_val,
771+ let obj = target. as_mut ( ) ;
772+
773+ #[ cfg( not( feature = "no_closure" ) ) ]
774+ let mut target_guard;
775+ #[ cfg( not( feature = "no_closure" ) ) ]
776+ let obj = if obj. is_shared ( ) {
777+ target_guard = obj. write_lock :: < Dynamic > ( ) . unwrap ( ) ;
778+ & mut * target_guard
779+ } else {
780+ obj
781+ } ;
782+
783+ let item = & mut self . get_indexed_mut (
784+ global, caches, obj, index, * pos, op_pos, true , false ,
740785 ) ?;
786+ self . eval_op_assignment ( global, caches, op_info, root, item, new_val) ?;
741787 }
742788 self . check_data_size ( target. source ( ) , op_info. position ( ) ) ?;
743789 Ok ( ( Dynamic :: UNIT , true ) )
@@ -747,12 +793,23 @@ impl Engine {
747793 #[ cfg( feature = "debugging" ) ]
748794 self . run_debugger ( global, caches, _scope, this_ptr, rhs) ?;
749795
750- let target = target. as_mut ( ) ;
796+ let obj = target. as_mut ( ) ;
797+
798+ #[ cfg( not( feature = "no_closure" ) ) ]
799+ let mut target_guard;
800+ #[ cfg( not( feature = "no_closure" ) ) ]
801+ let obj = if obj. is_shared ( ) {
802+ target_guard = obj. write_lock :: < Dynamic > ( ) . unwrap ( ) ;
803+ & mut * target_guard
804+ } else {
805+ obj
806+ } ;
807+
751808 let index = & mut x. 2 . clone ( ) . into ( ) ;
752- let val = self . get_indexed_mut (
753- global, caches, target , index, * pos, op_pos, false , false ,
809+ let item = self . get_indexed_mut (
810+ global, caches, obj , index, * pos, op_pos, false , false ,
754811 ) ?;
755- Ok ( ( val . take_or_clone ( ) , false ) )
812+ Ok ( ( item . take_or_clone ( ) , false ) )
756813 }
757814 // xxx.id op= ???
758815 ( Expr :: Property ( x, pos) , Some ( ( mut new_val, op_info) ) , false ) => {
@@ -856,16 +913,27 @@ impl Engine {
856913 let _node = & x. lhs ;
857914 let mut _this_ptr = this_ptr;
858915 let _tp = _this_ptr. as_deref_mut ( ) ;
916+ #[ cfg( not( feature = "no_closure" ) ) ]
917+ let mut target_guard;
859918
860- let val_target = & mut match x. lhs {
919+ let item = & mut match x. lhs {
861920 Expr :: Property ( ref p, pos) => {
862921 #[ cfg( feature = "debugging" ) ]
863922 self . run_debugger ( global, caches, _scope, _tp, _node) ?;
864923
865- let target = target. as_mut ( ) ;
924+ let obj = target. as_mut ( ) ;
925+
926+ #[ cfg( not( feature = "no_closure" ) ) ]
927+ let obj = if obj. is_shared ( ) {
928+ target_guard = obj. write_lock :: < Dynamic > ( ) . unwrap ( ) ;
929+ & mut * target_guard
930+ } else {
931+ obj
932+ } ;
933+
866934 let index = & mut p. 2 . clone ( ) . into ( ) ;
867935 self . get_indexed_mut (
868- global, caches, target , index, pos, op_pos, false , true ,
936+ global, caches, obj , index, pos, op_pos, false , true ,
869937 ) ?
870938 }
871939 // {xxx:map}.fn_name(arg_expr_list)[expr] | {xxx:map}.fn_name(arg_expr_list).expr
@@ -902,8 +970,8 @@ impl Engine {
902970 } ;
903971
904972 self . eval_dot_index_chain_raw (
905- global, caches, _scope, _this_ptr, root, rhs, val_target , & x. rhs ,
906- idx_values , new_val,
973+ global, caches, _scope, _this_ptr, root, rhs, item , & x. rhs , idx_values ,
974+ new_val,
907975 )
908976 }
909977 // xxx.sub_lhs[expr] | xxx.sub_lhs.expr
0 commit comments