From 2394dacaa5937e77e692a0821424322ed2578e9c Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Sun, 28 Feb 2021 22:28:39 +0700 Subject: [PATCH] added a workaround for Chrome 38-40 bug which does not allow to inherit symbols (incl. well-known) from DOM collections prototypes to instances #37 #406 --- CHANGELOG.md | 1 + packages/core-js-compat/src/data.js | 6 ++--- packages/core-js/internals/native-symbol.js | 8 ++++-- .../core-js/internals/well-known-symbol.js | 9 ++++--- tests/compat/tests.js | 27 ++++++++++++++----- 5 files changed, 36 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b84b988c818..6d1068dcd40d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ## Changelog ##### Unreleased +- Added a workaround for Chrome 38-40 bug which does not allow to inherit symbols (incl. well-known) from DOM collections prototypes to instances, [#37](https://github.com/zloirock/core-js/issues/37) - Used `NumericRangeIterator` as toStringTag instead of `RangeIterator` in `{ Number, BigInt }.range` iterator, per [this PR](https://github.com/tc39/proposal-Number.range/pull/46) - TypedArray constructors marked as supported from Safari 14.0 - Updated compat data mapping for iOS Safari and Opera for Android diff --git a/packages/core-js-compat/src/data.js b/packages/core-js-compat/src/data.js index 961b7b7d2014..0856120b6f6b 100644 --- a/packages/core-js-compat/src/data.js +++ b/packages/core-js-compat/src/data.js @@ -29,7 +29,7 @@ const data = { safari: '10.0', }, 'es.symbol.iterator': { - chrome: '39', + chrome: '41', edge: '13', firefox: '36', safari: '9.0', @@ -78,7 +78,7 @@ const data = { safari: '10.0', }, 'es.symbol.unscopables': { - chrome: '39', + chrome: '41', edge: '13', firefox: '48', safari: '9.0', @@ -880,7 +880,7 @@ const data = { safari: '10.0', }, 'es.string.iterator': { - chrome: '39', + chrome: '41', edge: '13', firefox: '36', safari: '9.0', diff --git a/packages/core-js/internals/native-symbol.js b/packages/core-js/internals/native-symbol.js index 18ed90884e38..86d5f4ee9f5a 100644 --- a/packages/core-js/internals/native-symbol.js +++ b/packages/core-js/internals/native-symbol.js @@ -1,7 +1,11 @@ +var IS_NODE = require('../internals/engine-is-node'); +var V8_VERSION = require('../internals/engine-v8-version'); var fails = require('../internals/fails'); module.exports = !!Object.getOwnPropertySymbols && !fails(function () { - // Chrome 38 Symbol has incorrect toString conversion /* global Symbol -- required for testing */ - return !String(Symbol()); + return !Symbol.sham && + // Chrome 38 Symbol has incorrect toString conversion + // Chrome 38-40 symbols are not inherited from DOM collections prototypes to instances + (IS_NODE ? V8_VERSION === 38 : V8_VERSION > 37 && V8_VERSION < 41); }); diff --git a/packages/core-js/internals/well-known-symbol.js b/packages/core-js/internals/well-known-symbol.js index 3fcc8c3a0524..c9518bf47e10 100644 --- a/packages/core-js/internals/well-known-symbol.js +++ b/packages/core-js/internals/well-known-symbol.js @@ -10,8 +10,11 @@ var Symbol = global.Symbol; var createWellKnownSymbol = USE_SYMBOL_AS_UID ? Symbol : Symbol && Symbol.withoutSetter || uid; module.exports = function (name) { - if (!has(WellKnownSymbolsStore, name)) { - if (NATIVE_SYMBOL && has(Symbol, name)) WellKnownSymbolsStore[name] = Symbol[name]; - else WellKnownSymbolsStore[name] = createWellKnownSymbol('Symbol.' + name); + if (!has(WellKnownSymbolsStore, name) || !(NATIVE_SYMBOL || typeof WellKnownSymbolsStore[name] == 'string')) { + if (NATIVE_SYMBOL && has(Symbol, name)) { + WellKnownSymbolsStore[name] = Symbol[name]; + } else { + WellKnownSymbolsStore[name] = createWellKnownSymbol('Symbol.' + name); + } } return WellKnownSymbolsStore[name]; }; diff --git a/tests/compat/tests.js b/tests/compat/tests.js index b34a22656ac0..812fdee90bbc 100644 --- a/tests/compat/tests.js +++ b/tests/compat/tests.js @@ -8,6 +8,24 @@ var NOT_WHITESPACES = '\u200B\u0085\u180E'; var USERAGENT = GLOBAL.navigator && GLOBAL.navigator.userAgent || ''; +var process = GLOBAL.process; +var v8 = process && process.versions && process.versions.v8 || ''; + +var match, V8_VERSION; + +if (v8) { + match = v8.split('.'); + V8_VERSION = +(match[0] + match[1]); +} else if (USERAGENT) { + match = USERAGENT.match(/Edge\/(\d+)/); + if (!match || match[1] >= 74) { + match = USERAGENT.match(/Chrome\/(\d+)/); + if (match) V8_VERSION = +match[1]; + } +} + +var IS_NODE = Object.prototype.toString.call(process) == '[object process]'; + // eslint-disable-next-line unicorn/no-unsafe-regex -- safe var WEBKIT_STRING_PAD_BUG = /Version\/10\.\d+(\.\d+)?( Mobile\/\w+)? Safari\//.test(USERAGENT); @@ -16,10 +34,6 @@ var DESCRIPTORS_SUPPORT = function () { }; var PROMISES_SUPPORT = function () { - var process = GLOBAL.process; - var IS_NODE = Object.prototype.toString.call(process) == '[object process]'; - var v8 = process && process.versions && process.versions.v8 || ''; - var promise = Promise.resolve(1); var empty = function () { /* empty */ }; var FakePromise = (promise.constructor = {})[Symbol.species] = function (exec) { @@ -28,12 +42,11 @@ var PROMISES_SUPPORT = function () { return (IS_NODE || typeof PromiseRejectionEvent == 'function') && promise.then(empty) instanceof FakePromise - && v8.indexOf('6.6') !== 0 - && USERAGENT.indexOf('Chrome/66') === -1; + && V8_VERSION !== 66; }; var SYMBOLS_SUPPORT = function () { - return String(Symbol()); + return Symbol && (IS_NODE ? V8_VERSION !== 38 : V8_VERSION < 38 || V8_VERSION > 40); }; var URL_AND_URL_SEARCH_PARAMS_SUPPORT = function () {