Skip to content

Commit

Permalink
setImmutably: don't clone all objects
Browse files Browse the repository at this point in the history
  • Loading branch information
ellatrix committed Nov 28, 2023
1 parent ece0838 commit 343e776
Showing 1 changed file with 12 additions and 43 deletions.
55 changes: 12 additions & 43 deletions packages/block-editor/src/utils/object.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,33 +55,6 @@ export function kebabCase( str ) {
} );
}

/**
* Clones an object.
* Arrays are also cloned as arrays.
* Non-object values are returned unchanged.
*
* @param {*} object Object to clone.
* @return {*} Cloned object, or original literal non-object value.
*/
function cloneObject( object ) {
if ( Array.isArray( object ) ) {
return object.map( cloneObject );
}

if ( object && typeof object === 'object' ) {
return {
...Object.fromEntries(
Object.entries( object ).map( ( [ key, value ] ) => [
key,
cloneObject( value ),
] )
),
};
}

return object;
}

/**
* Immutably sets a value inside an object. Like `lodash#set`, but returning a
* new object. Treats nullish initial values as empty objects. Clones any
Expand All @@ -93,24 +66,20 @@ function cloneObject( object ) {
* @return {Object} Cloned object with the new value set.
*/
export function setImmutably( object, path, value ) {
const normalizedPath = normalizePath( path );
const newObject = object ? cloneObject( object ) : {};
path = normalizePath( path );

if ( path.length === 0 ) {
throw new Error( 'Path cannot be empty' );
}

const clonedObj = Array.isArray( object ) ? [ ...object ] : { ...object };
const [ first, ...rest ] = path;

normalizedPath.reduce( ( acc, key, i ) => {
if ( acc[ key ] === undefined ) {
if ( Number.isInteger( path[ i + 1 ] ) ) {
acc[ key ] = [];
} else {
acc[ key ] = {};
}
}
if ( i === normalizedPath.length - 1 ) {
acc[ key ] = value;
}
return acc[ key ];
}, newObject );
clonedObj[ first ] = rest.length
? setImmutably( clonedObj[ first ], rest, value )
: value;

return newObject;
return clonedObj;
}

const stringToPath = memoize( ( path ) => path.split( '.' ) );
Expand Down

0 comments on commit 343e776

Please sign in to comment.