Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions packages/element/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,23 @@ _Returns_

- `boolean`: True when an element is considered empty.

### isPlainObject

Checks if the provided value is a plain object.

Plain objects are objects that are either:

- created by the `Object` constructor, or
- with a `[[Prototype]]` of `null`.

_Parameters_

- _value_ `*`: Value to check.

_Returns_

- `boolean`: True when value is considered a plain object.

### isValidElement

Checks if an object is a valid WPElement.
Expand Down
3 changes: 2 additions & 1 deletion packages/element/src/serialize.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
/**
* External dependencies
*/
import { kebabCase, isPlainObject } from 'lodash';
import { kebabCase } from 'lodash';

/**
* WordPress dependencies
Expand All @@ -44,6 +44,7 @@ import {
*/
import { createContext, Fragment, StrictMode, forwardRef } from './react';
import RawHTML from './raw-html';
import { isPlainObject } from './utils';

/** @typedef {import('./react').WPElement} WPElement */

Expand Down
39 changes: 38 additions & 1 deletion packages/element/src/test/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Internal dependencies
*/
import { createElement } from '../react';
import { isEmptyElement } from '../utils';
import { isEmptyElement, isPlainObject } from '../utils';

describe( 'isEmptyElement', () => {
test( 'should be empty', () => {
Expand All @@ -21,3 +21,40 @@ describe( 'isEmptyElement', () => {
expect( isEmptyElement( [ 'x' ] ) ).toBe( false );
} );
} );

describe( 'isPlainObject', () => {
test( 'should return true for plain objects', () => {
expect( isPlainObject( { foo: 'bar' } ) ).toBe( true );
expect( isPlainObject( new Object() ) ).toBe( true );
expect( isPlainObject( Object.prototype ) ).toBe( true );
expect( isPlainObject( Object.create( Object.prototype ) ) ).toBe(
true
);
expect( isPlainObject( Object.create( null ) ) ).toBe( true );
} );

test( 'should return false for anything else', () => {
expect( isPlainObject( undefined ) ).toBe( false );
expect( isPlainObject( null ) ).toBe( false );
expect( isPlainObject( true ) ).toBe( false );
expect( isPlainObject( [ 1, 2, 3 ] ) ).toBe( false );
expect( isPlainObject( '' ) ).toBe( false );
expect( isPlainObject( 5 ) ).toBe( false );
expect( isPlainObject( NaN ) ).toBe( false );
expect( isPlainObject( Infinity ) ).toBe( false );
expect( isPlainObject( new Array() ) ).toBe( false );
expect( isPlainObject( new String( '' ) ) ).toBe( false );
expect( isPlainObject( new Number( 5 ) ) ).toBe( false );
expect( isPlainObject( /someRegex/ ) ).toBe( false );
expect( isPlainObject( new Set( [ 1, 2, 3 ] ) ) ).toBe( false );
expect( isPlainObject( function () {} ) ).toBe( false );
expect( isPlainObject( () => {} ) ).toBe( false );
expect(
isPlainObject(
new ( function () {
return this;
} )()
)
).toBe( false );
} );
} );
25 changes: 25 additions & 0 deletions packages/element/src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,28 @@ export const isEmptyElement = ( element ) => {

return ! element;
};

/**
* Checks if the provided value is a plain object.
*
* Plain objects are objects that are either:
* - created by the `Object` constructor, or
* - with a `[[Prototype]]` of `null`.
*
* @param {*} value Value to check.
* @return {boolean} True when value is considered a plain object.
*/
export const isPlainObject = ( value ) => {
if ( typeof value !== 'object' || value === null ) {
return false;
}

if ( Object.getPrototypeOf( value ) === null ) {
return true;
}

return (
value.constructor === Object &&
Object.prototype.toString.call( value ) === '[object Object]'
);
};