diff --git a/src/isomorphic/classic/element/ReactElement.js b/src/isomorphic/classic/element/ReactElement.js index ee46a5f392dbb..307bb4d5c88b3 100644 --- a/src/isomorphic/classic/element/ReactElement.js +++ b/src/isomorphic/classic/element/ReactElement.js @@ -126,6 +126,13 @@ ReactElement.createElement = function(type, config, children) { if (config != null) { if (__DEV__) { + warning( + /* eslint-disable no-proto */ + config.__proto__ == null || config.__proto__ === Object.prototype, + /* eslint-enable no-proto */ + 'React.createElement(...): Expected props argument to be a plain object. ' + + 'Properties defined in its prototype chain will be ignored.' + ); ref = !config.hasOwnProperty('ref') || Object.getOwnPropertyDescriptor(config, 'ref').get ? null : config.ref; key = !config.hasOwnProperty('key') || @@ -268,6 +275,15 @@ ReactElement.cloneElement = function(element, config, children) { var owner = element._owner; if (config != null) { + if (__DEV__) { + warning( + /* eslint-disable no-proto */ + config.__proto__ == null || config.__proto__ === Object.prototype, + /* eslint-enable no-proto */ + 'React.cloneElement(...): Expected props argument to be a plain object. ' + + 'Properties defined in its prototype chain will be ignored.' + ); + } if (config.ref !== undefined) { // Silently steal the ref from the parent. ref = config.ref; diff --git a/src/isomorphic/classic/element/__tests__/ReactElement-test.js b/src/isomorphic/classic/element/__tests__/ReactElement-test.js index 402c9b95eddef..8b3900db9f651 100644 --- a/src/isomorphic/classic/element/__tests__/ReactElement-test.js +++ b/src/isomorphic/classic/element/__tests__/ReactElement-test.js @@ -138,6 +138,18 @@ describe('ReactElement', function() { expect(element.props.foo).toBe(1); }); + it('warns if the config object inherits from any type other than Object', function() { + spyOn(console, 'error'); + React.createElement('div', {foo: 1}); + expect(console.error).not.toHaveBeenCalled(); + React.createElement('div', Object.create({foo: 1})); + expect(console.error.argsForCall.length).toBe(1); + expect(console.error.argsForCall[0][0]).toContain( + 'React.createElement(...): Expected props argument to be a plain object. ' + + 'Properties defined in its prototype chain will be ignored.' + ); + }); + it('extracts key and ref from the config', function() { var element = React.createFactory(ComponentClass)({ key: '12', diff --git a/src/isomorphic/classic/element/__tests__/ReactElementClone-test.js b/src/isomorphic/classic/element/__tests__/ReactElementClone-test.js index f4c5b4b761bd1..20b4089726433 100644 --- a/src/isomorphic/classic/element/__tests__/ReactElementClone-test.js +++ b/src/isomorphic/classic/element/__tests__/ReactElementClone-test.js @@ -66,6 +66,18 @@ describe('ReactElementClone', function() { expect(ReactDOM.findDOMNode(component).childNodes[0].className).toBe('xyz'); }); + it('should warn if the config object inherits from any type other than Object', function() { + spyOn(console, 'error'); + React.cloneElement('div', {foo: 1}); + expect(console.error).not.toHaveBeenCalled(); + React.cloneElement('div', Object.create({foo: 1})); + expect(console.error.argsForCall.length).toBe(1); + expect(console.error.argsForCall[0][0]).toContain( + 'React.cloneElement(...): Expected props argument to be a plain object. ' + + 'Properties defined in its prototype chain will be ignored.' + ); + }); + it('should keep the original ref if it is not overridden', function() { var Grandparent = React.createClass({ render: function() {