Skip to content

Commit

Permalink
Support indices.groups when compiling named groups in regexps (#15092)
Browse files Browse the repository at this point in the history
Add support for indices.groups

If a RegExp has the /d flag (hasIndices), match objects should have an
extra property .indices with an array of the character indices that each
subgroup matched. The indices array itself has a property .groups giving
the matched character indices (or undefined) for each named capturing
group.

This doesn't do anything to enable support for the /d flag, the
hasIndices property, or the returned indices object, if the environment
does not support it, but it will populate .indices.groups in _wrapRegExp
if .indices is present, so that the
transform-named-capturing-groups-regex and
proposal-duplicate-named-capturing-groups-regex plugins can take
advantage of that support if it exists.
  • Loading branch information
ptomato committed Oct 31, 2022
1 parent 283720d commit d6fbba5
Show file tree
Hide file tree
Showing 6 changed files with 32 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){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)}',
'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);if(result){result.groups=buildGroups(result,this);var indices=result.indices;indices&&(indices.groups=buildGroups(indices,this))}return 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)}',
),
});
6 changes: 5 additions & 1 deletion packages/babel-helpers/src/helpers/wrapRegExp.js
Expand Up @@ -21,7 +21,11 @@ export default function _wrapRegExp() {

BabelRegExp.prototype.exec = function (str) {
var result = _super.exec.call(this, str);
if (result) result.groups = buildGroups(result, this);
if (result) {
result.groups = buildGroups(result, this);
var indices = result.indices;
if (indices) indices.groups = buildGroups(indices, this);
}
return result;
};
BabelRegExp.prototype[Symbol.replace] = function (str, substitution) {
Expand Down
@@ -0,0 +1,5 @@
let regexp = /(?<named>a)|(?<named>b)|c/d;

expect("a".match(regexp).indices.groups).toEqual({ named: [0, 1] });
expect("b".match(regexp).indices.groups).toEqual({ named: [0, 1] });
expect("c".match(regexp).indices.groups).toEqual({ named: undefined });
@@ -0,0 +1,3 @@
{
"minNodeVersion": "16.0.0"
}
@@ -0,0 +1,15 @@
var re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/d;

var result = re.exec("2017-12-23");

expect(result.indices.groups).toEqual({
year: [0, 4],
month: [5, 7],
day: [8, 10],
});

expect(result.indices.groups).toEqual({
year: result.indices[1],
month: result.indices[2],
day: result.indices[3],
});
@@ -0,0 +1,3 @@
{
"minNodeVersion": "16.0.0"
}

0 comments on commit d6fbba5

Please sign in to comment.