diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d5c20246682..b9add124fe8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,7 @@ ## Changelog +##### Unreleased +- `String#replaceAll` moved to stage 4, per Jun TC39 meeting + ##### 3.6.5 - 2020.04.09 - Updated Browserlist [#755](https://github.com/zloirock/core-js/issues/755) - Fixed `setImmediate` in Safari [#770](https://github.com/zloirock/core-js/issues/770), thanks [@dtinth](https://github.com/dtinth) diff --git a/README.md b/README.md index 63da489f1562..7e3ee0465e83 100644 --- a/README.md +++ b/README.md @@ -1693,6 +1693,13 @@ class Promise { ```js core-js/proposals/promise-all-settled ``` +##### [`String#replaceAll`](https://github.com/tc39/proposal-string-replace-all) +Module [`esnext.string.replace-all`](https://github.com/zloirock/core-js/blob/v3.6.5/packages/core-js/modules/esnext.string.replace-all.js) +```js +class String { + replaceAll(searchValue: string | RegExp, replaceString: string | (searchValue, index, this) => string): string; +} +``` #### Stage 3 proposals [*CommonJS entry points:*](#commonjs-api) @@ -1732,13 +1739,6 @@ Promise.any([ Promise.reject(3), ]).catch(({ errors }) => console.log(errors)); // => [1, 2, 3] ``` -##### [`String#replaceAll`](https://github.com/tc39/proposal-string-replace-all) -Module [`esnext.string.replace-all`](https://github.com/zloirock/core-js/blob/v3.6.5/packages/core-js/modules/esnext.string.replace-all.js) -```js -class String { - replaceAll(searchValue: string | RegExp, replaceString: string | (searchValue, index, this) => string): string; -} -``` [*CommonJS entry points:*](#commonjs-api) ```js core-js/proposals/string-replace-all diff --git a/packages/core-js-compat/src/data.js b/packages/core-js-compat/src/data.js index 81e7f129b9a1..8709611ed8d8 100644 --- a/packages/core-js-compat/src/data.js +++ b/packages/core-js-compat/src/data.js @@ -1228,6 +1228,12 @@ const data = { firefox: '53', safari: '10.0', }, + 'es.string.replace-all': { + chrome: '85', + firefox: '77', + safari: '13.1', + ios: '13.4', + }, 'esnext.aggregate-error': { }, 'esnext.array.is-template-object': { @@ -1443,8 +1449,7 @@ const data = { }, // TODO: Remove from `core-js@4` 'esnext.string.match-all': null, - 'esnext.string.replace-all': { - }, + 'esnext.string.replace-all': null, 'esnext.symbol.async-dispose': { }, 'esnext.symbol.dispose': { @@ -1523,6 +1528,7 @@ const data = { }; // TODO: Remove from `core-js@4` +data['esnext.string.replace-all'] = data['es.string.replace-all']; data['esnext.global-this'] = data['es.global-this']; data['esnext.promise.all-settled'] = data['es.promise.all-settled']; data['esnext.string.match-all'] = data['es.string.match-all']; diff --git a/packages/core-js-compat/src/modules-by-versions.js b/packages/core-js-compat/src/modules-by-versions.js index 2399c80822d8..53688d7f8ff3 100644 --- a/packages/core-js-compat/src/modules-by-versions.js +++ b/packages/core-js-compat/src/modules-by-versions.js @@ -55,5 +55,6 @@ module.exports = { 3.6: [ 'es.regexp.sticky', 'es.regexp.test', + 'es.string.replace-all', ], }; diff --git a/packages/core-js/es/index.js b/packages/core-js/es/index.js index 9436a3787280..552b4ab609b2 100644 --- a/packages/core-js/es/index.js +++ b/packages/core-js/es/index.js @@ -102,6 +102,7 @@ require('../modules/es.string.small'); require('../modules/es.string.strike'); require('../modules/es.string.sub'); require('../modules/es.string.sup'); +require('../modules/es.string.replace-all'); require('../modules/es.regexp.constructor'); require('../modules/es.regexp.exec'); require('../modules/es.regexp.flags'); diff --git a/packages/core-js/es/string/index.js b/packages/core-js/es/string/index.js index f036fe40760a..b145d7710270 100644 --- a/packages/core-js/es/string/index.js +++ b/packages/core-js/es/string/index.js @@ -10,6 +10,7 @@ require('../../modules/es.string.pad-end'); require('../../modules/es.string.pad-start'); require('../../modules/es.string.repeat'); require('../../modules/es.string.replace'); +require('../../modules/es.string.replace-all'); require('../../modules/es.string.search'); require('../../modules/es.string.split'); require('../../modules/es.string.starts-with'); diff --git a/packages/core-js/es/string/replace-all.js b/packages/core-js/es/string/replace-all.js new file mode 100644 index 000000000000..8bb6c992329a --- /dev/null +++ b/packages/core-js/es/string/replace-all.js @@ -0,0 +1,4 @@ +require('../../modules/es.string.replace-all'); +var entryUnbind = require('../../internals/entry-unbind'); + +module.exports = entryUnbind('String', 'replaceAll'); diff --git a/packages/core-js/es/string/virtual/index.js b/packages/core-js/es/string/virtual/index.js index 1151b7983419..206f2b29fdff 100644 --- a/packages/core-js/es/string/virtual/index.js +++ b/packages/core-js/es/string/virtual/index.js @@ -7,6 +7,7 @@ require('../../../modules/es.string.pad-end'); require('../../../modules/es.string.pad-start'); require('../../../modules/es.string.repeat'); require('../../../modules/es.string.replace'); +require('../../../modules/es.string.replace-all'); require('../../../modules/es.string.search'); require('../../../modules/es.string.split'); require('../../../modules/es.string.starts-with'); diff --git a/packages/core-js/features/string/replace-all.js b/packages/core-js/features/string/replace-all.js index 6de7f5191796..0b8e407b4529 100644 --- a/packages/core-js/features/string/replace-all.js +++ b/packages/core-js/features/string/replace-all.js @@ -1,4 +1 @@ -require('../../modules/esnext.string.replace-all'); -var entryUnbind = require('../../internals/entry-unbind'); - -module.exports = entryUnbind('String', 'replaceAll'); +module.exports = require('../../es/string/replace-all'); diff --git a/packages/core-js/modules/es.string.replace-all.js b/packages/core-js/modules/es.string.replace-all.js new file mode 100644 index 000000000000..22220eee158f --- /dev/null +++ b/packages/core-js/modules/es.string.replace-all.js @@ -0,0 +1,50 @@ +'use strict'; +var $ = require('../internals/export'); +var requireObjectCoercible = require('../internals/require-object-coercible'); +var isRegExp = require('../internals/is-regexp'); +var getRegExpFlags = require('../internals/regexp-flags'); +var wellKnownSymbol = require('../internals/well-known-symbol'); +var IS_PURE = require('../internals/is-pure'); + +var REPLACE = wellKnownSymbol('replace'); +var RegExpPrototype = RegExp.prototype; + +// `String.prototype.replaceAll` method +// https://github.com/tc39/proposal-string-replace-all +$({ target: 'String', proto: true }, { + replaceAll: function replaceAll(searchValue, replaceValue) { + var O = requireObjectCoercible(this); + var IS_REG_EXP, flags, replacer, string, searchString, template, result, position, index; + if (searchValue != null) { + IS_REG_EXP = isRegExp(searchValue); + if (IS_REG_EXP) { + flags = String(requireObjectCoercible('flags' in RegExpPrototype + ? searchValue.flags + : getRegExpFlags.call(searchValue) + )); + if (!~flags.indexOf('g')) throw TypeError('`.replaceAll` does not allow non-global regexes'); + } + replacer = searchValue[REPLACE]; + if (replacer !== undefined) { + return replacer.call(searchValue, O, replaceValue); + } else if (IS_PURE && IS_REG_EXP) { + return String(O).replace(searchValue, replaceValue); + } + } + string = String(O); + searchString = String(searchValue); + if (searchString === '') return replaceAll.call(string, /(?:)/g, replaceValue); + template = string.split(searchString); + if (typeof replaceValue !== 'function') { + return template.join(String(replaceValue)); + } + result = template[0]; + position = result.length; + for (index = 1; index < template.length; index++) { + result += String(replaceValue(searchString, position, string)); + position += searchString.length + template[index].length; + result += template[index]; + } + return result; + } +}); diff --git a/packages/core-js/modules/esnext.string.replace-all.js b/packages/core-js/modules/esnext.string.replace-all.js index 22220eee158f..574c6781ce98 100644 --- a/packages/core-js/modules/esnext.string.replace-all.js +++ b/packages/core-js/modules/esnext.string.replace-all.js @@ -1,50 +1,2 @@ -'use strict'; -var $ = require('../internals/export'); -var requireObjectCoercible = require('../internals/require-object-coercible'); -var isRegExp = require('../internals/is-regexp'); -var getRegExpFlags = require('../internals/regexp-flags'); -var wellKnownSymbol = require('../internals/well-known-symbol'); -var IS_PURE = require('../internals/is-pure'); - -var REPLACE = wellKnownSymbol('replace'); -var RegExpPrototype = RegExp.prototype; - -// `String.prototype.replaceAll` method -// https://github.com/tc39/proposal-string-replace-all -$({ target: 'String', proto: true }, { - replaceAll: function replaceAll(searchValue, replaceValue) { - var O = requireObjectCoercible(this); - var IS_REG_EXP, flags, replacer, string, searchString, template, result, position, index; - if (searchValue != null) { - IS_REG_EXP = isRegExp(searchValue); - if (IS_REG_EXP) { - flags = String(requireObjectCoercible('flags' in RegExpPrototype - ? searchValue.flags - : getRegExpFlags.call(searchValue) - )); - if (!~flags.indexOf('g')) throw TypeError('`.replaceAll` does not allow non-global regexes'); - } - replacer = searchValue[REPLACE]; - if (replacer !== undefined) { - return replacer.call(searchValue, O, replaceValue); - } else if (IS_PURE && IS_REG_EXP) { - return String(O).replace(searchValue, replaceValue); - } - } - string = String(O); - searchString = String(searchValue); - if (searchString === '') return replaceAll.call(string, /(?:)/g, replaceValue); - template = string.split(searchString); - if (typeof replaceValue !== 'function') { - return template.join(String(replaceValue)); - } - result = template[0]; - position = result.length; - for (index = 1; index < template.length; index++) { - result += String(replaceValue(searchString, position, string)); - position += searchString.length + template[index].length; - result += template[index]; - } - return result; - } -}); +// TODO: Remove from `core-js@4` +require('./es.string.replace-all'); diff --git a/packages/core-js/stable/string/replace-all.js b/packages/core-js/stable/string/replace-all.js new file mode 100644 index 000000000000..ae503aabe9be --- /dev/null +++ b/packages/core-js/stable/string/replace-all.js @@ -0,0 +1,3 @@ +var parent = require('../../es/string/replace-all'); + +module.exports = parent; diff --git a/packages/core-js/stage/3.js b/packages/core-js/stage/3.js index 4d694c96b026..4386bbbd410c 100644 --- a/packages/core-js/stage/3.js +++ b/packages/core-js/stage/3.js @@ -1,5 +1,4 @@ require('../proposals/promise-any'); -require('../proposals/string-replace-all'); var parent = require('./4'); module.exports = parent; diff --git a/packages/core-js/stage/4.js b/packages/core-js/stage/4.js index b9b4497be826..b3e8b26a9a2a 100644 --- a/packages/core-js/stage/4.js +++ b/packages/core-js/stage/4.js @@ -1,6 +1,7 @@ require('../proposals/global-this'); require('../proposals/promise-all-settled'); require('../proposals/string-match-all'); +require('../proposals/string-replace-all'); var path = require('../internals/path'); module.exports = path; diff --git a/tests/commonjs.js b/tests/commonjs.js index 1774057abeec..ea37a23fc94f 100644 --- a/tests/commonjs.js +++ b/tests/commonjs.js @@ -581,6 +581,7 @@ for (const _PATH of ['../packages/core-js-pure', '../packages/core-js']) { ok(typeof load('stable/string/strike') === 'function'); ok(typeof load('stable/string/sub') === 'function'); ok(typeof load('stable/string/sup') === 'function'); + ok(typeof load('stable/string/replace-all') === 'function'); ok(load('stable/string/pad-start')('a', 3) === ' a'); ok(load('stable/string/pad-end')('a', 3) === 'a '); ok(load('stable/string/trim-start')(' a ') === 'a '); @@ -851,6 +852,7 @@ for (const _PATH of ['../packages/core-js-pure', '../packages/core-js']) { ok(typeof load('es/string/strike') === 'function'); ok(typeof load('es/string/sub') === 'function'); ok(typeof load('es/string/sup') === 'function'); + ok(typeof load('es/string/replace-all') === 'function'); ok(load('es/string/pad-start')('a', 3) === ' a'); ok(load('es/string/pad-end')('a', 3) === 'a '); ok('next' in load('es/string/iterator')('qwe')); diff --git a/tests/compat/tests.js b/tests/compat/tests.js index d2b8090d2a23..21851c9f8492 100644 --- a/tests/compat/tests.js +++ b/tests/compat/tests.js @@ -875,6 +875,9 @@ GLOBAL.tests = { && 'a'.replace(/./, '$0') === '$0' && /./[Symbol.replace]('a', '$0') === '$0'; }, + 'es.string.replace-all': function () { + return String.prototype.replaceAll; + }, 'es.string.search': function () { var O = {}; O[Symbol.search] = function () { return 7; }; @@ -1401,9 +1404,6 @@ GLOBAL.tests = { 'esnext.string.code-points': function () { return String.prototype.codePoints; }, - 'esnext.string.replace-all': function () { - return String.prototype.replaceAll; - }, 'esnext.symbol.dispose': function () { return Symbol.dispose; }, diff --git a/tests/pure/esnext.string.replace-all.js b/tests/pure/es.string.replace-all.js similarity index 100% rename from tests/pure/esnext.string.replace-all.js rename to tests/pure/es.string.replace-all.js diff --git a/tests/tests/esnext.string.replace-all.js b/tests/tests/es.string.replace-all.js similarity index 100% rename from tests/tests/esnext.string.replace-all.js rename to tests/tests/es.string.replace-all.js diff --git a/tests/tests/index.js b/tests/tests/index.js index 9e1ac40ccbf7..6d486a217d9b 100644 --- a/tests/tests/index.js +++ b/tests/tests/index.js @@ -137,6 +137,7 @@ import './es.string.pad-start'; import './es.string.raw'; import './es.string.repeat'; import './es.string.replace'; +import './es.string.replace-all'; import './es.string.search'; import './es.string.small'; import './es.string.split'; @@ -294,7 +295,6 @@ import './esnext.set.symmetric-difference'; import './esnext.set.union'; import './esnext.string.at'; import './esnext.string.code-points'; -import './esnext.string.replace-all'; import './esnext.symbol.async-dispose'; import './esnext.symbol.dispose'; import './esnext.symbol.observable';