@@ -217,52 +217,59 @@ export function replaceEqualDeep<T>(prev: any, _next: T): T {
217217 const next = _next as any
218218
219219 const array = isPlainArray ( prev ) && isPlainArray ( next )
220+ const object = ! array && isPlainObject ( prev ) && isPlainObject ( next )
220221
221- if ( array || ( isSimplePlainObject ( prev ) && isSimplePlainObject ( next ) ) ) {
222- const prevItems = array ? prev : Reflect . ownKeys ( prev )
223- const prevSize = prevItems . length
224- const nextItems = array ? next : Reflect . ownKeys ( next )
225- const nextSize = nextItems . length
226- const copy : any = array ? new Array ( nextSize ) : { }
227-
228- let equalItems = 0
229-
230- for ( let i = 0 ; i < nextSize ; i ++ ) {
231- const key = array ? i : ( nextItems [ i ] as any )
232- const p = prev [ key ]
233- if (
234- ( array || prev . hasOwnProperty ( key ) ) &&
235- p === undefined &&
236- next [ key ] === undefined
237- ) {
238- copy [ key ] = undefined
222+ if ( ! array && ! object ) return next
223+
224+ const prevItems = array ? prev : getEnumerableOwnKeys ( prev )
225+ if ( ! prevItems ) return next
226+ const nextItems = array ? next : getEnumerableOwnKeys ( next )
227+ if ( ! nextItems ) return next
228+ const prevSize = prevItems . length
229+ const nextSize = nextItems . length
230+ const copy : any = array ? new Array ( nextSize ) : { }
231+
232+ let equalItems = 0
233+
234+ for ( let i = 0 ; i < nextSize ; i ++ ) {
235+ const key = array ? i : ( nextItems [ i ] as any )
236+ const p = prev [ key ]
237+ if (
238+ ( array || prev . hasOwnProperty ( key ) ) &&
239+ p === undefined &&
240+ next [ key ] === undefined
241+ ) {
242+ copy [ key ] = undefined
243+ equalItems ++
244+ } else {
245+ const value = replaceEqualDeep ( p , next [ key ] )
246+ copy [ key ] = value
247+ if ( value === p && p !== undefined ) {
239248 equalItems ++
240- } else {
241- const value = replaceEqualDeep ( p , next [ key ] )
242- copy [ key ] = value
243- if ( value === p && p !== undefined ) {
244- equalItems ++
245- }
246249 }
247250 }
248-
249- return prevSize === nextSize && equalItems === prevSize ? prev : copy
250251 }
251252
252- return next
253+ return prevSize === nextSize && equalItems === prevSize ? prev : copy
253254}
254255
255256/**
256- * A wrapper around `isPlainObject` with additional checks to ensure that it is not
257- * only a plain object, but also one that is "clone-friendly" (doesn't have any
258- * non-enumerable properties).
257+ * Equivalent to `Reflect.ownKeys`, but ensures that objects are "clone-friendly":
258+ * will return false if object has any non-enumerable properties.
259259 */
260- function isSimplePlainObject ( o : any ) {
261- return (
262- // all the checks from isPlainObject are more likely to hit so we perform them first
263- isPlainObject ( o ) &&
264- Object . getOwnPropertyNames ( o ) . length === Object . keys ( o ) . length
265- )
260+ function getEnumerableOwnKeys ( o : object ) {
261+ const keys = [ ]
262+ const names = Object . getOwnPropertyNames ( o )
263+ for ( const name of names ) {
264+ if ( ! Object . prototype . propertyIsEnumerable . call ( o , name ) ) return false
265+ keys . push ( name )
266+ }
267+ const symbols = Object . getOwnPropertySymbols ( o )
268+ for ( const symbol of symbols ) {
269+ if ( ! Object . prototype . propertyIsEnumerable . call ( o , symbol ) ) return false
270+ keys . push ( symbol )
271+ }
272+ return keys
266273}
267274
268275// Copied from: https://github.com/jonschlinkert/is-plain-object
0 commit comments