Skip to content

Commit

Permalink
Add support for arrays
Browse files Browse the repository at this point in the history
  • Loading branch information
tyxla committed Jul 4, 2023
1 parent a74f1cc commit 6f36e49
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 2 deletions.
13 changes: 11 additions & 2 deletions packages/block-editor/src/utils/object.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,17 @@ 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(
Expand All @@ -79,7 +84,7 @@ function cloneObject( 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
* nested objects.
* nested objects. Supports arrays, too.
*
* @param {Object} object Object to set a value in.
* @param {number|string|Array} path Path in the object to modify.
Expand All @@ -92,7 +97,11 @@ export function setImmutably( object, path, value ) {

normalizedPath.reduce( ( acc, key, i ) => {
if ( acc[ key ] === undefined ) {
acc[ key ] = {};
if ( Number.isInteger( path[ i + 1 ] ) ) {
acc[ key ] = [];
} else {
acc[ key ] = {};
}
}
if ( i === normalizedPath.length - 1 ) {
acc[ key ] = value;
Expand Down
36 changes: 36 additions & 0 deletions packages/block-editor/src/utils/test/object.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,22 @@ describe( 'setImmutably', () => {
expect( result ).toEqual( { test: 2 } );
} );

it( 'handles first level arrays properly', () => {
const result = setImmutably( [ 5 ], 0, 6 );

expect( result ).toEqual( [ 6 ] );
} );

it( 'handles nested arrays properly', () => {
const result = setImmutably(
[ [ 'foo', [ 'bar' ] ] ],
[ 0, 1, 0 ],
'baz'
);

expect( result ).toEqual( [ [ 'foo', [ 'baz' ] ] ] );
} );

describe( 'with array notation access', () => {
it( 'assigns values at deeper levels', () => {
const result = setImmutably( {}, [ 'foo', 'bar', 'baz' ], 5 );
Expand Down Expand Up @@ -236,5 +252,25 @@ describe( 'setImmutably', () => {
expect( result.foo.bar ).not.toBe( input.foo.bar );
expect( result.foo.bar.baz ).not.toBe( input.foo.bar.baz );
} );

it( 'clones arrays at the first level', () => {
const input = [];
const result = setImmutably( input, 0, 1 );

expect( result ).not.toBe( input );
} );

it( 'clones arrays at deeper levels', () => {
const input = [ [ [ [ 'foo', [ 'bar' ] ] ] ] ];
const result = setImmutably( input, [ 0, 0, 0, 1, 0 ], 'baz' );

expect( result ).not.toBe( input );
expect( result[ 0 ] ).not.toBe( input[ 0 ] );
expect( result[ 0 ][ 0 ] ).not.toBe( input[ 0 ][ 0 ] );
expect( result[ 0 ][ 0 ][ 0 ] ).not.toBe( input[ 0 ][ 0 ][ 0 ] );
expect( result[ 0 ][ 0 ][ 0 ][ 1 ] ).not.toBe(
input[ 0 ][ 0 ][ 0 ][ 1 ]
);
} );
} );
} );

0 comments on commit 6f36e49

Please sign in to comment.