@@ -1191,14 +1191,18 @@ func (p *parser) scanBasicBackslash(scanOnly bool) (*regexNode, error) {
1191
1191
backpos := p .textpos ()
1192
1192
ch := p .rightChar (0 )
1193
1193
1194
- // allow \k<foo> instead of \<foo>, which is now deprecated
1194
+ // Allow \k<foo> instead of \<foo>, which is now deprecated.
1195
1195
1196
- if ch == 'k' {
1196
+ // According to ECMAScript specification, \k<name> is only parsed as a named group reference if
1197
+ // there is at least one group name in the regexp.
1198
+ // See https://www.ecma-international.org/ecma-262/#sec-isvalidregularexpressionliteral, step 7.
1199
+ // Note, during the first (scanOnly) run we may not have all group names scanned, but that's ok.
1200
+ if ch == 'k' && (! p .useOptionE () || len (p .capnames ) > 0 ) {
1197
1201
if p .charsRight () >= 2 {
1198
1202
p .moveRight (1 )
1199
1203
ch = p .moveRightGetChar ()
1200
1204
1201
- if ch == '<' || ch == '\'' {
1205
+ if ch == '<' || ( ! p . useOptionE () && ch == '\'' ) { // No support for \k'name' in ECMAScript
1202
1206
angled = true
1203
1207
if ch == '\'' {
1204
1208
close = '\''
@@ -1214,7 +1218,7 @@ func (p *parser) scanBasicBackslash(scanOnly bool) (*regexNode, error) {
1214
1218
1215
1219
ch = p .rightChar (0 )
1216
1220
1217
- } else if (ch == '<' || ch == '\'' ) && p .charsRight () > 1 { // Note angle without \g
1221
+ } else if ! p . useOptionE () && (ch == '<' || ch == '\'' ) && p .charsRight () > 1 { // Note angle without \g
1218
1222
angled = true
1219
1223
if ch == '\'' {
1220
1224
close = '\''
@@ -1257,14 +1261,21 @@ func (p *parser) scanBasicBackslash(scanOnly bool) (*regexNode, error) {
1257
1261
return nil , p .getErr (ErrUndefinedBackRef , capnum )
1258
1262
}
1259
1263
1260
- } else if angled && IsWordChar ( ch ) {
1264
+ } else if angled {
1261
1265
capname := p .scanCapname ()
1262
1266
1263
- if p .charsRight () > 0 && p .moveRightGetChar () == close {
1267
+ if capname != "" && p .charsRight () > 0 && p .moveRightGetChar () == close {
1268
+
1269
+ if scanOnly {
1270
+ return nil , nil
1271
+ }
1272
+
1264
1273
if p .isCaptureName (capname ) {
1265
1274
return newRegexNodeM (ntRef , p .options , p .captureSlotFromName (capname )), nil
1266
1275
}
1267
1276
return nil , p .getErr (ErrUndefinedNameRef , capname )
1277
+ } else {
1278
+ return nil , p .getErr (ErrMalformedNameRef )
1268
1279
}
1269
1280
}
1270
1281
@@ -1276,6 +1287,10 @@ func (p *parser) scanBasicBackslash(scanOnly bool) (*regexNode, error) {
1276
1287
return nil , err
1277
1288
}
1278
1289
1290
+ if scanOnly {
1291
+ return nil , nil
1292
+ }
1293
+
1279
1294
if p .useOptionI () {
1280
1295
ch = unicode .ToLower (ch )
1281
1296
}
0 commit comments