@@ -6,13 +6,20 @@ export type ReconcileOptions = {
6
6
key ?: string | null ;
7
7
merge ?: boolean ;
8
8
} ;
9
+ export type ReconcileWithKeysOptions = {
10
+ keys ?: object | null ;
11
+ merge ?: boolean ;
12
+ } ;
13
+ const emptyKeys = /* #__PURE__*/ Object . create ( null ) ;
9
14
10
15
function applyState (
11
16
target : any ,
12
17
parent : any ,
13
18
property : PropertyKey ,
14
19
merge : boolean | undefined ,
15
- key : string | null
20
+ key : string | null ,
21
+ keys : object | null ,
22
+ useKeys : boolean | null
16
23
) {
17
24
const previous = parent [ property ] ;
18
25
if ( target === previous ) return ;
@@ -43,7 +50,7 @@ function applyState(
43
50
( key && previous [ start ] && target [ start ] && previous [ start ] [ key ] === target [ start ] [ key ] ) ) ;
44
51
start ++
45
52
) {
46
- applyState ( target [ start ] , previous , start , merge , key ) ;
53
+ applyState ( target [ start ] , previous , start , merge , key , keys , useKeys ) ;
47
54
}
48
55
49
56
const temp = new Array ( target . length ) ,
@@ -65,7 +72,7 @@ function applyState(
65
72
for ( j = start ; j <= newEnd ; j ++ ) setProperty ( previous , j , target [ j ] ) ;
66
73
for ( ; j < target . length ; j ++ ) {
67
74
setProperty ( previous , j , temp [ j ] ) ;
68
- applyState ( target [ j ] , previous , j , merge , key ) ;
75
+ applyState ( target [ j ] , previous , j , merge , key , keys , useKeys ) ;
69
76
}
70
77
if ( previous . length > target . length ) setProperty ( previous , "length" , target . length ) ;
71
78
return ;
@@ -95,12 +102,12 @@ function applyState(
95
102
for ( j = start ; j < target . length ; j ++ ) {
96
103
if ( j in temp ) {
97
104
setProperty ( previous , j , temp [ j ] ) ;
98
- applyState ( target [ j ] , previous , j , merge , key ) ;
105
+ applyState ( target [ j ] , previous , j , merge , key , keys , useKeys ) ;
99
106
} else setProperty ( previous , j , target [ j ] ) ;
100
107
}
101
108
} else {
102
109
for ( let i = 0 , len = target . length ; i < len ; i ++ ) {
103
- applyState ( target [ i ] , previous , i , merge , key ) ;
110
+ applyState ( target [ i ] , previous , i , merge , key , keys , useKeys ) ;
104
111
}
105
112
}
106
113
if ( previous . length > target . length ) setProperty ( previous , "length" , target . length ) ;
@@ -109,7 +116,15 @@ function applyState(
109
116
110
117
const targetKeys = Object . keys ( target ) ;
111
118
for ( let i = 0 , len = targetKeys . length ; i < len ; i ++ ) {
112
- applyState ( target [ targetKeys [ i ] ] , previous , targetKeys [ i ] , merge , key ) ;
119
+ applyState (
120
+ target [ targetKeys [ i ] ] ,
121
+ previous ,
122
+ targetKeys [ i ] ,
123
+ merge ,
124
+ ! useKeys ? key : isArray ? ( keys || emptyKeys ) . _key : keys [ targetKeys [ i ] ] ?. _key ,
125
+ ! useKeys ? null : isArray ? keys : keys [ targetKeys [ i ] ] || emptyKeys ,
126
+ useKeys
127
+ ) ;
113
128
}
114
129
const previousKeys = Object . keys ( previous ) ;
115
130
for ( let i = 0 , len = previousKeys . length ; i < len ; i ++ ) {
@@ -126,7 +141,20 @@ export function reconcile<T extends U, U>(
126
141
v = unwrap ( value ) ;
127
142
return state => {
128
143
if ( ! isWrappable ( state ) || ! isWrappable ( v ) ) return v ;
129
- const res = applyState ( v , { [ $ROOT ] : state } , $ROOT , merge , key ) ;
144
+ const res = applyState ( v , { [ $ROOT ] : state } , $ROOT , merge , key , null , null ) ;
145
+ return res === undefined ? ( state as T ) : res ;
146
+ } ;
147
+ }
148
+
149
+ export function reconcileWithKeys < T extends U , U > (
150
+ value : T ,
151
+ options : ReconcileWithKeysOptions = { }
152
+ ) : ( state : U ) => T {
153
+ const { merge, keys = emptyKeys } = options ,
154
+ v = unwrap ( value ) ;
155
+ return state => {
156
+ if ( ! isWrappable ( state ) || ! isWrappable ( v ) ) return v ;
157
+ const res = applyState ( v , { [ $ROOT ] : state } , $ROOT , merge , keys . _key , keys , true ) ;
130
158
return res === undefined ? ( state as T ) : res ;
131
159
} ;
132
160
}
0 commit comments