From 9e602e8010741a721e94eae97fc91e3fbe6576c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Wed, 27 Jul 2022 17:24:07 +0200 Subject: [PATCH 1/5] Add support for the duplicate named capturing groups proposal --- Makefile | 19 +++--- .../src/features.ts | 1 + .../src/index.ts | 65 +++++++++++++++++-- .../src/util.ts | 3 +- .../conflict-false-true}/input.mjs | 0 .../runtime/conflict-false-true/options.json | 7 ++ .../runtime/conflict-true-false/input.mjs | 1 + .../runtime/conflict-true-false/options.json | 7 ++ .../input.mjs | 1 + .../options.json | 0 .../output.mjs | 0 .../babel-helpers/src/helpers-generated.ts | 2 +- .../babel-helpers/src/helpers/wrapRegExp.js | 11 +++- .../.npmignore | 3 + .../README.md | 19 ++++++ .../package.json | 52 +++++++++++++++ .../src/index.ts | 20 ++++++ .../test/fixtures/runtime/basic/input.js | 1 + .../test/fixtures/runtime/basic/output.js | 5 ++ .../test/fixtures/runtime/exec.js | 5 ++ .../test/fixtures/runtime/options.json | 3 + .../test/fixtures/syntax/basic/input.js | 1 + .../test/fixtures/syntax/basic/output.js | 1 + .../test/fixtures/syntax/options.json | 5 ++ .../unique-name-not-transformed/input.js | 1 + .../unique-name-not-transformed/output.js | 1 + .../input.js | 1 + .../options.json | 6 ++ .../output.js | 1 + .../test/fixtures/wrapper/basic/input.js | 1 + .../test/fixtures/wrapper/basic/output.js | 3 + .../looks-like-a-group-unicode/input.js | 1 + .../looks-like-a-group-unicode/options.json | 6 ++ .../looks-like-a-group-unicode/output.js | 1 + .../wrapper/looks-like-a-group/input.js | 1 + .../wrapper/looks-like-a-group/output.js | 1 + .../wrapper/only-when-named-groups/input.js | 1 + .../wrapper/only-when-named-groups/output.js | 1 + .../test/fixtures/wrapper/options.json | 3 + .../skips-anonymous-capturing-groups/input.js | 1 + .../output.js | 3 + .../fixtures/wrapper/test-method/input.js | 1 + .../fixtures/wrapper/test-method/output.js | 1 + .../test/index.js | 3 + .../test/package.json | 1 + .../src/index.ts | 4 +- yarn.lock | 28 ++++++-- 47 files changed, 275 insertions(+), 28 deletions(-) rename packages/babel-helper-create-regexp-features-plugin/test/fixtures/{plugin-transform-named-capturing-groups-regex/runtime-false-not-overwritten => runtime/conflict-false-true}/input.mjs (100%) create mode 100644 packages/babel-helper-create-regexp-features-plugin/test/fixtures/runtime/conflict-false-true/options.json create mode 100644 packages/babel-helper-create-regexp-features-plugin/test/fixtures/runtime/conflict-true-false/input.mjs create mode 100644 packages/babel-helper-create-regexp-features-plugin/test/fixtures/runtime/conflict-true-false/options.json create mode 100644 packages/babel-helper-create-regexp-features-plugin/test/fixtures/runtime/plugin-transform-named-capturing-groups-regex-runtime-false-not-overwritten/input.mjs rename packages/babel-helper-create-regexp-features-plugin/test/fixtures/{plugin-transform-named-capturing-groups-regex/runtime-false-not-overwritten => runtime/plugin-transform-named-capturing-groups-regex-runtime-false-not-overwritten}/options.json (100%) rename packages/babel-helper-create-regexp-features-plugin/test/fixtures/{plugin-transform-named-capturing-groups-regex/runtime-false-not-overwritten => runtime/plugin-transform-named-capturing-groups-regex-runtime-false-not-overwritten}/output.mjs (100%) create mode 100644 packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/.npmignore create mode 100644 packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/README.md create mode 100644 packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/package.json create mode 100644 packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/src/index.ts create mode 100644 packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/runtime/basic/input.js create mode 100644 packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/runtime/basic/output.js create mode 100644 packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/runtime/exec.js create mode 100644 packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/runtime/options.json create mode 100644 packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/syntax/basic/input.js create mode 100644 packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/syntax/basic/output.js create mode 100644 packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/syntax/options.json create mode 100644 packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/syntax/unique-name-not-transformed/input.js create mode 100644 packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/syntax/unique-name-not-transformed/output.js create mode 100644 packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/syntax/unique-name-with-named-groups-plugin/input.js create mode 100644 packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/syntax/unique-name-with-named-groups-plugin/options.json create mode 100644 packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/syntax/unique-name-with-named-groups-plugin/output.js create mode 100644 packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/basic/input.js create mode 100644 packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/basic/output.js create mode 100644 packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/looks-like-a-group-unicode/input.js create mode 100644 packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/looks-like-a-group-unicode/options.json create mode 100644 packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/looks-like-a-group-unicode/output.js create mode 100644 packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/looks-like-a-group/input.js create mode 100644 packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/looks-like-a-group/output.js create mode 100644 packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/only-when-named-groups/input.js create mode 100644 packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/only-when-named-groups/output.js create mode 100644 packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/options.json create mode 100644 packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/skips-anonymous-capturing-groups/input.js create mode 100644 packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/skips-anonymous-capturing-groups/output.js create mode 100644 packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/test-method/input.js create mode 100644 packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/test-method/output.js create mode 100644 packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/index.js create mode 100644 packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/package.json diff --git a/Makefile b/Makefile index 1d710d85053e..ee2743fa1141 100644 --- a/Makefile +++ b/Makefile @@ -185,15 +185,16 @@ test-test262-update-allowlist: new-version-checklist: - # @echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" - # @echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" - # @echo "!!!!!! !!!!!!" - # @echo "!!!!!! Write any message that should !!!!!!" - # @echo "!!!!!! block the release here !!!!!!" - # @echo "!!!!!! !!!!!!" - # @echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" - # @echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" - # @exit 1 + @echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + @echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + @echo "!!!!!! !!!!!!" + @echo "!!!!!! Update minVersion in the wrapRegExp helper, !!!!!!" + @echo "!!!!!! and the requried core version in the duplicate !!!!!!" + @echo "!!!!!! named groups plugin. !!!!!!" + @echo "!!!!!! !!!!!!" + @echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + @echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + @exit 1 new-version: $(MAKE) new-version-checklist diff --git a/packages/babel-helper-create-regexp-features-plugin/src/features.ts b/packages/babel-helper-create-regexp-features-plugin/src/features.ts index abe72d0b4729..ed9b6f4ed60a 100644 --- a/packages/babel-helper-create-regexp-features-plugin/src/features.ts +++ b/packages/babel-helper-create-regexp-features-plugin/src/features.ts @@ -5,6 +5,7 @@ export const FEATURES = Object.freeze({ namedCaptureGroups: 1 << 3, unicodeSetsFlag_syntax: 1 << 4, unicodeSetsFlag: 1 << 5, + duplicateNamedCaptureGroups: 1 << 6, }); // We can't use a symbol because this needs to always be the same, even if diff --git a/packages/babel-helper-create-regexp-features-plugin/src/index.ts b/packages/babel-helper-create-regexp-features-plugin/src/index.ts index 060a3638f94d..d1be9056db04 100644 --- a/packages/babel-helper-create-regexp-features-plugin/src/index.ts +++ b/packages/babel-helper-create-regexp-features-plugin/src/index.ts @@ -1,5 +1,11 @@ import rewritePattern from "regexpu-core"; -import { featuresKey, FEATURES, enableFeature, runtimeKey } from "./features"; +import { + featuresKey, + FEATURES, + enableFeature, + runtimeKey, + hasFeature, +} from "./features"; import { generateRegexpuOptions, canSkipRegexpu, transformFlags } from "./util"; import type { NodePath } from "@babel/traverse"; @@ -44,7 +50,7 @@ export function createRegExpFeaturePlugin({ const features = file.get(featuresKey) ?? 0; let newFeatures = enableFeature(features, FEATURES[feature]); - const { useUnicodeFlag, runtime = true } = options; + const { useUnicodeFlag, runtime } = options; if (useUnicodeFlag === false) { newFeatures = enableFeature(newFeatures, FEATURES.unicodeFlag); } @@ -52,8 +58,29 @@ export function createRegExpFeaturePlugin({ file.set(featuresKey, newFeatures); } - if (!runtime) { - file.set(runtimeKey, false); + if (runtime !== undefined) { + if ( + file.has(runtimeKey) && + file.get(runtimeKey) !== runtime && + // TODO(Babel 8): Remove this check. It's necessary because in Babel 7 + // we allow multiple copies of transform-named-capturing-groups-regex + // with conflicting 'runtime' options. + hasFeature(newFeatures, FEATURES.duplicateNamedCaptureGroups) + ) { + throw new Error( + `The 'runtime' option must be the same for ` + + `'@babel/plugin-transform-named-capturing-groups-regex' and ` + + `'@babel/plugin-proposal-duplicate-named-capturing-groups-regex'.`, + ); + } + // TODO(Babel 8): Remove this check and always set it. + // It's necessary because in Babel 7 we allow multiple copies of + // transform-named-capturing-groups-regex with conflicting 'runtime' options. + if (feature === "namedCaptureGroups") { + if (!runtime || !file.has(runtimeKey)) file.set(runtimeKey, runtime); + } else { + file.set(runtimeKey, runtime); + } } if (!file.has(versionKey) || file.get(versionKey) < version) { @@ -71,14 +98,38 @@ export function createRegExpFeaturePlugin({ const regexpuOptions = generateRegexpuOptions(features); if (canSkipRegexpu(node, regexpuOptions)) return; - const namedCaptureGroups: Record = {}; + const namedCaptureGroups: Record = { + __proto__: null, + }; + let hasDuplicateNamedCaptureGroups = false; if (regexpuOptions.namedGroups === "transform") { regexpuOptions.onNamedGroup = (name, index) => { - namedCaptureGroups[name] = index; + const prev = namedCaptureGroups[name]; + if (typeof prev === "number") { + hasDuplicateNamedCaptureGroups = true; + namedCaptureGroups[name] = [prev, index]; + } else if (Array.isArray(prev)) { + prev.push(index); + } else { + namedCaptureGroups[name] = index; + } }; } - node.pattern = rewritePattern(node.pattern, node.flags, regexpuOptions); + let pattern = rewritePattern(node.pattern, node.flags, regexpuOptions); + if ( + !hasDuplicateNamedCaptureGroups && + hasFeature(features, FEATURES.duplicateNamedCaptureGroups) && + !hasFeature(features, FEATURES.namedCaptureGroups) + ) { + // If we only transformed named groups because we want to transform duplicates + // but there are no duplicates, re-transform the regexp without transforming + // named groups. + regexpuOptions.namedGroups = false; + if (canSkipRegexpu(node, regexpuOptions)) return; + pattern = rewritePattern(node.pattern, node.flags, regexpuOptions); + } + node.pattern = pattern; if ( regexpuOptions.namedGroups === "transform" && diff --git a/packages/babel-helper-create-regexp-features-plugin/src/util.ts b/packages/babel-helper-create-regexp-features-plugin/src/util.ts index b4c7e5251dfc..0648767f53dc 100644 --- a/packages/babel-helper-create-regexp-features-plugin/src/util.ts +++ b/packages/babel-helper-create-regexp-features-plugin/src/util.ts @@ -20,7 +20,8 @@ export function generateRegexpuOptions(toTransform: number): RegexpuOptions { feat("unicodeSetsFlag_syntax", "parse"), dotAllFlag: feat("dotAllFlag"), unicodePropertyEscapes: feat("unicodePropertyEscape"), - namedGroups: feat("namedCaptureGroups"), + namedGroups: + feat("namedCaptureGroups") || feat("duplicateNamedCaptureGroups"), onNamedGroup: () => {}, }; } diff --git a/packages/babel-helper-create-regexp-features-plugin/test/fixtures/plugin-transform-named-capturing-groups-regex/runtime-false-not-overwritten/input.mjs b/packages/babel-helper-create-regexp-features-plugin/test/fixtures/runtime/conflict-false-true/input.mjs similarity index 100% rename from packages/babel-helper-create-regexp-features-plugin/test/fixtures/plugin-transform-named-capturing-groups-regex/runtime-false-not-overwritten/input.mjs rename to packages/babel-helper-create-regexp-features-plugin/test/fixtures/runtime/conflict-false-true/input.mjs diff --git a/packages/babel-helper-create-regexp-features-plugin/test/fixtures/runtime/conflict-false-true/options.json b/packages/babel-helper-create-regexp-features-plugin/test/fixtures/runtime/conflict-false-true/options.json new file mode 100644 index 000000000000..97779c7e163d --- /dev/null +++ b/packages/babel-helper-create-regexp-features-plugin/test/fixtures/runtime/conflict-false-true/options.json @@ -0,0 +1,7 @@ +{ + "plugins": [ + ["transform-named-capturing-groups-regex", { "runtime": true }], + ["proposal-duplicate-named-capturing-groups-regex", { "runtime": false }] + ], + "throws": "The 'runtime' option must be the same for '@babel/plugin-transform-named-capturing-groups-regex' and '@babel/plugin-proposal-duplicate-named-capturing-groups-regex'." +} diff --git a/packages/babel-helper-create-regexp-features-plugin/test/fixtures/runtime/conflict-true-false/input.mjs b/packages/babel-helper-create-regexp-features-plugin/test/fixtures/runtime/conflict-true-false/input.mjs new file mode 100644 index 000000000000..3d7f5b1517b5 --- /dev/null +++ b/packages/babel-helper-create-regexp-features-plugin/test/fixtures/runtime/conflict-true-false/input.mjs @@ -0,0 +1 @@ +/(?\d{4})/ diff --git a/packages/babel-helper-create-regexp-features-plugin/test/fixtures/runtime/conflict-true-false/options.json b/packages/babel-helper-create-regexp-features-plugin/test/fixtures/runtime/conflict-true-false/options.json new file mode 100644 index 000000000000..d430ab5acc70 --- /dev/null +++ b/packages/babel-helper-create-regexp-features-plugin/test/fixtures/runtime/conflict-true-false/options.json @@ -0,0 +1,7 @@ +{ + "plugins": [ + ["transform-named-capturing-groups-regex", { "runtime": false }], + ["proposal-duplicate-named-capturing-groups-regex", { "runtime": true }] + ], + "throws": "The 'runtime' option must be the same for '@babel/plugin-transform-named-capturing-groups-regex' and '@babel/plugin-proposal-duplicate-named-capturing-groups-regex'." +} diff --git a/packages/babel-helper-create-regexp-features-plugin/test/fixtures/runtime/plugin-transform-named-capturing-groups-regex-runtime-false-not-overwritten/input.mjs b/packages/babel-helper-create-regexp-features-plugin/test/fixtures/runtime/plugin-transform-named-capturing-groups-regex-runtime-false-not-overwritten/input.mjs new file mode 100644 index 000000000000..3d7f5b1517b5 --- /dev/null +++ b/packages/babel-helper-create-regexp-features-plugin/test/fixtures/runtime/plugin-transform-named-capturing-groups-regex-runtime-false-not-overwritten/input.mjs @@ -0,0 +1 @@ +/(?\d{4})/ diff --git a/packages/babel-helper-create-regexp-features-plugin/test/fixtures/plugin-transform-named-capturing-groups-regex/runtime-false-not-overwritten/options.json b/packages/babel-helper-create-regexp-features-plugin/test/fixtures/runtime/plugin-transform-named-capturing-groups-regex-runtime-false-not-overwritten/options.json similarity index 100% rename from packages/babel-helper-create-regexp-features-plugin/test/fixtures/plugin-transform-named-capturing-groups-regex/runtime-false-not-overwritten/options.json rename to packages/babel-helper-create-regexp-features-plugin/test/fixtures/runtime/plugin-transform-named-capturing-groups-regex-runtime-false-not-overwritten/options.json diff --git a/packages/babel-helper-create-regexp-features-plugin/test/fixtures/plugin-transform-named-capturing-groups-regex/runtime-false-not-overwritten/output.mjs b/packages/babel-helper-create-regexp-features-plugin/test/fixtures/runtime/plugin-transform-named-capturing-groups-regex-runtime-false-not-overwritten/output.mjs similarity index 100% rename from packages/babel-helper-create-regexp-features-plugin/test/fixtures/plugin-transform-named-capturing-groups-regex/runtime-false-not-overwritten/output.mjs rename to packages/babel-helper-create-regexp-features-plugin/test/fixtures/runtime/plugin-transform-named-capturing-groups-regex-runtime-false-not-overwritten/output.mjs diff --git a/packages/babel-helpers/src/helpers-generated.ts b/packages/babel-helpers/src/helpers-generated.ts index d40d731026b9..07c11f7a6e51 100644 --- a/packages/babel-helpers/src/helpers-generated.ts +++ b/packages/babel-helpers/src/helpers-generated.ts @@ -39,6 +39,6 @@ export default Object.freeze({ ), wrapRegExp: helper( "7.2.6", - '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){return groups[name]=result[g[name]],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{let k=0;for(;void 0===result[i[k]]&&k+1]+)>/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)}', ), }); diff --git a/packages/babel-helpers/src/helpers/wrapRegExp.js b/packages/babel-helpers/src/helpers/wrapRegExp.js index d8e110af2675..f852d9e6cf36 100644 --- a/packages/babel-helpers/src/helpers/wrapRegExp.js +++ b/packages/babel-helpers/src/helpers/wrapRegExp.js @@ -56,7 +56,16 @@ export default function _wrapRegExp() { var g = _groups.get(re); return Object.keys(g).reduce(function (groups, name) { - groups[name] = result[g[name]]; + var i = g[name]; + if (typeof i === "number") groups[name] = result[i]; + else { + // i is an array of indexes + let k = 0; + // if no group matched, we stop at k = i.length - 1 and then + // we store result[i[i.length - 1]] which is undefined. + while (result[i[k]] === undefined && k + 1 < i.length) k++; + groups[name] = result[i[k]]; + } return groups; }, Object.create(null)); } diff --git a/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/.npmignore b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/.npmignore new file mode 100644 index 000000000000..f9806945836e --- /dev/null +++ b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/.npmignore @@ -0,0 +1,3 @@ +src +test +*.log diff --git a/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/README.md b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/README.md new file mode 100644 index 000000000000..58fec2daa0d2 --- /dev/null +++ b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/README.md @@ -0,0 +1,19 @@ +# @babel/plugin-proposal-duplicate-named-capturing-groups-regex + +> Compile regular expressions using duplicate named groups to index-based groups. + +See our website [@babel/plugin-proposal-duplicate-named-capturing-groups-regex](https://babeljs.io/docs/en/babel-plugin-proposal-duplicate-named-capturing-groups-regex) for more information. + +## Install + +Using npm: + +```sh +npm install --save-dev @babel/plugin-proposal-duplicate-named-capturing-groups-regex +``` + +or using yarn: + +```sh +yarn add @babel/plugin-proposal-duplicate-named-capturing-groups-regex --dev +``` diff --git a/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/package.json b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/package.json new file mode 100644 index 000000000000..92c1c9fcca92 --- /dev/null +++ b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/package.json @@ -0,0 +1,52 @@ +{ + "name": "@babel/plugin-proposal-duplicate-named-capturing-groups-regex", + "version": "7.18.6", + "description": "Compile regular expressions using duplicate named groups to index-based groups.", + "homepage": "https://babel.dev/docs/en/next/babel-plugin-proposal-duplicate-named-capturing-groups-regex", + "license": "MIT", + "publishConfig": { + "access": "public" + }, + "main": "./lib/index.js", + "keywords": [ + "babel-plugin", + "regex", + "regexp", + "regular expressions" + ], + "repository": { + "type": "git", + "url": "https://github.com/babel/babel.git", + "directory": "packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex" + }, + "bugs": "https://github.com/babel/babel/issues", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "workspace:^", + "@babel/helper-plugin-utils": "workspace:^" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + }, + "devDependencies": { + "@babel/core": "workspace:^", + "@babel/helper-plugin-test-runner": "workspace:^", + "core-js": "^3.22.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "author": "The Babel Team (https://babel.dev/team)", + "conditions": { + "USE_ESM": [ + { + "type": "module" + }, + null + ] + }, + "exports": { + ".": "./lib/index.js", + "./package.json": "./package.json" + }, + "type": "commonjs" +} diff --git a/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/src/index.ts b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/src/index.ts new file mode 100644 index 000000000000..76d83980f495 --- /dev/null +++ b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/src/index.ts @@ -0,0 +1,20 @@ +/* eslint-disable @babel/development/plugin-name */ +import { createRegExpFeaturePlugin } from "@babel/helper-create-regexp-features-plugin"; +import { declare } from "@babel/helper-plugin-utils"; + +export interface Options { + runtime?: boolean; +} + +export default declare((api, options: Options) => { + const { runtime } = options; + if (runtime !== undefined && typeof runtime !== "boolean") { + throw new Error("The 'runtime' option must be boolean"); + } + + return createRegExpFeaturePlugin({ + name: "proposal-duplicate-named-capturing-groups-regex", + feature: "duplicateNamedCaptureGroups", + options: { runtime }, + }); +}); diff --git a/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/runtime/basic/input.js b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/runtime/basic/input.js new file mode 100644 index 000000000000..b6b1233b66a9 --- /dev/null +++ b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/runtime/basic/input.js @@ -0,0 +1 @@ +/(?:(?\d\d\d\d)|(?\d\d))-(?\d\d)/; diff --git a/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/runtime/basic/output.js b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/runtime/basic/output.js new file mode 100644 index 000000000000..f53db765b4ae --- /dev/null +++ b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/runtime/basic/output.js @@ -0,0 +1,5 @@ +/*#__PURE__*/ +babelHelpers.wrapRegExp(/(?:(\d\d\d\d)|(\d\d))\x2D(\d\d)/, { + year: [1, 2], + month: 3 +}); diff --git a/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/runtime/exec.js b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/runtime/exec.js new file mode 100644 index 000000000000..1347ef53e9f1 --- /dev/null +++ b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/runtime/exec.js @@ -0,0 +1,5 @@ +let regexp = /(?a)|(?b)|c/; + +expect("a".match(regexp).groups).toEqual({ named: "a" }); +expect("b".match(regexp).groups).toEqual({ named: "b" }); +expect("c".match(regexp).groups).toEqual({ named: undefined }); diff --git a/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/runtime/options.json b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/runtime/options.json new file mode 100644 index 000000000000..cacf4d1974df --- /dev/null +++ b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/runtime/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["proposal-duplicate-named-capturing-groups-regex"] +} diff --git a/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/syntax/basic/input.js b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/syntax/basic/input.js new file mode 100644 index 000000000000..873e6d6b0572 --- /dev/null +++ b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/syntax/basic/input.js @@ -0,0 +1 @@ +/(?:(?\d\d\d\d)|(?\d\d)) is \k/; diff --git a/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/syntax/basic/output.js b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/syntax/basic/output.js new file mode 100644 index 000000000000..7351dd79a1e4 --- /dev/null +++ b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/syntax/basic/output.js @@ -0,0 +1 @@ +/(?:(\d\d\d\d)|(\d\d)) is \1\2/; diff --git a/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/syntax/options.json b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/syntax/options.json new file mode 100644 index 000000000000..d254b9b39da5 --- /dev/null +++ b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/syntax/options.json @@ -0,0 +1,5 @@ +{ + "plugins": [ + ["proposal-duplicate-named-capturing-groups-regex", { "runtime": false }] + ] +} diff --git a/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/syntax/unique-name-not-transformed/input.js b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/syntax/unique-name-not-transformed/input.js new file mode 100644 index 000000000000..1d1628ac0978 --- /dev/null +++ b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/syntax/unique-name-not-transformed/input.js @@ -0,0 +1 @@ +/(?\d\d\d\d) is \k/; diff --git a/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/syntax/unique-name-not-transformed/output.js b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/syntax/unique-name-not-transformed/output.js new file mode 100644 index 000000000000..1d1628ac0978 --- /dev/null +++ b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/syntax/unique-name-not-transformed/output.js @@ -0,0 +1 @@ +/(?\d\d\d\d) is \k/; diff --git a/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/syntax/unique-name-with-named-groups-plugin/input.js b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/syntax/unique-name-with-named-groups-plugin/input.js new file mode 100644 index 000000000000..1d1628ac0978 --- /dev/null +++ b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/syntax/unique-name-with-named-groups-plugin/input.js @@ -0,0 +1 @@ +/(?\d\d\d\d) is \k/; diff --git a/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/syntax/unique-name-with-named-groups-plugin/options.json b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/syntax/unique-name-with-named-groups-plugin/options.json new file mode 100644 index 000000000000..247156232ea5 --- /dev/null +++ b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/syntax/unique-name-with-named-groups-plugin/options.json @@ -0,0 +1,6 @@ +{ + "plugins": [ + ["proposal-duplicate-named-capturing-groups-regex", { "runtime": false }], + ["transform-named-capturing-groups-regex", { "runtime": false }] + ] +} diff --git a/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/syntax/unique-name-with-named-groups-plugin/output.js b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/syntax/unique-name-with-named-groups-plugin/output.js new file mode 100644 index 000000000000..cac0bdaaf258 --- /dev/null +++ b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/syntax/unique-name-with-named-groups-plugin/output.js @@ -0,0 +1 @@ +/(\d\d\d\d) is \1/; diff --git a/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/basic/input.js b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/basic/input.js new file mode 100644 index 000000000000..2761445e091b --- /dev/null +++ b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/basic/input.js @@ -0,0 +1 @@ +"foo".match(/(?.)\k/); \ No newline at end of file diff --git a/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/basic/output.js b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/basic/output.js new file mode 100644 index 000000000000..779aac3d8537 --- /dev/null +++ b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/basic/output.js @@ -0,0 +1,3 @@ +"foo".match( /*#__PURE__*/babelHelpers.wrapRegExp(/(.)\1/, { + double: 1 +})); diff --git a/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/looks-like-a-group-unicode/input.js b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/looks-like-a-group-unicode/input.js new file mode 100644 index 000000000000..00a7c78b9344 --- /dev/null +++ b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/looks-like-a-group-unicode/input.js @@ -0,0 +1 @@ +/no-groups-\(?looks\)\u{10000}/u; diff --git a/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/looks-like-a-group-unicode/options.json b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/looks-like-a-group-unicode/options.json new file mode 100644 index 000000000000..148c4e8cb79c --- /dev/null +++ b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/looks-like-a-group-unicode/options.json @@ -0,0 +1,6 @@ +{ + "plugins": [ + "transform-named-capturing-groups-regex", + "transform-unicode-regex" + ] +} diff --git a/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/looks-like-a-group-unicode/output.js b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/looks-like-a-group-unicode/output.js new file mode 100644 index 000000000000..af299f8fceaf --- /dev/null +++ b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/looks-like-a-group-unicode/output.js @@ -0,0 +1 @@ +/no\x2Dgroups\x2D\(?looks\)(?:\uD800\uDC00)/; diff --git a/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/looks-like-a-group/input.js b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/looks-like-a-group/input.js new file mode 100644 index 000000000000..4c55ef0dbe17 --- /dev/null +++ b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/looks-like-a-group/input.js @@ -0,0 +1 @@ +/no-groups-\(?looks\)/; diff --git a/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/looks-like-a-group/output.js b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/looks-like-a-group/output.js new file mode 100644 index 000000000000..6fe7c2ef533c --- /dev/null +++ b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/looks-like-a-group/output.js @@ -0,0 +1 @@ +/no\x2Dgroups\x2D\(?looks\)/; diff --git a/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/only-when-named-groups/input.js b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/only-when-named-groups/input.js new file mode 100644 index 000000000000..581032632ae1 --- /dev/null +++ b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/only-when-named-groups/input.js @@ -0,0 +1 @@ +"foo".match(/(.)\1/); \ No newline at end of file diff --git a/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/only-when-named-groups/output.js b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/only-when-named-groups/output.js new file mode 100644 index 000000000000..c545e42ac5ca --- /dev/null +++ b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/only-when-named-groups/output.js @@ -0,0 +1 @@ +"foo".match(/(.)\1/); diff --git a/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/options.json b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/options.json new file mode 100644 index 000000000000..8b8fe93e5deb --- /dev/null +++ b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["transform-named-capturing-groups-regex"] +} diff --git a/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/skips-anonymous-capturing-groups/input.js b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/skips-anonymous-capturing-groups/input.js new file mode 100644 index 000000000000..86639f6f7e17 --- /dev/null +++ b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/skips-anonymous-capturing-groups/input.js @@ -0,0 +1 @@ +"abba".match(/(.)(?.)\k\1/); \ No newline at end of file diff --git a/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/skips-anonymous-capturing-groups/output.js b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/skips-anonymous-capturing-groups/output.js new file mode 100644 index 000000000000..16f5e24236b2 --- /dev/null +++ b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/skips-anonymous-capturing-groups/output.js @@ -0,0 +1,3 @@ +"abba".match( /*#__PURE__*/babelHelpers.wrapRegExp(/(.)(.)\2\1/, { + n: 2 +})); diff --git a/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/test-method/input.js b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/test-method/input.js new file mode 100644 index 000000000000..3e26e4ee498a --- /dev/null +++ b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/test-method/input.js @@ -0,0 +1 @@ +/^(?.)\k$/.test("aa"); \ No newline at end of file diff --git a/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/test-method/output.js b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/test-method/output.js new file mode 100644 index 000000000000..808fc64e4f90 --- /dev/null +++ b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/fixtures/wrapper/test-method/output.js @@ -0,0 +1 @@ +/^(.)\1$/.test("aa"); diff --git a/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/index.js b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/index.js new file mode 100644 index 000000000000..21a55ce6b5e7 --- /dev/null +++ b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/index.js @@ -0,0 +1,3 @@ +import runner from "@babel/helper-plugin-test-runner"; + +runner(import.meta.url); diff --git a/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/package.json b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/package.json new file mode 100644 index 000000000000..5ffd9800b97c --- /dev/null +++ b/packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/test/package.json @@ -0,0 +1 @@ +{ "type": "module" } diff --git a/packages/babel-plugin-transform-named-capturing-groups-regex/src/index.ts b/packages/babel-plugin-transform-named-capturing-groups-regex/src/index.ts index 0cd52bba1b09..f81e9867cada 100644 --- a/packages/babel-plugin-transform-named-capturing-groups-regex/src/index.ts +++ b/packages/babel-plugin-transform-named-capturing-groups-regex/src/index.ts @@ -7,8 +7,8 @@ export interface Options { } export default declare((api, options: Options) => { - const { runtime = true } = options; - if (typeof runtime !== "boolean") { + const { runtime } = options; + if (runtime !== undefined && typeof runtime !== "boolean") { throw new Error("The 'runtime' option must be boolean"); } diff --git a/yarn.lock b/yarn.lock index 1b59b1781b6d..7ffd884ccfb2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -317,7 +317,7 @@ __metadata: gensync: ^1.0.0-beta.2 json5: ^2.2.1 semver: ^6.3.0 - checksum: c7ee5b2c10bc5b0325e31fb5da4cb4bc03f9d5f5c00ec3481a018917bcc6b7b040de0690c606a424f57e5fc26d218d64e7718d0e5d7d8614d39c8cd898fab9b3 + checksum: bcc057bf6edbc4299bc759a292686d48e76d18617adb2327b38667a4972bb2ab1527c23b51168b37183d2fdb4218ac1f18319466d2c30837d469e9136dfd0dab languageName: node linkType: hard @@ -452,7 +452,7 @@ __metadata: "@babel/types": ^7.18.13 "@jridgewell/gen-mapping": ^0.3.2 jsesc: ^2.5.1 - checksum: 27f5e7eb774e4d76ee75dc96e3e1bd26cc0ee7cea13a8f7342b716319c0a4d4e26fc49aa8f19316f7c99383da55eeb2a866c6e034e9deacad58a9de9ed6004fb + checksum: b98ef678ad07bc3af76a041517ce49cc9a5ed0b943e4359aa86af3320a0b0525f9d902cbf1969b37d0bf104bcd89af31c2f35408b8dabff038543d281b416733 languageName: node linkType: hard @@ -570,7 +570,7 @@ __metadata: "@babel/helper-split-export-declaration": ^7.18.6 peerDependencies: "@babel/core": ^7.0.0 - checksum: 3d2da92a54b885b211a747a8c553bb0190895d140cd1daab5d9945b2b271817d9d288a512364085e9fad19bd503921cd85fcc12f98df67b39b27f5655eb9d058 + checksum: 000fb88ef4cc674a08d0b4f7b76db52e3f72fb0f0128d4881c140f640da2a8819601f1646e9956f7b6359d2d0b4ef155821c63f8f352c761ea82fff8e9ff7dc9 languageName: node linkType: hard @@ -1098,7 +1098,7 @@ __metadata: resolution: "@babel/parser@npm:7.18.13" bin: parser: ./bin/babel-parser.js - checksum: 8b41c35607668495d67d9a7c5f61768aaab26acf887efdadc2781aed54046981480ef40aeda0b84d61aed02cf0c4ff4b028d5f83ab85e17e2ddff318f9243b8b + checksum: e4d14756503a0f42936b7b1fa1bf8ece6208e56cd9b0294b51bb2ad37796dac6cc8cc912d4fcbc7cc82d7ac0aed4febb1dde0197caacca160e7ae153e93ffe69 languageName: node linkType: hard @@ -1359,6 +1359,20 @@ __metadata: languageName: unknown linkType: soft +"@babel/plugin-proposal-duplicate-named-capturing-groups-regex@workspace:packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex": + version: 0.0.0-use.local + resolution: "@babel/plugin-proposal-duplicate-named-capturing-groups-regex@workspace:packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex" + dependencies: + "@babel/core": "workspace:^" + "@babel/helper-create-regexp-features-plugin": "workspace:^" + "@babel/helper-plugin-test-runner": "workspace:^" + "@babel/helper-plugin-utils": "workspace:^" + core-js: ^3.22.1 + peerDependencies: + "@babel/core": ^7.0.0 + languageName: unknown + linkType: soft + "@babel/plugin-proposal-dynamic-import@npm:^7.18.6": version: 7.18.6 resolution: "@babel/plugin-proposal-dynamic-import@npm:7.18.6" @@ -2359,7 +2373,7 @@ __metadata: "@babel/helper-plugin-utils": ^7.18.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 83e44ec93a4cfbf69376db8836d00ec803820081bf0f8b6cea73a9b3cd320b8285768d5b385744af4a27edda4b6502245c52d3ed026ea61356faf57bfe78effb + checksum: a1e49ee0279234d61721b4099b6ddd37b528bdaa4fa4186e41f8408bfd6b54f61af9148ffd0725346c88713ca5a826e0460e08fe379dfa03ce65001432d88790 languageName: node linkType: hard @@ -3753,7 +3767,7 @@ __metadata: "@babel/types": ^7.18.13 debug: ^4.1.0 globals: ^11.1.0 - checksum: 1a2ef738fac4968feba6385787a3f8f7357d08e7739ecc5b37d8ff5668935253a03290f700f02a85ccfd369d5898625f0722d7733bff2ef91504f6cd8b836f19 + checksum: 6b31fd3ab79131b8830c5fede49eb2687ff3e1ee1527a77ee476274188a6ecfda65665a6d5759c6cb5469b798d0b28b4cf3df1ea3bb55f11946e8eea30c746a8 languageName: node linkType: hard @@ -3782,7 +3796,7 @@ __metadata: "@babel/helper-string-parser": ^7.18.10 "@babel/helper-validator-identifier": ^7.18.6 to-fast-properties: ^2.0.0 - checksum: abc3ad1f3b6864df0ea0e778bcdf7d2c5ee2293811192962d50e8a8c05c1aeec90a48275f53b2a45aad882ed8bef9477ae1f8e70ac1d44d039e14930d1388dcc + checksum: 1505b9cc1100da3876401c9c282dc266091a90e2732be7a0b3028d3e56046f079ff12c6d7b026f4ab3894fbfec9116122a0d5920352628b1cf11db30a2d91c39 languageName: node linkType: hard From bd8e8dc7cfa544a701fbf0673ea69a508841c46d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Wed, 24 Aug 2022 17:05:14 +0200 Subject: [PATCH 2/5] let -> var --- packages/babel-helpers/src/helpers-generated.ts | 2 +- packages/babel-helpers/src/helpers/wrapRegExp.js | 2 +- tsconfig.json | 4 ++++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/babel-helpers/src/helpers-generated.ts b/packages/babel-helpers/src/helpers-generated.ts index 07c11f7a6e51..d83b9864398b 100644 --- a/packages/babel-helpers/src/helpers-generated.ts +++ b/packages/babel-helpers/src/helpers-generated.ts @@ -39,6 +39,6 @@ export default Object.freeze({ ), wrapRegExp: helper( "7.2.6", - '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{let k=0;for(;void 0===result[i[k]]&&k+1]+)>/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]+)>/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)}', ), }); diff --git a/packages/babel-helpers/src/helpers/wrapRegExp.js b/packages/babel-helpers/src/helpers/wrapRegExp.js index f852d9e6cf36..b5100b6fec0f 100644 --- a/packages/babel-helpers/src/helpers/wrapRegExp.js +++ b/packages/babel-helpers/src/helpers/wrapRegExp.js @@ -60,7 +60,7 @@ export default function _wrapRegExp() { if (typeof i === "number") groups[name] = result[i]; else { // i is an array of indexes - let k = 0; + var k = 0; // if no group matched, we stop at k = i.length - 1 and then // we store result[i[i.length - 1]] which is undefined. while (result[i[k]] === undefined && k + 1 < i.length) k++; diff --git a/tsconfig.json b/tsconfig.json index 269001d3a2a7..8869ed393c1e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -50,6 +50,7 @@ "./packages/babel-plugin-proposal-decorators/src/**/*.ts", "./packages/babel-plugin-proposal-destructuring-private/src/**/*.ts", "./packages/babel-plugin-proposal-do-expressions/src/**/*.ts", + "./packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/src/**/*.ts", "./packages/babel-plugin-proposal-dynamic-import/src/**/*.ts", "./packages/babel-plugin-proposal-export-default-from/src/**/*.ts", "./packages/babel-plugin-proposal-export-namespace-from/src/**/*.ts", @@ -313,6 +314,9 @@ "@babel/plugin-proposal-do-expressions": [ "./packages/babel-plugin-proposal-do-expressions/src" ], + "@babel/plugin-proposal-duplicate-named-capturing-groups-regex": [ + "./packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex/src" + ], "@babel/plugin-proposal-dynamic-import": [ "./packages/babel-plugin-proposal-dynamic-import/src" ], From c97d9b7a7b8b6ea48611cf4d3e618a0a70cd9c78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Wed, 24 Aug 2022 17:16:19 +0200 Subject: [PATCH 3/5] Fix checksums --- yarn.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/yarn.lock b/yarn.lock index 7ffd884ccfb2..8c5033b1dcf7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -317,7 +317,7 @@ __metadata: gensync: ^1.0.0-beta.2 json5: ^2.2.1 semver: ^6.3.0 - checksum: bcc057bf6edbc4299bc759a292686d48e76d18617adb2327b38667a4972bb2ab1527c23b51168b37183d2fdb4218ac1f18319466d2c30837d469e9136dfd0dab + checksum: c7ee5b2c10bc5b0325e31fb5da4cb4bc03f9d5f5c00ec3481a018917bcc6b7b040de0690c606a424f57e5fc26d218d64e7718d0e5d7d8614d39c8cd898fab9b3 languageName: node linkType: hard @@ -452,7 +452,7 @@ __metadata: "@babel/types": ^7.18.13 "@jridgewell/gen-mapping": ^0.3.2 jsesc: ^2.5.1 - checksum: b98ef678ad07bc3af76a041517ce49cc9a5ed0b943e4359aa86af3320a0b0525f9d902cbf1969b37d0bf104bcd89af31c2f35408b8dabff038543d281b416733 + checksum: 27f5e7eb774e4d76ee75dc96e3e1bd26cc0ee7cea13a8f7342b716319c0a4d4e26fc49aa8f19316f7c99383da55eeb2a866c6e034e9deacad58a9de9ed6004fb languageName: node linkType: hard @@ -570,7 +570,7 @@ __metadata: "@babel/helper-split-export-declaration": ^7.18.6 peerDependencies: "@babel/core": ^7.0.0 - checksum: 000fb88ef4cc674a08d0b4f7b76db52e3f72fb0f0128d4881c140f640da2a8819601f1646e9956f7b6359d2d0b4ef155821c63f8f352c761ea82fff8e9ff7dc9 + checksum: 3d2da92a54b885b211a747a8c553bb0190895d140cd1daab5d9945b2b271817d9d288a512364085e9fad19bd503921cd85fcc12f98df67b39b27f5655eb9d058 languageName: node linkType: hard @@ -1098,7 +1098,7 @@ __metadata: resolution: "@babel/parser@npm:7.18.13" bin: parser: ./bin/babel-parser.js - checksum: e4d14756503a0f42936b7b1fa1bf8ece6208e56cd9b0294b51bb2ad37796dac6cc8cc912d4fcbc7cc82d7ac0aed4febb1dde0197caacca160e7ae153e93ffe69 + checksum: 8b41c35607668495d67d9a7c5f61768aaab26acf887efdadc2781aed54046981480ef40aeda0b84d61aed02cf0c4ff4b028d5f83ab85e17e2ddff318f9243b8b languageName: node linkType: hard @@ -2373,7 +2373,7 @@ __metadata: "@babel/helper-plugin-utils": ^7.18.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: a1e49ee0279234d61721b4099b6ddd37b528bdaa4fa4186e41f8408bfd6b54f61af9148ffd0725346c88713ca5a826e0460e08fe379dfa03ce65001432d88790 + checksum: 83e44ec93a4cfbf69376db8836d00ec803820081bf0f8b6cea73a9b3cd320b8285768d5b385744af4a27edda4b6502245c52d3ed026ea61356faf57bfe78effb languageName: node linkType: hard @@ -3767,7 +3767,7 @@ __metadata: "@babel/types": ^7.18.13 debug: ^4.1.0 globals: ^11.1.0 - checksum: 6b31fd3ab79131b8830c5fede49eb2687ff3e1ee1527a77ee476274188a6ecfda65665a6d5759c6cb5469b798d0b28b4cf3df1ea3bb55f11946e8eea30c746a8 + checksum: 1a2ef738fac4968feba6385787a3f8f7357d08e7739ecc5b37d8ff5668935253a03290f700f02a85ccfd369d5898625f0722d7733bff2ef91504f6cd8b836f19 languageName: node linkType: hard @@ -3796,7 +3796,7 @@ __metadata: "@babel/helper-string-parser": ^7.18.10 "@babel/helper-validator-identifier": ^7.18.6 to-fast-properties: ^2.0.0 - checksum: 1505b9cc1100da3876401c9c282dc266091a90e2732be7a0b3028d3e56046f079ff12c6d7b026f4ab3894fbfec9116122a0d5920352628b1cf11db30a2d91c39 + checksum: abc3ad1f3b6864df0ea0e778bcdf7d2c5ee2293811192962d50e8a8c05c1aeec90a48275f53b2a45aad882ed8bef9477ae1f8e70ac1d44d039e14930d1388dcc languageName: node linkType: hard From f4348e35c33d48737f60992cb671f8e5adedd6d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Wed, 24 Aug 2022 18:21:57 +0200 Subject: [PATCH 4/5] Avoid calling regexpu for duplicated named groups when not necessary --- .../src/index.ts | 23 ++++--------------- .../src/util.ts | 23 ++++++++++++++++--- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/packages/babel-helper-create-regexp-features-plugin/src/index.ts b/packages/babel-helper-create-regexp-features-plugin/src/index.ts index d1be9056db04..52b9e2188d28 100644 --- a/packages/babel-helper-create-regexp-features-plugin/src/index.ts +++ b/packages/babel-helper-create-regexp-features-plugin/src/index.ts @@ -95,18 +95,18 @@ export function createRegExpFeaturePlugin({ const features = file.get(featuresKey); const runtime = file.get(runtimeKey) ?? true; - const regexpuOptions = generateRegexpuOptions(features); - if (canSkipRegexpu(node, regexpuOptions)) return; + const regexpuOptions = generateRegexpuOptions(node.pattern, features); + if (canSkipRegexpu(node, regexpuOptions)) { + return; + } const namedCaptureGroups: Record = { __proto__: null, }; - let hasDuplicateNamedCaptureGroups = false; if (regexpuOptions.namedGroups === "transform") { regexpuOptions.onNamedGroup = (name, index) => { const prev = namedCaptureGroups[name]; if (typeof prev === "number") { - hasDuplicateNamedCaptureGroups = true; namedCaptureGroups[name] = [prev, index]; } else if (Array.isArray(prev)) { prev.push(index); @@ -116,20 +116,7 @@ export function createRegExpFeaturePlugin({ }; } - let pattern = rewritePattern(node.pattern, node.flags, regexpuOptions); - if ( - !hasDuplicateNamedCaptureGroups && - hasFeature(features, FEATURES.duplicateNamedCaptureGroups) && - !hasFeature(features, FEATURES.namedCaptureGroups) - ) { - // If we only transformed named groups because we want to transform duplicates - // but there are no duplicates, re-transform the regexp without transforming - // named groups. - regexpuOptions.namedGroups = false; - if (canSkipRegexpu(node, regexpuOptions)) return; - pattern = rewritePattern(node.pattern, node.flags, regexpuOptions); - } - node.pattern = pattern; + node.pattern = rewritePattern(node.pattern, node.flags, regexpuOptions); if ( regexpuOptions.namedGroups === "transform" && diff --git a/packages/babel-helper-create-regexp-features-plugin/src/util.ts b/packages/babel-helper-create-regexp-features-plugin/src/util.ts index 0648767f53dc..d879f0a14e70 100644 --- a/packages/babel-helper-create-regexp-features-plugin/src/util.ts +++ b/packages/babel-helper-create-regexp-features-plugin/src/util.ts @@ -3,7 +3,10 @@ import { FEATURES, hasFeature } from "./features"; import type { RegexpuOptions } from "regexpu-core"; -export function generateRegexpuOptions(toTransform: number): RegexpuOptions { +export function generateRegexpuOptions( + pattern: string, + toTransform: number, +): RegexpuOptions { type Experimental = 1; const feat = ( @@ -13,6 +16,21 @@ export function generateRegexpuOptions(toTransform: number): RegexpuOptions { return hasFeature(toTransform, FEATURES[name]) ? ok : false; }; + const featDuplicateNamedGroups = (): "transform" | false => { + if (!feat("duplicateNamedCaptureGroups")) return false; + + // This can return false positive, for example for /\(?\)/. + // However, it's such a rare occurrence that it's ok to compile + // the regexp even if we only need to compile regexps with + // duplicate named capturing groups. + const regex = /\(\?<([^>]+)>/g; + const seen = new Set(); + for (let match; (match = regex.exec(pattern)); seen.add(match[1])) { + if (seen.has(match[1])) return "transform"; + } + return false; + }; + return { unicodeFlag: feat("unicodeFlag"), unicodeSetsFlag: @@ -20,8 +38,7 @@ export function generateRegexpuOptions(toTransform: number): RegexpuOptions { feat("unicodeSetsFlag_syntax", "parse"), dotAllFlag: feat("dotAllFlag"), unicodePropertyEscapes: feat("unicodePropertyEscape"), - namedGroups: - feat("namedCaptureGroups") || feat("duplicateNamedCaptureGroups"), + namedGroups: feat("namedCaptureGroups") || featDuplicateNamedGroups(), onNamedGroup: () => {}, }; } From 5929d75b3266dd96a28f6fe061b144c4db70ba98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Thu, 25 Aug 2022 14:15:23 +0200 Subject: [PATCH 5/5] Add to standalone --- packages/babel-standalone/package.json | 1 + packages/babel-standalone/scripts/pluginConfig.json | 1 + packages/babel-standalone/src/generated/plugins.ts | 4 ++++ packages/babel-standalone/src/preset-stage-3.ts | 1 + yarn.lock | 3 ++- 5 files changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/babel-standalone/package.json b/packages/babel-standalone/package.json index 69fc1401e910..63b0e2de1888 100644 --- a/packages/babel-standalone/package.json +++ b/packages/babel-standalone/package.json @@ -16,6 +16,7 @@ "@babel/plugin-proposal-decorators": "workspace:^", "@babel/plugin-proposal-destructuring-private": "workspace:^", "@babel/plugin-proposal-do-expressions": "workspace:^", + "@babel/plugin-proposal-duplicate-named-capturing-groups-regex": "workspace:^", "@babel/plugin-proposal-dynamic-import": "workspace:^", "@babel/plugin-proposal-export-default-from": "workspace:^", "@babel/plugin-proposal-export-namespace-from": "workspace:^", diff --git a/packages/babel-standalone/scripts/pluginConfig.json b/packages/babel-standalone/scripts/pluginConfig.json index 363b180479f9..adde8183bce3 100644 --- a/packages/babel-standalone/scripts/pluginConfig.json +++ b/packages/babel-standalone/scripts/pluginConfig.json @@ -27,6 +27,7 @@ "proposal-decorators", "proposal-destructuring-private", "proposal-do-expressions", + "proposal-duplicate-named-capturing-groups-regex", "proposal-dynamic-import", "proposal-export-default-from", "proposal-export-namespace-from", diff --git a/packages/babel-standalone/src/generated/plugins.ts b/packages/babel-standalone/src/generated/plugins.ts index 0e9e6f9c1efb..ff13ad3fd0d8 100644 --- a/packages/babel-standalone/src/generated/plugins.ts +++ b/packages/babel-standalone/src/generated/plugins.ts @@ -30,6 +30,7 @@ import proposalClassStaticBlock from "@babel/plugin-proposal-class-static-block" import proposalDecorators from "@babel/plugin-proposal-decorators"; import proposalDestructuringPrivate from "@babel/plugin-proposal-destructuring-private"; import proposalDoExpressions from "@babel/plugin-proposal-do-expressions"; +import proposalDuplicateNamedCapturingGroupsRegex from "@babel/plugin-proposal-duplicate-named-capturing-groups-regex"; import proposalDynamicImport from "@babel/plugin-proposal-dynamic-import"; import proposalExportDefaultFrom from "@babel/plugin-proposal-export-default-from"; import proposalExportNamespaceFrom from "@babel/plugin-proposal-export-namespace-from"; @@ -128,6 +129,7 @@ export { proposalDecorators, proposalDestructuringPrivate, proposalDoExpressions, + proposalDuplicateNamedCapturingGroupsRegex, proposalDynamicImport, proposalExportDefaultFrom, proposalExportNamespaceFrom, @@ -227,6 +229,8 @@ export const all: { [k: string]: any } = { "proposal-decorators": proposalDecorators, "proposal-destructuring-private": proposalDestructuringPrivate, "proposal-do-expressions": proposalDoExpressions, + "proposal-duplicate-named-capturing-groups-regex": + proposalDuplicateNamedCapturingGroupsRegex, "proposal-dynamic-import": proposalDynamicImport, "proposal-export-default-from": proposalExportDefaultFrom, "proposal-export-namespace-from": proposalExportNamespaceFrom, diff --git a/packages/babel-standalone/src/preset-stage-3.ts b/packages/babel-standalone/src/preset-stage-3.ts index 7c7d73d73862..1a8e257edf5b 100644 --- a/packages/babel-standalone/src/preset-stage-3.ts +++ b/packages/babel-standalone/src/preset-stage-3.ts @@ -5,6 +5,7 @@ export default (_: any, { loose = false } = {}) => { const plugins: any[] = [ babelPlugins.syntaxImportAssertions, babelPlugins.proposalUnicodeSetsRegex, + babelPlugins.proposalDuplicateNamedCapturingGroupsRegex, ]; if (!process.env.BABEL_8_BREAKING) { diff --git a/yarn.lock b/yarn.lock index 8c5033b1dcf7..957d538dcad5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1359,7 +1359,7 @@ __metadata: languageName: unknown linkType: soft -"@babel/plugin-proposal-duplicate-named-capturing-groups-regex@workspace:packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex": +"@babel/plugin-proposal-duplicate-named-capturing-groups-regex@workspace:^, @babel/plugin-proposal-duplicate-named-capturing-groups-regex@workspace:packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex": version: 0.0.0-use.local resolution: "@babel/plugin-proposal-duplicate-named-capturing-groups-regex@workspace:packages/babel-plugin-proposal-duplicate-named-capturing-groups-regex" dependencies: @@ -3624,6 +3624,7 @@ __metadata: "@babel/plugin-proposal-decorators": "workspace:^" "@babel/plugin-proposal-destructuring-private": "workspace:^" "@babel/plugin-proposal-do-expressions": "workspace:^" + "@babel/plugin-proposal-duplicate-named-capturing-groups-regex": "workspace:^" "@babel/plugin-proposal-dynamic-import": "workspace:^" "@babel/plugin-proposal-export-default-from": "workspace:^" "@babel/plugin-proposal-export-namespace-from": "workspace:^"