Skip to content

Commit

Permalink
Add support for arrays (#52280)
Browse files Browse the repository at this point in the history
  • Loading branch information
tyxla authored Jul 7, 2023
1 parent 9e8763a commit 4e9b121
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 ]
);
} );
} );
} );

1 comment on commit 4e9b121

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Flaky tests detected in 4e9b121.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/5483176087
📝 Reported issues:

Please sign in to comment.