@@ -2772,11 +2772,20 @@ func (a *Array) setParentUpdater(f parentUpdater) {
2772
2772
// setCallbackWithChild sets up callback function with child value (child)
2773
2773
// so parent array (a) can be notified when child value is modified.
2774
2774
func (a * Array ) setCallbackWithChild (i uint64 , child Value , maxInlineSize uint64 ) {
2775
- c , ok := child .(mutableValueNotifier )
2775
+ // Unwrap child value if needed (e.g. interpreter.SomeValue)
2776
+ unwrappedChild , wrapperSize := unwrapValue (child )
2777
+
2778
+ c , ok := unwrappedChild .(mutableValueNotifier )
2776
2779
if ! ok {
2777
2780
return
2778
2781
}
2779
2782
2783
+ if maxInlineSize < wrapperSize {
2784
+ maxInlineSize = 0
2785
+ } else {
2786
+ maxInlineSize -= wrapperSize
2787
+ }
2788
+
2780
2789
vid := c .ValueID ()
2781
2790
2782
2791
// mutableElementIndex is lazily initialized.
@@ -2809,6 +2818,8 @@ func (a *Array) setCallbackWithChild(i uint64, child Value, maxInlineSize uint64
2809
2818
return false , err
2810
2819
}
2811
2820
2821
+ storable = unwrapStorable (storable )
2822
+
2812
2823
// Verify retrieved element is either SlabIDStorable or Slab, with identical value ID.
2813
2824
switch storable := storable .(type ) {
2814
2825
case SlabIDStorable :
@@ -2827,15 +2838,19 @@ func (a *Array) setCallbackWithChild(i uint64, child Value, maxInlineSize uint64
2827
2838
return false , nil
2828
2839
}
2829
2840
2841
+ // NOTE: Must reset child using original child (not unwrapped child)
2842
+
2830
2843
// Set child value with parent array using updated index.
2831
- // Set() calls c .Storable() which returns inlined or not-inlined child storable.
2832
- existingValueStorable , err := a .set (adjustedIndex , c )
2844
+ // Set() calls child .Storable() which returns inlined or not-inlined child storable.
2845
+ existingValueStorable , err := a .set (adjustedIndex , child )
2833
2846
if err != nil {
2834
2847
return false , err
2835
2848
}
2836
2849
2837
2850
// Verify overwritten storable has identical value ID.
2838
2851
2852
+ existingValueStorable = unwrapStorable (existingValueStorable )
2853
+
2839
2854
switch existingValueStorable := existingValueStorable .(type ) {
2840
2855
case SlabIDStorable :
2841
2856
sid := SlabID (existingValueStorable )
@@ -2923,38 +2938,87 @@ func (a *Array) Set(index uint64, value Value) (Storable, error) {
2923
2938
// If overwritten storable is an inlined slab, uninline the slab and store it in storage.
2924
2939
// This is to prevent potential data loss because the overwritten inlined slab was not in
2925
2940
// storage and any future changes to it would have been lost.
2926
- switch s := existingStorable .(type ) {
2941
+ existingStorable , existingValueID , _ , err = uninlineStorableIfNeeded (a .Storage , existingStorable )
2942
+ if err != nil {
2943
+ return nil , err
2944
+ }
2945
+
2946
+ // Remove overwritten array/map's ValueID from mutableElementIndex if:
2947
+ // - new value isn't array/map, or
2948
+ // - new value is array/map with different value ID
2949
+ if existingValueID != emptyValueID {
2950
+ unwrappedValue , _ := unwrapValue (value )
2951
+ newValue , ok := unwrappedValue .(mutableValueNotifier )
2952
+ if ! ok || existingValueID != newValue .ValueID () {
2953
+ delete (a .mutableElementIndex , existingValueID )
2954
+ }
2955
+ }
2956
+
2957
+ return existingStorable , nil
2958
+ }
2959
+
2960
+ // uninlineStorableIfNeeded uninlines given storable if needed, and
2961
+ // returns uninlined Storable and its ValueID.
2962
+ // If given storable is a WrapperStorable, this function uninlines
2963
+ // wrapped storable if needed and returns a new WrapperStorable
2964
+ // with wrapped uninlined storable and its ValidID.
2965
+ func uninlineStorableIfNeeded (storage SlabStorage , storable Storable ) (Storable , ValueID , bool , error ) {
2966
+ if storable == nil {
2967
+ return storable , emptyValueID , false , nil
2968
+ }
2969
+
2970
+ switch s := storable .(type ) {
2927
2971
case ArraySlab : // inlined array slab
2928
- err = s .Uninline (a . Storage )
2972
+ err : = s .Uninline (storage )
2929
2973
if err != nil {
2930
- return nil , err
2974
+ return nil , emptyValueID , false , err
2931
2975
}
2932
- existingStorable = SlabIDStorable (s .SlabID ())
2933
- existingValueID = slabIDToValueID (s .SlabID ())
2976
+
2977
+ slabID := s .SlabID ()
2978
+
2979
+ newStorable := SlabIDStorable (slabID )
2980
+ valueID := slabIDToValueID (slabID )
2981
+
2982
+ return newStorable , valueID , true , nil
2934
2983
2935
2984
case MapSlab : // inlined map slab
2936
- err = s .Uninline (a . Storage )
2985
+ err : = s .Uninline (storage )
2937
2986
if err != nil {
2938
- return nil , err
2987
+ return nil , emptyValueID , false , err
2939
2988
}
2940
- existingStorable = SlabIDStorable (s .SlabID ())
2941
- existingValueID = slabIDToValueID (s .SlabID ())
2989
+
2990
+ slabID := s .SlabID ()
2991
+
2992
+ newStorable := SlabIDStorable (slabID )
2993
+ valueID := slabIDToValueID (slabID )
2994
+
2995
+ return newStorable , valueID , true , nil
2942
2996
2943
2997
case SlabIDStorable : // uninlined slab
2944
- existingValueID = slabIDToValueID (SlabID (s ))
2945
- }
2998
+ valueID := slabIDToValueID (SlabID (s ))
2946
2999
2947
- // Remove overwritten array/map's ValueID from mutableElementIndex if:
2948
- // - new value isn't array/map, or
2949
- // - new value is array/map with different value ID
2950
- if existingValueID != emptyValueID {
2951
- newValue , ok := value .(mutableValueNotifier )
2952
- if ! ok || existingValueID != newValue .ValueID () {
2953
- delete (a .mutableElementIndex , existingValueID )
3000
+ return storable , valueID , false , nil
3001
+
3002
+ case WrapperStorable :
3003
+ unwrappedStorable := unwrapStorable (s )
3004
+
3005
+ // Uninline wrapped storable if needed.
3006
+ uninlinedWrappedStorable , valueID , uninlined , err := uninlineStorableIfNeeded (storage , unwrappedStorable )
3007
+ if err != nil {
3008
+ return nil , emptyValueID , false , err
3009
+ }
3010
+
3011
+ if ! uninlined {
3012
+ return storable , valueID , uninlined , nil
2954
3013
}
3014
+
3015
+ // Create a new WrapperStorable with uninlinedWrappedStorable
3016
+ newStorable := s .WrapAtreeStorable (uninlinedWrappedStorable )
3017
+
3018
+ return newStorable , valueID , uninlined , nil
2955
3019
}
2956
3020
2957
- return existingStorable , nil
3021
+ return storable , emptyValueID , false , nil
2958
3022
}
2959
3023
2960
3024
func (a * Array ) set (index uint64 , value Value ) (Storable , error ) {
@@ -3068,39 +3132,20 @@ func (a *Array) Remove(index uint64) (Storable, error) {
3068
3132
return nil , err
3069
3133
}
3070
3134
3071
- // If overwritten storable is an inlined slab, uninline the slab and store it in storage.
3135
+ // If removed storable is an inlined slab, uninline the slab and store it in storage.
3072
3136
// This is to prevent potential data loss because the overwritten inlined slab was not in
3073
3137
// storage and any future changes to it would have been lost.
3074
- switch s := storable .(type ) {
3075
- case ArraySlab :
3076
- err = s .Uninline (a .Storage )
3077
- if err != nil {
3078
- return nil , err
3079
- }
3080
- storable = SlabIDStorable (s .SlabID ())
3081
-
3082
- // Delete removed element ValueID from mutableElementIndex
3083
- removedValueID := slabIDToValueID (s .SlabID ())
3084
- delete (a .mutableElementIndex , removedValueID )
3085
-
3086
- case MapSlab :
3087
- err = s .Uninline (a .Storage )
3088
- if err != nil {
3089
- return nil , err
3090
- }
3091
- storable = SlabIDStorable (s .SlabID ())
3092
-
3093
- // Delete removed element ValueID from mutableElementIndex
3094
- removedValueID := slabIDToValueID (s .SlabID ())
3095
- delete (a .mutableElementIndex , removedValueID )
3138
+ removedStorable , removedValueID , _ , err := uninlineStorableIfNeeded (a .Storage , storable )
3139
+ if err != nil {
3140
+ return nil , err
3141
+ }
3096
3142
3097
- case SlabIDStorable :
3098
- // Delete removed element ValueID from mutableElementIndex
3099
- removedValueID := slabIDToValueID (SlabID (s ))
3143
+ // Delete removed element ValueID from mutableElementIndex
3144
+ if removedValueID != emptyValueID {
3100
3145
delete (a .mutableElementIndex , removedValueID )
3101
3146
}
3102
3147
3103
- return storable , nil
3148
+ return removedStorable , nil
3104
3149
}
3105
3150
3106
3151
func (a * Array ) remove (index uint64 ) (Storable , error ) {
@@ -3361,7 +3406,10 @@ var defaultReadOnlyArrayIteratorMutatinCallback ReadOnlyArrayIteratorMutationCal
3361
3406
var _ ArrayIterator = & readOnlyArrayIterator {}
3362
3407
3363
3408
func (i * readOnlyArrayIterator ) setMutationCallback (value Value ) {
3364
- if v , ok := value .(mutableValueNotifier ); ok {
3409
+
3410
+ unwrappedChild , _ := unwrapValue (value )
3411
+
3412
+ if v , ok := unwrappedChild .(mutableValueNotifier ); ok {
3365
3413
v .setParentUpdater (func () (found bool , err error ) {
3366
3414
i .valueMutationCallback (value )
3367
3415
return true , NewReadOnlyIteratorElementMutationError (i .array .ValueID (), v .ValueID ())
0 commit comments