- Revision
- 254195
- Author
- [email protected]
- Date
- 2020-01-08 05:48:20 -0800 (Wed, 08 Jan 2020)
Log Message
RegExp.prototype[Symbol.replace] does not support named capture groups
https://bugs.webkit.org/show_bug.cgi?id=205783
Reviewed by Ross Kirsling.
JSTests:
* test262/expectations.yaml: Mark 6 test cases as passing.
Source/_javascript_Core:
This patch adds named capture groups support to RegExp.prototype[Symbol.replace],
for both functional and string pattern replacement.
(steps 14.j-l of https://tc39.es/ecma262/#sec-regexp.prototype-@@replace)
This method is used in slow path of String.prototype.replace (RegExp subclass handling),
yet it also can be invoked directly in user code.
* builtins/RegExpPrototype.js:
(getSubstitution):
(Symbol.replace):
Modified Paths
Diff
Modified: trunk/JSTests/ChangeLog (254194 => 254195)
--- trunk/JSTests/ChangeLog 2020-01-08 12:45:03 UTC (rev 254194)
+++ trunk/JSTests/ChangeLog 2020-01-08 13:48:20 UTC (rev 254195)
@@ -1,3 +1,12 @@
+2020-01-08 Alexey Shvayka <[email protected]>
+
+ RegExp.prototype[Symbol.replace] does not support named capture groups
+ https://bugs.webkit.org/show_bug.cgi?id=205783
+
+ Reviewed by Ross Kirsling.
+
+ * test262/expectations.yaml: Mark 6 test cases as passing.
+
2020-01-07 Saam Barati <[email protected]>
AI rule for ValueMod/ValueDiv produce constants with the wrong format when the result can be an int32
Modified: trunk/JSTests/test262/expectations.yaml (254194 => 254195)
--- trunk/JSTests/test262/expectations.yaml 2020-01-08 12:45:03 UTC (rev 254194)
+++ trunk/JSTests/test262/expectations.yaml 2020-01-08 13:48:20 UTC (rev 254195)
@@ -1264,12 +1264,6 @@
test/built-ins/Proxy/construct/trap-is-not-callable-realm.js:
default: 'Test262Error: Expected a TypeError but got a TypeError'
strict mode: 'Test262Error: Expected a TypeError but got a TypeError'
-test/built-ins/RegExp/named-groups/groups-object-subclass-sans.js:
- default: 'Test262Error: Expected SameValue(«b», «$<a>») to be true'
- strict mode: 'Test262Error: Expected SameValue(«b», «$<a>») to be true'
-test/built-ins/RegExp/named-groups/groups-object-subclass.js:
- default: 'Test262Error: Expected SameValue(«b», «$<a>») to be true'
- strict mode: 'Test262Error: Expected SameValue(«b», «$<a>») to be true'
test/built-ins/RegExp/named-groups/unicode-property-names.js:
default: 'SyntaxError: Invalid regular _expression_: invalid group specifier name'
strict mode: 'SyntaxError: Invalid regular _expression_: invalid group specifier name'
@@ -1669,9 +1663,6 @@
test/built-ins/String/proto-from-ctor-realm.js:
default: 'Test262Error: Expected SameValue(«», «») to be true'
strict mode: 'Test262Error: Expected SameValue(«», «») to be true'
-test/built-ins/String/prototype/replaceAll/searchValue-replacer-RegExp-call.js:
- default: "Test262Error: sample 11: 'abcba'.replaceAll(/(?<named>b)/g, '($<named>)') Expected SameValue(«a($<named>)c($<named>)a», «a(b)c(b)a») to be true"
- strict mode: "Test262Error: sample 11: 'abcba'.replaceAll(/(?<named>b)/g, '($<named>)') Expected SameValue(«a($<named>)c($<named>)a», «a(b)c(b)a») to be true"
test/built-ins/ThrowTypeError/extensible.js:
default: 'Test262Error: Expected SameValue(«true», «false») to be true'
strict mode: 'Test262Error: Expected SameValue(«true», «false») to be true'
Modified: trunk/Source/_javascript_Core/ChangeLog (254194 => 254195)
--- trunk/Source/_javascript_Core/ChangeLog 2020-01-08 12:45:03 UTC (rev 254194)
+++ trunk/Source/_javascript_Core/ChangeLog 2020-01-08 13:48:20 UTC (rev 254195)
@@ -1,3 +1,21 @@
+2020-01-08 Alexey Shvayka <[email protected]>
+
+ RegExp.prototype[Symbol.replace] does not support named capture groups
+ https://bugs.webkit.org/show_bug.cgi?id=205783
+
+ Reviewed by Ross Kirsling.
+
+ This patch adds named capture groups support to RegExp.prototype[Symbol.replace],
+ for both functional and string pattern replacement.
+ (steps 14.j-l of https://tc39.es/ecma262/#sec-regexp.prototype-@@replace)
+
+ This method is used in slow path of String.prototype.replace (RegExp subclass handling),
+ yet it also can be invoked directly in user code.
+
+ * builtins/RegExpPrototype.js:
+ (getSubstitution):
+ (Symbol.replace):
+
2020-01-07 Saam Barati <[email protected]>
AI rule for ValueMod/ValueDiv produce constants with the wrong format when the result can be an int32
Modified: trunk/Source/_javascript_Core/builtins/RegExpPrototype.js (254194 => 254195)
--- trunk/Source/_javascript_Core/builtins/RegExpPrototype.js 2020-01-08 12:45:03 UTC (rev 254194)
+++ trunk/Source/_javascript_Core/builtins/RegExpPrototype.js 2020-01-08 13:48:20 UTC (rev 254195)
@@ -179,7 +179,7 @@
{
"use strict";
- function getSubstitution(matched, str, position, captures, replacement)
+ function getSubstitution(matched, str, position, captures, namedCaptures, replacement)
{
"use strict";
@@ -219,6 +219,24 @@
result = result + str.substring(tailPos);
start++;
break;
+ case "<":
+ if (namedCaptures !== @undefined) {
+ let groupNameStartIndex = start + 1;
+ let groupNameEndIndex = replacement.indexOf(">", groupNameStartIndex);
+ if (groupNameEndIndex !== -1) {
+ let groupName = replacement.substring(groupNameStartIndex, groupNameEndIndex);
+ let capture = namedCaptures[groupName];
+ if (capture !== @undefined)
+ result = result + @toString(capture);
+
+ start = groupNameEndIndex + 1;
+ break;
+ }
+ }
+
+ result = result + "$<";
+ start++;
+ break;
default:
let chCode = ch.charCodeAt(0);
if (chCode >= 0x30 && chCode <= 0x39) {
@@ -325,6 +343,7 @@
}
let replacement;
+ let namedCaptures = result.groups;
if (functionalReplace) {
let replacerArgs = [ matched ].concat(captures);
@@ -331,11 +350,18 @@
replacerArgs.@push(position);
replacerArgs.@push(str);
+ if (namedCaptures !== @undefined)
+ replacerArgs.@push(namedCaptures);
+
let replValue = replace.@apply(@undefined, replacerArgs);
replacement = @toString(replValue);
- } else
- replacement = getSubstitution(matched, str, position, captures, replace);
+ } else {
+ if (namedCaptures !== @undefined)
+ namedCaptures = @toObject(namedCaptures, "RegExp.prototype[Symbol.replace] requires 'groups' property of a match not be null");
+ replacement = getSubstitution(matched, str, position, captures, namedCaptures, replace);
+ }
+
if (position >= nextSourcePosition && position >= lastPosition) {
accumulatedResult = accumulatedResult + str.substring(nextSourcePosition, position) + replacement;
nextSourcePosition = position + matchLength;