@@ -245,6 +245,8 @@ export function partialMatchKey(a: any, b: any): boolean {
245
245
return false
246
246
}
247
247
248
+ const hasOwn = Object . prototype . hasOwnProperty
249
+
248
250
/**
249
251
* This function returns `a` if `b` is deeply equal.
250
252
* If not, it will replace any deeply equal children of `b` with those of `a`.
@@ -258,37 +260,43 @@ export function replaceEqualDeep(a: any, b: any): any {
258
260
259
261
const array = isPlainArray ( a ) && isPlainArray ( b )
260
262
261
- if ( array || ( isPlainObject ( a ) && isPlainObject ( b ) ) ) {
262
- const aItems = array ? a : Object . keys ( a )
263
- const aSize = aItems . length
264
- const bItems = array ? b : Object . keys ( b )
265
- const bSize = bItems . length
266
- const copy : any = array ? [ ] : { }
267
- const aItemsSet = new Set ( aItems )
268
-
269
- let equalItems = 0
270
-
271
- for ( let i = 0 ; i < bSize ; i ++ ) {
272
- const key = array ? i : bItems [ i ]
273
- if (
274
- ( ( ! array && aItemsSet . has ( key ) ) || array ) &&
275
- a [ key ] === undefined &&
276
- b [ key ] === undefined
277
- ) {
278
- copy [ key ] = undefined
279
- equalItems ++
280
- } else {
281
- copy [ key ] = replaceEqualDeep ( a [ key ] , b [ key ] )
282
- if ( copy [ key ] === a [ key ] && a [ key ] !== undefined ) {
283
- equalItems ++
284
- }
285
- }
263
+ if ( ! array && ! ( isPlainObject ( a ) && isPlainObject ( b ) ) ) return b
264
+
265
+ const aItems = array ? a : Object . keys ( a )
266
+ const aSize = aItems . length
267
+ const bItems = array ? b : Object . keys ( b )
268
+ const bSize = bItems . length
269
+ const copy : any = array ? new Array ( bSize ) : { }
270
+
271
+ let equalItems = 0
272
+
273
+ for ( let i = 0 ; i < bSize ; i ++ ) {
274
+ const key : any = array ? i : bItems [ i ]
275
+ const aItem = a [ key ]
276
+ const bItem = b [ key ]
277
+
278
+ if ( aItem === bItem ) {
279
+ copy [ key ] = aItem
280
+ if ( array ? i < aSize : hasOwn . call ( a , key ) ) equalItems ++
281
+ continue
282
+ }
283
+
284
+ if (
285
+ aItem === null ||
286
+ bItem === null ||
287
+ typeof aItem !== 'object' ||
288
+ typeof bItem !== 'object'
289
+ ) {
290
+ copy [ key ] = bItem
291
+ continue
286
292
}
287
293
288
- return aSize === bSize && equalItems === aSize ? a : copy
294
+ const v = replaceEqualDeep ( aItem , bItem )
295
+ copy [ key ] = v
296
+ if ( v === aItem ) equalItems ++
289
297
}
290
298
291
- return b
299
+ return aSize === bSize && equalItems === aSize ? a : copy
292
300
}
293
301
294
302
/**
@@ -311,13 +319,12 @@ export function shallowEqualObjects<T extends Record<string, any>>(
311
319
return true
312
320
}
313
321
314
- export function isPlainArray ( value : unknown ) {
322
+ export function isPlainArray ( value : unknown ) : value is Array < unknown > {
315
323
return Array . isArray ( value ) && value . length === Object . keys ( value ) . length
316
324
}
317
325
318
326
// Copied from: https://github.com/jonschlinkert/is-plain-object
319
- // eslint-disable-next-line @typescript-eslint/no-wrapper-object-types
320
- export function isPlainObject ( o : any ) : o is Object {
327
+ export function isPlainObject ( o : any ) : o is Record < PropertyKey , unknown > {
321
328
if ( ! hasObjectPrototype ( o ) ) {
322
329
return false
323
330
}
0 commit comments