diff --git a/package.json b/package.json index 6c4b443531..c9c8325172 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "babel-core": "^5.6.18", "babel-eslint": "^3.1.15", "babel-loader": "^5.1.4", + "contextify": "^0.1.14", "eslint": "^0.23", "eslint-config-airbnb": "0.0.6", "eslint-plugin-react": "^2.3.0", diff --git a/src/utils/isPlainObject.js b/src/utils/isPlainObject.js index a5896655e5..db3f6a0113 100644 --- a/src/utils/isPlainObject.js +++ b/src/utils/isPlainObject.js @@ -1,12 +1,23 @@ +var fnToString = (fn) => Function.prototype.toString.call(fn); + /** * @param {any} obj The object to inspect. * @returns {boolean} True if the argument appears to be a plain object. */ export default function isPlainObject(obj) { - if (!obj) { + if (!obj || typeof obj !== 'object') { return false; } - return typeof obj === 'object' && - Object.getPrototypeOf(obj) === Object.prototype; + var proto = typeof obj.constructor === 'function' ? Object.getPrototypeOf(obj) : Object.prototype; + + if (proto === null) { + return true; + } + + var constructor = proto.constructor; + + return typeof constructor === 'function' + && constructor instanceof constructor + && fnToString(constructor) === fnToString(Object); } diff --git a/test/utils/isPlainObject.spec.js b/test/utils/isPlainObject.spec.js index 24180258aa..963c7f610c 100644 --- a/test/utils/isPlainObject.spec.js +++ b/test/utils/isPlainObject.spec.js @@ -1,5 +1,6 @@ import expect from 'expect'; import isPlainObject from '../../src/utils/isPlainObject'; +import contextify from 'contextify'; describe('isPlainObject', () => { it('should return true only if plain object', () => { @@ -7,11 +8,17 @@ describe('isPlainObject', () => { this.prop = 1; } + const sandbox = contextify(); + sandbox.run('var fromAnotherRealm = {};'); + + expect(isPlainObject(sandbox.fromAnotherRealm)).toBe(true); expect(isPlainObject(new Test())).toBe(false); expect(isPlainObject(new Date())).toBe(false); expect(isPlainObject([1, 2, 3])).toBe(false); expect(isPlainObject(null)).toBe(false); expect(isPlainObject()).toBe(false); expect(isPlainObject({ 'x': 1, 'y': 2 })).toBe(true); + + sandbox.dispose(); }); });