diff --git a/CHANGELOG.md b/CHANGELOG.md index e4166c9a5e9f..b207fa80326d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ ## Changelog ##### Unreleased +- Added `RegExp` named capture groups polyfill, [#521](https://github.com/zloirock/core-js/issues/521) +- Added `RegExp` `dotAll` flag polyfill, [#792](https://github.com/zloirock/core-js/issues/792) - Added missed polyfills of [Annex B](https://tc39.es/ecma262/#sec-additional-built-in-properties) features (required mainly for some non-browser engines), [#336](https://github.com/zloirock/core-js/issues/336): - `escape` - `unescape` @@ -7,7 +9,7 @@ - `Date.prototype.getYear` - `Date.prototype.setYear` - `Date.prototype.toGMTString` -- Fixed detection of forbidden host code points in URL polyfill +- Fixed detection of forbidden host code points in `URL` polyfill - Allowed `rhino` target in `core-js-compat` / `core-js-builder`, added compat data for `rhino` 1.7.13, [#942](https://github.com/zloirock/core-js/issues/942), thanks [@gausie](https://github.com/gausie) - `.at` marked as supported from FF90 diff --git a/README.md b/README.md index 962bbea2e92e..2c5a79908412 100644 --- a/README.md +++ b/README.md @@ -669,7 +669,7 @@ Adding support of well-known [symbols](#ecmascript-symbol) `@@match`, `@@replace Annex B methods. Modules [`es.string.anchor`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.string.anchor.js), [`es.string.big`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.string.big.js), [`es.string.blink`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.string.blink.js), [`es.string.bold`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.string.bold.js), [`es.string.fixed`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.string.fixed.js), [`es.string.fontcolor`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.string.fontcolor.js), [`es.string.fontsize`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.string.fontsize.js), [`es.string.italics`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.string.italics.js), [`es.string.link`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.string.link.js), [`es.string.small`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.string.small.js), [`es.string.strike`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.string.strike.js), [`es.string.sub`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.string.sub.js), [`es.string.sup`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.string.sup.js), [`es.string.substr`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.string.substr.js), [`es.escape`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.escape.js) and [`es.unescape`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.unescape.js). -`RegExp` features: modules [`es.regexp.constructor`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.regexp.constructor.js), [`es.regexp.flags`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.regexp.flags.js), [`es.regexp.sticky`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.regexp.sticky.js) and [`es.regexp.test`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.regexp.test.js). +`RegExp` features: modules [`es.regexp.constructor`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.regexp.constructor.js), [`es.regexp.dot-all`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.regexp.dot-all.js), [`es.regexp.flags`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.regexp.flags.js), [`es.regexp.sticky`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.regexp.sticky.js) and [`es.regexp.test`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.regexp.test.js). ```js class String { static fromCodePoint(...codePoints: Array): string; @@ -710,7 +710,8 @@ class String { } class RegExp { - constructor(pattern: RegExp | string, flags?: string): RegExp; // support of sticky (`y`) flag; can alter flags + // support of sticky (`y`) flag, dotAll (`s`) flag, named capture groups, can alter flags + constructor(pattern: RegExp | string, flags?: string): RegExp; exec(): Array | null; // IE8 fixes test(string: string): boolean; // delegation to `.exec` toString(): string; // ES2015+ fix - generic @@ -719,8 +720,9 @@ class RegExp { @@replace(string: string, replaceValue: Function | string): string; @@search(string: string): number; @@split(string: string, limit: number): Array; - readonly attribute flags: string; // IE9+ - readonly attribute sticky: boolean; + readonly attribute dotAll: boolean; // IE9+ + readonly attribute flags: string; // IE9+ + readonly attribute sticky: boolean; // IE9+ } function escape(string: string): string; @@ -766,6 +768,7 @@ core-js(-pure)/es|stable|features/string(/virtual)/sup core-js(-pure)/es|stable|features/string(/virtual)/iterator core-js/es|stable|features/regexp core-js/es|stable|features/regexp/constructor +core-js/es|stable|features/regexp/dot-all core-js(-pure)/es|stable|features/regexp/flags core-js/es|stable|features/regexp/sticky core-js/es|stable|features/regexp/test @@ -773,7 +776,7 @@ core-js/es|stable|features/regexp/to-string core-js/es|stable|features/escape core-js/es|stable|features/unescape ``` -[*Examples*](http://es6.zloirock.ru/#for(var%20val%20of%20'a%F0%A0%AE%B7b')%7B%0A%20%20log(val)%3B%20%2F%2F%20%3D%3E%20'a'%2C%20'%F0%A0%AE%B7'%2C%20'b'%0A%7D%0A%0Alog('foobarbaz'.includes('bar'))%3B%20%20%20%20%20%20%2F%2F%20%3D%3E%20true%0Alog('foobarbaz'.includes('bar'%2C%204))%3B%20%20%20%2F%2F%20%3D%3E%20false%0Alog('foobarbaz'.startsWith('foo'))%3B%20%20%20%20%2F%2F%20%3D%3E%20true%0Alog('foobarbaz'.startsWith('bar'%2C%203))%3B%20%2F%2F%20%3D%3E%20true%0Alog('foobarbaz'.endsWith('baz'))%3B%20%20%20%20%20%20%2F%2F%20%3D%3E%20true%0Alog('foobarbaz'.endsWith('bar'%2C%206))%3B%20%20%20%2F%2F%20%3D%3E%20true%0A%0Alog('string'.repeat(3))%3B%20%2F%2F%20%3D%3E%20'stringstringstring'%0A%0Alog('hello'.padStart(10))%3B%20%20%20%20%20%20%20%20%20%2F%2F%20%3D%3E%20'%20%20%20%20%20hello'%0Alog('hello'.padStart(10%2C%20'1234'))%3B%20%2F%2F%20%3D%3E%20'12341hello'%0Alog('hello'.padEnd(10))%3B%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%3D%3E%20'hello%20%20%20%20%20'%0Alog('hello'.padEnd(10%2C%20'1234'))%3B%20%20%20%2F%2F%20%3D%3E%20'hello12341'%0A%0Alog('%F0%A0%AE%B7'.codePointAt(0))%3B%20%2F%2F%20%3D%3E%20134071%0A%0Avar%20name%20%3D%20'Bob'%3B%0Alog(String.raw%60Hi%5Cn%24%7Bname%7D!%60)%3B%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%3D%3E%20'Hi%5C%5CnBob!'%20(ES6%20template%20string%20syntax)%0Alog(String.raw(%7B%20raw%3A%20'test'%20%7D%2C%200%2C%201%2C%202))%3B%20%2F%2F%20%3D%3E%20%2F%2F%20't0e1s2t'%0A%0Alog('foo'.bold())%3B%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%3D%3E%20'%3Cb%3Efoo%3C%2Fb%3E'%0Alog('bar'.anchor('a%22b'))%3B%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%3D%3E%20'%3Ca%20name%3D%22a%26quot%3Bb%22%3Ebar%3C%2Fa%3E'%0Alog('baz'.link('http%3A%2F%2Fexample.com'))%3B%20%2F%2F%20%3D%3E%20'%3Ca%20href%3D%22http%3A%2F%2Fexample.com%22%3Ebaz%3C%2Fa%3E'%0A%0Alog(RegExp(%2F.%2Fg%2C%20'm'))%3B%20%2F%2F%20%3D%3E%20%2F.%2Fm%0A%0Alog(%2Ffoo%2F.flags)%3B%20%20%20%20%2F%2F%20%3D%3E%20''%0Alog(%2Ffoo%2Fgim.flags)%3B%20%2F%2F%20%3D%3E%20'gim'%0A%0Alog(RegExp('foo'%2C%20'y').sticky)%3B%20%2F%2F%20%3D%3E%20true%0A%0Aconst%20text%20%3D%20'First%20line%5CnSecond%20line'%3B%0Aconst%20regex%20%3D%20RegExp('(%5C%5CS%2B)%20line%5C%5Cn%3F'%2C%20'y')%3B%0A%0Alog(regex.exec(text)%5B1%5D)%3B%20%2F%2F%20%3D%3E%20'First'%0Alog(regex.exec(text)%5B1%5D)%3B%20%2F%2F%20%3D%3E%20'Second'%0Alog(regex.exec(text))%3B%20%20%20%20%2F%2F%20%3D%3E%20null%0A%0Alog('foo'.match(%7B%5BSymbol.match%5D%3A%20_%20%3D%3E%201%7D))%3B%20%20%20%20%20%2F%2F%20%3D%3E%201%0Alog('foo'.replace(%7B%5BSymbol.replace%5D%3A%20_%20%3D%3E%202%7D))%3B%20%2F%2F%20%3D%3E%202%0Alog('foo'.search(%7B%5BSymbol.search%5D%3A%20_%20%3D%3E%203%7D))%3B%20%20%20%2F%2F%20%3D%3E%203%0Alog('foo'.split(%7B%5BSymbol.split%5D%3A%20_%20%3D%3E%204%7D))%3B%20%20%20%20%20%2F%2F%20%3D%3E%204%0A%0Alog(RegExp.prototype.toString.call(%7Bsource%3A%20'foo'%2C%20flags%3A%20'bar'%7D))%3B%0A%0Alog('%20%20%20hello%20%20%20'.trimLeft())%3B%20%20%2F%2F%20%3D%3E%20'hello%20%20%20'%0Alog('%20%20%20hello%20%20%20'.trimRight())%3B%20%2F%2F%20%3D%3E%20'%20%20%20hello'%0Alog('%20%20%20hello%20%20%20'.trimStart())%3B%20%2F%2F%20%3D%3E%20'hello%20%20%20'%0Alog('%20%20%20hello%20%20%20'.trimEnd())%3B%20%20%20%2F%2F%20%3D%3E%20'%20%20%20hello'%0A%0Afor%20(let%20%5B_%2C%20d%2C%20D%5D%20of%20'1111a2b3cccc'.matchAll(%2F(%5Cd)(%5CD)%2Fg))%20%7B%0A%20%20log(d%2C%20D)%3B%20%2F%2F%20%3D%3E%201%20a%2C%202%20b%2C%203%20c%0A%7D%0A%0Alog('Test%20abc%20test%20test%20abc%20test.'.replaceAll('abc'%2C%20'foo'))%3B%20%2F%2F%20-%3E%20'Test%20foo%20test%20test%20foo%20test.'): +[*Examples*](http://es6.zloirock.ru/#for(var%20val%20of%20'a%F0%A0%AE%B7b')%7B%0A%20%20log(val)%3B%20%2F%2F%20%3D%3E%20'a'%2C%20'%F0%A0%AE%B7'%2C%20'b'%0A%7D%0A%0Alog('foobarbaz'.includes('bar'))%3B%20%20%20%20%20%20%2F%2F%20%3D%3E%20true%0Alog('foobarbaz'.includes('bar'%2C%204))%3B%20%20%20%2F%2F%20%3D%3E%20false%0Alog('foobarbaz'.startsWith('foo'))%3B%20%20%20%20%2F%2F%20%3D%3E%20true%0Alog('foobarbaz'.startsWith('bar'%2C%203))%3B%20%2F%2F%20%3D%3E%20true%0Alog('foobarbaz'.endsWith('baz'))%3B%20%20%20%20%20%20%2F%2F%20%3D%3E%20true%0Alog('foobarbaz'.endsWith('bar'%2C%206))%3B%20%20%20%2F%2F%20%3D%3E%20true%0A%0Alog('string'.repeat(3))%3B%20%2F%2F%20%3D%3E%20'stringstringstring'%0A%0Alog('hello'.padStart(10))%3B%20%20%20%20%20%20%20%20%20%2F%2F%20%3D%3E%20'%20%20%20%20%20hello'%0Alog('hello'.padStart(10%2C%20'1234'))%3B%20%2F%2F%20%3D%3E%20'12341hello'%0Alog('hello'.padEnd(10))%3B%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%3D%3E%20'hello%20%20%20%20%20'%0Alog('hello'.padEnd(10%2C%20'1234'))%3B%20%20%20%2F%2F%20%3D%3E%20'hello12341'%0A%0Alog('%F0%A0%AE%B7'.codePointAt(0))%3B%20%2F%2F%20%3D%3E%20134071%0A%0Avar%20name%20%3D%20'Bob'%3B%0Alog(String.raw%60Hi%5Cn%24%7Bname%7D!%60)%3B%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%3D%3E%20'Hi%5C%5CnBob!'%20(ES6%20template%20string%20syntax)%0Alog(String.raw(%7B%20raw%3A%20'test'%20%7D%2C%200%2C%201%2C%202))%3B%20%2F%2F%20%3D%3E%20%2F%2F%20't0e1s2t'%0A%0Alog('foo'.bold())%3B%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%3D%3E%20'%3Cb%3Efoo%3C%2Fb%3E'%0Alog('bar'.anchor('a%22b'))%3B%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20%3D%3E%20'%3Ca%20name%3D%22a%26quot%3Bb%22%3Ebar%3C%2Fa%3E'%0Alog('baz'.link('http%3A%2F%2Fexample.com'))%3B%20%2F%2F%20%3D%3E%20'%3Ca%20href%3D%22http%3A%2F%2Fexample.com%22%3Ebaz%3C%2Fa%3E'%0A%0Alog(RegExp('.'%2C%20's').test('%5Cn'))%3B%20%2F%2F%20%3D%3E%20true%0Alog(RegExp('.'%2C%20's').dotAll)%3B%20%20%20%20%20%2F%2F%20%3D%3E%20true%0A%0Alog(RegExp('foo%3A(%3F%3Cfoo%3E%5C%5Cw%2B)%2Cbar%3A(%3F%3Cbar%3E%5C%5Cw%2B)').exec('foo%3Aabc%2Cbar%3Adef').groups.bar)%3B%20%2F%2F%20%3D%3E%20'def'%0A%0Alog('foo%3Aabc%2Cbar%3Adef'.replace(RegExp('foo%3A(%3F%3Cfoo%3E%5C%5Cw%2B)%2Cbar%3A(%3F%3Cbar%3E%5C%5Cw%2B)')%2C%20'%24%3Cbar%3E%2C%24%3Cfoo%3E'))%3B%20%2F%2F%20%3D%3E%20'def%2Cabc'%0A%0Alog(RegExp(%2F.%2Fg%2C%20'm'))%3B%20%2F%2F%20%3D%3E%20%2F.%2Fm%0A%0Alog(%2Ffoo%2F.flags)%3B%20%20%20%20%2F%2F%20%3D%3E%20''%0Alog(%2Ffoo%2Fgim.flags)%3B%20%2F%2F%20%3D%3E%20'gim'%0A%0Alog(RegExp('foo'%2C%20'y').sticky)%3B%20%2F%2F%20%3D%3E%20true%0A%0Aconst%20text%20%3D%20'First%20line%5CnSecond%20line'%3B%0Aconst%20regex%20%3D%20RegExp('(%5C%5CS%2B)%20line%5C%5Cn%3F'%2C%20'y')%3B%0A%0Alog(regex.exec(text)%5B1%5D)%3B%20%2F%2F%20%3D%3E%20'First'%0Alog(regex.exec(text)%5B1%5D)%3B%20%2F%2F%20%3D%3E%20'Second'%0Alog(regex.exec(text))%3B%20%20%20%20%2F%2F%20%3D%3E%20null%0A%0Alog('foo'.match(%7B%5BSymbol.match%5D%3A%20_%20%3D%3E%201%7D))%3B%20%20%20%20%20%2F%2F%20%3D%3E%201%0Alog('foo'.replace(%7B%5BSymbol.replace%5D%3A%20_%20%3D%3E%202%7D))%3B%20%2F%2F%20%3D%3E%202%0Alog('foo'.search(%7B%5BSymbol.search%5D%3A%20_%20%3D%3E%203%7D))%3B%20%20%20%2F%2F%20%3D%3E%203%0Alog('foo'.split(%7B%5BSymbol.split%5D%3A%20_%20%3D%3E%204%7D))%3B%20%20%20%20%20%2F%2F%20%3D%3E%204%0A%0Alog(RegExp.prototype.toString.call(%7Bsource%3A%20'foo'%2C%20flags%3A%20'bar'%7D))%3B%0A%0Alog('%20%20%20hello%20%20%20'.trimLeft())%3B%20%20%2F%2F%20%3D%3E%20'hello%20%20%20'%0Alog('%20%20%20hello%20%20%20'.trimRight())%3B%20%2F%2F%20%3D%3E%20'%20%20%20hello'%0Alog('%20%20%20hello%20%20%20'.trimStart())%3B%20%2F%2F%20%3D%3E%20'hello%20%20%20'%0Alog('%20%20%20hello%20%20%20'.trimEnd())%3B%20%20%20%2F%2F%20%3D%3E%20'%20%20%20hello'%0A%0Afor%20(let%20%5B_%2C%20d%2C%20D%5D%20of%20'1111a2b3cccc'.matchAll(%2F(%5Cd)(%5CD)%2Fg))%20%7B%0A%20%20log(d%2C%20D)%3B%20%2F%2F%20%3D%3E%201%20a%2C%202%20b%2C%203%20c%0A%7D%0A%0Alog('Test%20abc%20test%20test%20abc%20test.'.replaceAll('abc'%2C%20'foo'))%3B%20%2F%2F%20-%3E%20'Test%20foo%20test%20test%20foo%20test.'): ```js for (let value of 'a𠮷b') { console.log(value); // => 'a', '𠮷', 'b' @@ -804,6 +807,13 @@ String.raw({ raw: 'test' }, 0, 1, 2); // => 't0e1s2t' 'bar'.anchor('a"b'); // => 'bar' 'baz'.link('http://example.com'); // => 'baz' +RegExp('.', 's').test('\n'); // => true +RegExp('.', 's').dotAll; // => true + +RegExp('foo:(?\\w+),bar:(?\\w+)').exec('foo:abc,bar:def').groups.bar; // => 'def' + +'foo:abc,bar:def'.replace(RegExp('foo:(?\\w+),bar:(?\\w+)'), '$,$'); // => 'def,abc' + RegExp(/./g, 'm'); // => /./m /foo/.flags; // => '' diff --git a/packages/core-js/internals/regexp-exec.js b/packages/core-js/internals/regexp-exec.js index c8b9ae72bc71..099e9b35ceb0 100644 --- a/packages/core-js/internals/regexp-exec.js +++ b/packages/core-js/internals/regexp-exec.js @@ -33,9 +33,9 @@ if (PATCH) { // eslint-disable-next-line max-statements -- TODO patchedExec = function exec(str) { var re = this; - var lastIndex, reCopy, match, i, result, object, group; var state = getInternalState(re); var raw = state.raw; + var result, reCopy, lastIndex, match, i, object, group; if (raw) { raw.lastIndex = re.lastIndex; diff --git a/packages/core-js/modules/es.regexp.constructor.js b/packages/core-js/modules/es.regexp.constructor.js index 5b99c05a4e96..e7b7c59de314 100644 --- a/packages/core-js/modules/es.regexp.constructor.js +++ b/packages/core-js/modules/es.regexp.constructor.js @@ -92,7 +92,7 @@ var handleNCG = function (string) { continue; case chr === '>' && ncg: if (groupname === '' || has(names, groupname)) { - throw new TypeError('Invalid capture group name'); + throw new SyntaxError('Invalid capture group name'); } names[groupname] = true; named.push([groupname, groupid]); diff --git a/packages/core-js/modules/es.string.replace.js b/packages/core-js/modules/es.string.replace.js index 0ec51a2d9dea..89fb9493a3e3 100644 --- a/packages/core-js/modules/es.string.replace.js +++ b/packages/core-js/modules/es.string.replace.js @@ -51,8 +51,9 @@ fixRegExpWellKnownSymbolLogic('replace', function (_, nativeReplace, maybeCallNa // https://tc39.es/ecma262/#sec-regexp.prototype-@@replace function (string, replaceValue) { if ( - (!REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE && REPLACE_KEEPS_$0) || - (typeof replaceValue === 'string' && replaceValue.indexOf(UNSAFE_SUBSTITUTE) === -1) + typeof replaceValue === 'string' && + replaceValue.indexOf(UNSAFE_SUBSTITUTE) === -1 && + replaceValue.indexOf('$<') === -1 ) { var res = maybeCallNative(nativeReplace, this, string, replaceValue); if (res.done) return res.value; diff --git a/tests/compat/tests.js b/tests/compat/tests.js index 6e4a09bb9aaf..1db06e5a674b 100644 --- a/tests/compat/tests.js +++ b/tests/compat/tests.js @@ -145,6 +145,12 @@ var TYPED_ARRAY_CONSTRUCTORS_NOT_REQUIRES_WRAPPERS = function () { && new Int8Array(new ArrayBuffer(2), 1, undefined).length == 1; }; +function NCG_SUPPORT() { + var re = RegExp('(?b)'); + return re.exec('b').groups.a === 'b' && + 'b'.replace(re, '$c') === 'bc'; +} + function createIsRegExpLogicTest(name) { return function () { var regexp = /./; @@ -782,7 +788,7 @@ GLOBAL.tests = { 'es.reflect.to-string-tag': function () { return Reflect[Symbol.toStringTag]; }, - 'es.regexp.constructor': function () { + 'es.regexp.constructor': [NCG_SUPPORT, function () { var re1 = /a/g; var re2 = /a/g; re2[Symbol.match] = false; @@ -793,11 +799,11 @@ GLOBAL.tests = { && new RegExp('a', 'y') // just check that it doesn't throw && RegExp('.', 's').exec('\n') && RegExp[Symbol.species]; - }, + }], 'es.regexp.dot-all': function () { return RegExp('.', 's').dotAll; }, - 'es.regexp.exec': function () { + 'es.regexp.exec': [NCG_SUPPORT, function () { var re1 = /a/; var re2 = /b*/g; var reSticky = new RegExp('a', 'y'); @@ -812,7 +818,7 @@ GLOBAL.tests = { && (reSticky.lastIndex = 1, reSticky.exec('bac')[0] === 'a') && (reStickyAnchored.lastIndex = 2, reStickyAnchored.exec('cba') === null) && RegExp('.', 's').exec('\n'); - }, + }], 'es.regexp.flags': function () { return Object.getOwnPropertyDescriptor(RegExp.prototype, 'flags').get.call({ dotAll: true, sticky: true }) === 'sy'; }, @@ -893,7 +899,7 @@ GLOBAL.tests = { 'es.string.repeat': function () { return String.prototype.repeat; }, - 'es.string.replace': function () { + 'es.string.replace': [NCG_SUPPORT, function () { var O = {}; O[Symbol.replace] = function () { return 7; }; @@ -902,20 +908,12 @@ GLOBAL.tests = { re.exec = function () { execCalled = true; return null; }; re[Symbol.replace](''); - var re2 = /./; - re2.exec = function () { - var result = []; - result.groups = { a: '7' }; - return result; - }; - return ''.replace(O) == 7 && execCalled - && ''.replace(re2, '$') === '7' // eslint-disable-next-line regexp/prefer-escape-replacement-dollar-char -- required for testing && 'a'.replace(/./, '$0') === '$0' && /./[Symbol.replace]('a', '$0') === '$0'; - }, + }], 'es.string.replace-all': function () { return String.prototype.replaceAll; }, diff --git a/tests/tests/es.regexp.constructor.js b/tests/tests/es.regexp.constructor.js index 2b7fde551864..4caede090604 100644 --- a/tests/tests/es.regexp.constructor.js +++ b/tests/tests/es.regexp.constructor.js @@ -69,5 +69,14 @@ if (DESCRIPTORS) { assert.same(RegExp('(?b)', (typeof '').charAt(5)).exec('b').groups?.a, 'b', 'NCG #1'); // eslint-disable-next-line regexp/no-unused-capturing-group -- required for testing assert.same(RegExp('(b)', (typeof '').charAt(5)).exec('b').groups, undefined, 'NCG #2'); + assert.same('foo:abc,bar:def'.replace(RegExp('foo:(?\\w+),bar:(?\\w+)'), '$,$'), 'def,abc', 'replace #1'); + assert.same('foo:abc,bar:def'.replace(RegExp('foo:(?\\w+),bar:(?\\w+)'), (...args) => { + const { foo, bar } = args.pop(); + return `${ bar },${ foo }`; + }), 'def,abc', 'replace #2'); + // eslint-disable-next-line no-invalid-regexp -- required for testing + assert.throws(() => RegExp('(?<1a>b)'), SyntaxError, 'incorrect group name #1'); + // eslint-disable-next-line no-invalid-regexp -- required for testing + assert.throws(() => RegExp('(?b)'), SyntaxError, 'incorrect group name #2'); }); }