From b5f8ab3fbdc6ed76237b9c0734ec882faf50dfc0 Mon Sep 17 00:00:00 2001 From: Ben Lesh Date: Fri, 4 Nov 2016 10:36:41 -0700 Subject: [PATCH] fix(Object.assign): stop polyfilling Object assign (#2080) RxJS should not be responsible for polyfilling `Object.assign`. This should also increase code coverage around the alternate method used for assign BREAKING CHANGE: RxJS will no longer polyfill `Object.assign`. It does not require `Object.assign` to function, however, your code may be inadvertently relying on this polyfill. --- spec/util/assign-spec.ts | 49 ++++++++++++++++++++++++++++++++++++++++ src/util/assign.ts | 38 ++++++++++++------------------- 2 files changed, 63 insertions(+), 24 deletions(-) create mode 100644 spec/util/assign-spec.ts diff --git a/spec/util/assign-spec.ts b/spec/util/assign-spec.ts new file mode 100644 index 0000000000..720338fea0 --- /dev/null +++ b/spec/util/assign-spec.ts @@ -0,0 +1,49 @@ +import { expect } from 'chai'; +import { assign, getAssign, assignImpl } from '../../dist/cjs/util/assign'; + +describe('assign', () => { + it('should exist', () => { + expect(assign).to.be.a('function'); + }); + + if (Object.assign) { + it('should use Object.assign if available', () => { + expect(assign).to.equal(Object.assign); + }); + } + + it('should assign n objects to a target', () => { + const target = { what: 'what' }; + const source1 = { wut: 'socks' }; + const source2 = { and : 'sandals' }; + const result = assign(target, source1, source2); + + expect(result).to.equal(target); + expect(result).to.deep.equal({ what: 'what', wut: 'socks', and: 'sandals' }); + }); +}); + +describe('assignImpl', () => { + it('should assign n objects to a target', () => { + const target = { what: 'what' }; + const source1 = { wut: 'socks' }; + const source2 = { and : 'sandals' }; + const result = assignImpl(target, source1, source2); + + expect(result).to.equal(target); + expect(result).to.deep.equal({ what: 'what', wut: 'socks', and: 'sandals' }); + }); +}); + +describe('getAssign', () => { + it('should return assignImpl if Object.assign does not exist on root', () => { + const result = getAssign({ Object: {} }); + expect(result).to.equal(assignImpl); + }); + + it('should return Object.assign if it exists', () => { + const FAKE = () => { /* lol */ }; + const result = getAssign({ Object: { assign: FAKE } }); + expect(result).to.equal(FAKE); + }); +}); \ No newline at end of file diff --git a/src/util/assign.ts b/src/util/assign.ts index 4dfca286f7..ca06dc72cd 100644 --- a/src/util/assign.ts +++ b/src/util/assign.ts @@ -1,30 +1,20 @@ import { root } from './root'; -const Object = root.Object; - -if (typeof (Object).assign != 'function') { - (function () { - (Object).assign = function assignPolyfill(target: Object, ...sources: Array): Object { - if (target === undefined || target === null) { - throw new TypeError('cannot convert undefined or null to object'); - } - - const output = Object(target); - const len = sources.length; - for (let index = 0; index < len; index++) { - let source = sources[index]; - if (source !== undefined && source !== null) { - for (let key in source) { - if (source.hasOwnProperty(key)) { - output[key] = source[key]; - } - } - } +export function assignImpl(target: Object, ...sources: Object[]) { + const len = sources.length; + for (let i = 0; i < len; i++) { + const source = sources[i]; + for (let k in source) { + if (source.hasOwnProperty(k)) { + target[k] = source[k]; } + } + } + return target; +}; - return output; - }; - })(); +export function getAssign(root: any) { + return root.Object.assign || assignImpl; } -export const assign: (target: Object, ...sources: Array) => Object = Object.assign; \ No newline at end of file +export const assign = getAssign(root); \ No newline at end of file