From 598df0bc201e4a177d51bd3d29a4249b997987df Mon Sep 17 00:00:00 2001 From: Dmitry Soshnikov Date: Thu, 28 Jan 2016 17:20:39 -0800 Subject: [PATCH] Add Object.entries and Object.values polyfill Reviewed By: martinbigio Differential Revision: D2876430 fb-gh-sync-id: 25c7680a71c9187beb937f6faf030a83c9c81fc5 --- packager/react-packager/src/Resolver/index.js | 1 + .../src/Resolver/polyfills/Object.es7.js | 56 ++++++++ .../polyfills/__tests__/Object.es7-test.js | 120 ++++++++++++++++++ 3 files changed, 177 insertions(+) create mode 100644 packager/react-packager/src/Resolver/polyfills/Object.es7.js create mode 100644 packager/react-packager/src/Resolver/polyfills/__tests__/Object.es7-test.js diff --git a/packager/react-packager/src/Resolver/index.js b/packager/react-packager/src/Resolver/index.js index 0166681f0b3ede..4cb4707f1283e4 100644 --- a/packager/react-packager/src/Resolver/index.js +++ b/packager/react-packager/src/Resolver/index.js @@ -157,6 +157,7 @@ class Resolver { path.join(__dirname, 'polyfills/String.prototype.es6.js'), path.join(__dirname, 'polyfills/Array.prototype.es6.js'), path.join(__dirname, 'polyfills/Array.es6.js'), + path.join(__dirname, 'polyfills/Object.es7.js'), path.join(__dirname, 'polyfills/babelHelpers.js'), ].concat(this._polyfillModuleNames); diff --git a/packager/react-packager/src/Resolver/polyfills/Object.es7.js b/packager/react-packager/src/Resolver/polyfills/Object.es7.js new file mode 100644 index 00000000000000..597c49e7fc22d8 --- /dev/null +++ b/packager/react-packager/src/Resolver/polyfills/Object.es7.js @@ -0,0 +1,56 @@ +/** + * Copyright 2004-present Facebook. All Rights Reserved. + * + * @provides Object.es7 + * @polyfill + */ + +(function() { + + const hasOwnProperty = Object.prototype.hasOwnProperty; + + /** + * Returns an array of the given object's own enumerable entries. + * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries + * + */ + if (typeof Object.entries !== 'function') { + Object.entries = function(object) { + // `null` and `undefined` values are not allowed. + if (object == null) { + throw new TypeError('Object.entries called on non-object'); + } + + let entries = []; + for (let key in object) { + if (hasOwnProperty.call(object, key)) { + entries.push([key, object[key]]); + } + } + return entries; + }; + } + + /** + * Returns an array of the given object's own enumerable entries. + * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/values + * + */ + if (typeof Object.values !== 'function') { + Object.values = function(object) { + // `null` and `undefined` values are not allowed. + if (object == null) { + throw new TypeError('Object.values called on non-object'); + } + + let values = []; + for (let key in object) { + if (hasOwnProperty.call(object, key)) { + values.push(object[key]); + } + } + return values; + }; + } + +})(); \ No newline at end of file diff --git a/packager/react-packager/src/Resolver/polyfills/__tests__/Object.es7-test.js b/packager/react-packager/src/Resolver/polyfills/__tests__/Object.es7-test.js new file mode 100644 index 00000000000000..ee7782eb781ac4 --- /dev/null +++ b/packager/react-packager/src/Resolver/polyfills/__tests__/Object.es7-test.js @@ -0,0 +1,120 @@ +/** + * Copyright 2004-present Facebook. All Rights Reserved. + * + * @emails oncall+jsinfra + */ + + /* eslint-disable fb-www/object-create-only-one-param */ + +jest.autoMockOff(); + +describe('Object (ES7)', () => { + beforeEach(() => { + delete Object.entries; + delete Object.values; + jest.resetModuleRegistry(); + require('../Object.es7'); + }); + + describe('Object.entries', () => { + it('should have a length of 1', () => { + expect(Object.entries.length).toBe(1); + }); + + it('should check for type', () => { + expect(Object.entries.bind(null, null)).toThrow(TypeError( + 'Object.entries called on non-object' + )); + expect(Object.entries.bind(null, undefined)).toThrow(TypeError( + 'Object.entries called on non-object' + )); + expect(Object.entries.bind(null, [])).not.toThrow(); + expect(Object.entries.bind(null, () => {})).not.toThrow(); + expect(Object.entries.bind(null, {})).not.toThrow(); + expect(Object.entries.bind(null, 'abc')).not.toThrow(); + }); + + it('should return enumerable entries', () => { + let foo = Object.defineProperties({}, { + x: {value: 10, enumerable: true}, + y: {value: 20}, + }); + + expect(Object.entries(foo)).toEqual([['x', 10]]); + + let bar = {x: 10, y: 20}; + expect(Object.entries(bar)).toEqual([['x', 10], ['y', 20]]); + }); + + it('should work with proto-less objects', () => { + let foo = Object.create(null, { + x: {value: 10, enumerable: true}, + y: {value: 20}, + }); + + expect(Object.entries(foo)).toEqual([['x', 10]]); + }); + + it('should return only own entries', () => { + let foo = Object.create({z: 30}, { + x: {value: 10, enumerable: true}, + y: {value: 20}, + }); + + expect(Object.entries(foo)).toEqual([['x', 10]]); + }); + + it('should convert to object primitive string', () => { + expect(Object.entries('ab')).toEqual([['0', 'a'], ['1', 'b']]); + }); + }); + + describe('Object.values', () => { + it('should have a length of 1', () => { + expect(Object.values.length).toBe(1); + }); + + it('should check for type', () => { + expect(Object.values.bind(null, null)).toThrow(TypeError( + 'Object.values called on non-object' + )); + expect(Object.values.bind(null, [])).not.toThrow(); + expect(Object.values.bind(null, () => {})).not.toThrow(); + expect(Object.values.bind(null, {})).not.toThrow(); + }); + + it('should return enumerable values', () => { + let foo = Object.defineProperties({}, { + x: {value: 10, enumerable: true}, + y: {value: 20}, + }); + + expect(Object.values(foo)).toEqual([10]); + + let bar = {x: 10, y: 20}; + expect(Object.values(bar)).toEqual([10, 20]); + }); + + it('should work with proto-less objects', () => { + let foo = Object.create(null, { + x: {value: 10, enumerable: true}, + y: {value: 20}, + }); + + expect(Object.values(foo)).toEqual([10]); + }); + + it('should return only own values', () => { + let foo = Object.create({z: 30}, { + x: {value: 10, enumerable: true}, + y: {value: 20}, + }); + + expect(Object.values(foo)).toEqual([10]); + }); + + it('should convert to object primitive string', () => { + expect(Object.values('ab')).toEqual(['a', 'b']); + }); + }); +}); \ No newline at end of file