Skip to content

Commit

Permalink
Handle multiple named groups in wrapRegExp replace() (#15090)
Browse files Browse the repository at this point in the history
Previously, the [Symbol.replace] implementation in BabelRegExp assumed
that the groups object property values were only numbers. With the
duplicate named capturing groups plugin, they can be arrays of numbers
as well.

In the case of a duplicate named capturing group, the replacement
pattern $<name> can be replaced by the concatenation of the pattern
indices that have that name: e.g., $1$2.
  • Loading branch information
ptomato committed Oct 29, 2022
1 parent 082caa1 commit 19090d4
Show file tree
Hide file tree
Showing 3 changed files with 8 additions and 2 deletions.
2 changes: 1 addition & 1 deletion packages/babel-helpers/src/helpers-generated.ts
Expand Up @@ -59,6 +59,6 @@ export default Object.freeze({
),
wrapRegExp: helper(
"7.19.0",
'import setPrototypeOf from"setPrototypeOf";import inherits from"inherits";export default function _wrapRegExp(){_wrapRegExp=function(re,groups){return new BabelRegExp(re,void 0,groups)};var _super=RegExp.prototype,_groups=new WeakMap;function BabelRegExp(re,flags,groups){var _this=new RegExp(re,flags);return _groups.set(_this,groups||_groups.get(re)),setPrototypeOf(_this,BabelRegExp.prototype)}function buildGroups(result,re){var g=_groups.get(re);return Object.keys(g).reduce((function(groups,name){var i=g[name];if("number"==typeof i)groups[name]=result[i];else{for(var k=0;void 0===result[i[k]]&&k+1<i.length;)k++;groups[name]=result[i[k]]}return groups}),Object.create(null))}return inherits(BabelRegExp,RegExp),BabelRegExp.prototype.exec=function(str){var result=_super.exec.call(this,str);return result&&(result.groups=buildGroups(result,this)),result},BabelRegExp.prototype[Symbol.replace]=function(str,substitution){if("string"==typeof substitution){var groups=_groups.get(this);return _super[Symbol.replace].call(this,str,substitution.replace(/\\$<([^>]+)>/g,(function(_,name){return"$"+groups[name]})))}if("function"==typeof substitution){var _this=this;return _super[Symbol.replace].call(this,str,(function(){var args=arguments;return"object"!=typeof args[args.length-1]&&(args=[].slice.call(args)).push(buildGroups(args,_this)),substitution.apply(this,args)}))}return _super[Symbol.replace].call(this,str,substitution)},_wrapRegExp.apply(this,arguments)}',
'import setPrototypeOf from"setPrototypeOf";import inherits from"inherits";export default function _wrapRegExp(){_wrapRegExp=function(re,groups){return new BabelRegExp(re,void 0,groups)};var _super=RegExp.prototype,_groups=new WeakMap;function BabelRegExp(re,flags,groups){var _this=new RegExp(re,flags);return _groups.set(_this,groups||_groups.get(re)),setPrototypeOf(_this,BabelRegExp.prototype)}function buildGroups(result,re){var g=_groups.get(re);return Object.keys(g).reduce((function(groups,name){var i=g[name];if("number"==typeof i)groups[name]=result[i];else{for(var k=0;void 0===result[i[k]]&&k+1<i.length;)k++;groups[name]=result[i[k]]}return groups}),Object.create(null))}return inherits(BabelRegExp,RegExp),BabelRegExp.prototype.exec=function(str){var result=_super.exec.call(this,str);return result&&(result.groups=buildGroups(result,this)),result},BabelRegExp.prototype[Symbol.replace]=function(str,substitution){if("string"==typeof substitution){var groups=_groups.get(this);return _super[Symbol.replace].call(this,str,substitution.replace(/\\$<([^>]+)>/g,(function(_,name){var group=groups[name];return"$"+(Array.isArray(group)?group.join("$"):group)})))}if("function"==typeof substitution){var _this=this;return _super[Symbol.replace].call(this,str,(function(){var args=arguments;return"object"!=typeof args[args.length-1]&&(args=[].slice.call(args)).push(buildGroups(args,_this)),substitution.apply(this,args)}))}return _super[Symbol.replace].call(this,str,substitution)},_wrapRegExp.apply(this,arguments)}',
),
});
3 changes: 2 additions & 1 deletion packages/babel-helpers/src/helpers/wrapRegExp.js
Expand Up @@ -31,7 +31,8 @@ export default function _wrapRegExp() {
this,
str,
substitution.replace(/\$<([^>]+)>/g, function (_, name) {
return "$" + groups[name];
var group = groups[name];
return "$" + (Array.isArray(group) ? group.join("$") : group);
})
);
} else if (typeof substitution === "function") {
Expand Down
@@ -0,0 +1,5 @@
let regexp = /(?<named>a)|(?<named>b)|c/;

expect("a".replace(regexp, "[$<named>]")).toEqual("[a]");
expect("b".replace(regexp, "[$<named>]")).toEqual("[b]");
expect("c".replace(regexp, "[$<named>]")).toEqual("[]");

0 comments on commit 19090d4

Please sign in to comment.