From 6319f3c5be315de65db50db371486515afabae64 Mon Sep 17 00:00:00 2001 From: Ben Lesh Date: Tue, 6 Mar 2018 19:00:23 -0800 Subject: [PATCH] feat(Symbol.iterator): no longer polyfilled (#3389) BREAKING CHANGE: We are no longer polyfilling `Symbol.iterator`. That would be done by a proper polyfilling library --- spec/symbol/iterator-spec.ts | 100 -------------------------------- src/internal/symbol/iterator.ts | 40 +++---------- 2 files changed, 9 insertions(+), 131 deletions(-) delete mode 100644 spec/symbol/iterator-spec.ts diff --git a/spec/symbol/iterator-spec.ts b/spec/symbol/iterator-spec.ts deleted file mode 100644 index 91e4bba774..0000000000 --- a/spec/symbol/iterator-spec.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { expect } from 'chai'; -import { $$iterator, symbolIteratorPonyfill } from '../../src/internal/symbol/iterator'; - -describe('iterator symbol', () => { - it('should exist', () => { - expect($$iterator).to.exist; - }); -}); - -describe('symbolIteratorPonyfill', () => { - describe('when root.Symbol is a function', () => { - describe('and Symbol.iterator exists', () => { - it('should return Symbol.iterator', () => { - const FakeSymbol = function () { /* lol */ }; - (FakeSymbol).iterator = {}; - const result = symbolIteratorPonyfill({ Symbol: FakeSymbol }); - expect(result).to.equal((FakeSymbol).iterator); - }); - }); - - describe('and Symbol.iterator does not exist', () => { - it('should use Symbol to create an return a symbol and polyfill Symbol.iterator', () => { - const SYMBOL_RETURN = {}; - let passedDescription: string; - const root = { - Symbol: function (description: string) { - passedDescription = description; - return SYMBOL_RETURN; - } - }; - - const result = symbolIteratorPonyfill(root); - expect(result).to.equal(SYMBOL_RETURN); - expect((root.Symbol).iterator).to.equal(SYMBOL_RETURN); - }); - }); - }); - - describe('when root.Symbol is NOT a function', () => { - describe('and root.Set exists with an @@iterator property that is a function (Mozilla bug)', () => { - it ('should return "$$iterator"', () => { - const result = symbolIteratorPonyfill({ - Set: function FakeSet() { - this['@@iterator'] = function () { /* lol */ }; - } - }); - expect(result).to.equal('@@iterator'); - }); - }); - - describe('root.Set does not exit or does not have an @@iterator property', () => { - describe('but Map exists and a random key on Map.prototype that matches Map.prototype.entries (for es6-shim)', () => { - it('should return the key that matches the "entries" key on Map.prototype, but not return "size"', () => { - function FakeMap() { /* lol */ } - function fakeMethod() { /* lol */ } - FakeMap.prototype['-omg-lol-i-can-use-whatever-I-want-YOLO-'] = fakeMethod; - FakeMap.prototype.entries = fakeMethod; - FakeMap.prototype.size = fakeMethod; - const root = { - Map: FakeMap - }; - - const result = symbolIteratorPonyfill(root); - expect(result).to.equal('-omg-lol-i-can-use-whatever-I-want-YOLO-'); - }); - }); - - describe('but Map exists and no other key except "size" on Map.prototype that matches Map.prototype.entries (for es6-shim)', () => { - it('should return "@@iterator"', () => { - function FakeMap() { /* lol */ } - function fakeMethod() { /* lol */ } - FakeMap.prototype.entries = fakeMethod; - FakeMap.prototype.size = fakeMethod; - const root = { - Map: FakeMap - }; - - const result = symbolIteratorPonyfill(root); - expect(result).to.equal('@@iterator'); - }); - }); - - describe('if Set exists but has no iterator, and Map does not exist (bad polyfill maybe?)', () => { - it('should return "@@iterator"', () => { - const result = symbolIteratorPonyfill({ - Set: function () { /* lol */ } - }); - expect(result).to.equal('@@iterator'); - }); - }); - - describe('and root.Set and root.Map do NOT exist', () => { - it('should return "@@iterator"', () => { - const result = symbolIteratorPonyfill({}); - expect(result).to.equal('@@iterator'); - }); - }); - }); - }); -}); diff --git a/src/internal/symbol/iterator.ts b/src/internal/symbol/iterator.ts index cdee34a606..2475131f06 100644 --- a/src/internal/symbol/iterator.ts +++ b/src/internal/symbol/iterator.ts @@ -1,38 +1,16 @@ -import { root } from '../util/root'; -export function symbolIteratorPonyfill(root: any) { - const Symbol: any = root.Symbol; - - if (typeof Symbol === 'function') { - if (!Symbol.iterator) { - Symbol.iterator = Symbol('iterator polyfill'); - } - return Symbol.iterator; - } else { - // [for Mozilla Gecko 27-35:](https://mzl.la/2ewE1zC) - const { Set } = root; - if (Set && typeof new Set()['@@iterator'] === 'function') { - return '@@iterator'; - } - const { Map } = root; - // required for compatability with es6-shim - if (Map) { - let keys = Object.getOwnPropertyNames(Map.prototype); - for (let i = 0; i < keys.length; ++i) { - let key = keys[i]; - // according to spec, Map.prototype[@@iterator] and Map.orototype.entries must be equal. - if (key !== 'entries' && key !== 'size' && Map.prototype[key] === Map.prototype['entries']) { - return key; - } - } - } - return '@@iterator'; - } +/* NOTE: Warning users that they don't have a Symbol.iterator + polyfill. We don't want to throw on this, because it's not required + by the library. However it will provide clues to users on older + browsers why things like `from(iterable)` doesn't work. */ +if (!Symbol || !Symbol.iterator) { + console.warn('RxJS: Symbol.observable does not exist'); } -export const iterator = symbolIteratorPonyfill(root); +/** The native Symbol.iterator instance or a string */ +export const iterator = Symbol && Symbol.iterator || '@@iterator'; /** - * @deprecated use iterator instead + * @deprecated use {@link iterator} instead */ export const $$iterator = iterator;