@@ -661,7 +661,7 @@ var pp$9 = Parser.prototype;
661
661
662
662
// ## Parser utilities
663
663
664
- var literal = / ^ (?: ' ( (?: \\ . | [ ^ ' \\ ] ) * ?) ' | " ( (?: \\ . | [ ^ " \\ ] ) * ?) " ) / ;
664
+ var literal = / ^ (?: ' ( (?: \\ [ ^ ] | [ ^ ' \\ ] ) * ?) ' | " ( (?: \\ [ ^ ] | [ ^ " \\ ] ) * ?) " ) / ;
665
665
pp$9 . strictDirective = function ( start ) {
666
666
if ( this . options . ecmaVersion < 5 ) { return false }
667
667
for ( ; ; ) {
@@ -847,7 +847,7 @@ pp$8.isLet = function(context) {
847
847
// Statement) is allowed here. If context is not empty then only a Statement
848
848
// is allowed. However, `let [` is an explicit negative lookahead for
849
849
// ExpressionStatement, so special-case it first.
850
- if ( nextCh === 91 || nextCh === 92 ) { return true } // '[', '/ '
850
+ if ( nextCh === 91 || nextCh === 92 ) { return true } // '[', '\ '
851
851
if ( context ) { return false }
852
852
853
853
if ( nextCh === 123 || nextCh > 0xd7ff && nextCh < 0xdc00 ) { return true } // '{', astral
@@ -1040,13 +1040,19 @@ pp$8.parseForStatement = function(node) {
1040
1040
return this . parseFor ( node , init$1 )
1041
1041
}
1042
1042
var startsWithLet = this . isContextual ( "let" ) , isForOf = false ;
1043
+ var containsEsc = this . containsEsc ;
1043
1044
var refDestructuringErrors = new DestructuringErrors ;
1044
- var init = this . parseExpression ( awaitAt > - 1 ? "await" : true , refDestructuringErrors ) ;
1045
+ var initPos = this . start ;
1046
+ var init = awaitAt > - 1
1047
+ ? this . parseExprSubscripts ( refDestructuringErrors , "await" )
1048
+ : this . parseExpression ( true , refDestructuringErrors ) ;
1045
1049
if ( this . type === types$1 . _in || ( isForOf = this . options . ecmaVersion >= 6 && this . isContextual ( "of" ) ) ) {
1046
- if ( this . options . ecmaVersion >= 9 ) {
1047
- if ( this . type === types$1 . _in ) {
1048
- if ( awaitAt > - 1 ) { this . unexpected ( awaitAt ) ; }
1049
- } else { node . await = awaitAt > - 1 ; }
1050
+ if ( awaitAt > - 1 ) { // implies `ecmaVersion >= 9` (see declaration of awaitAt)
1051
+ if ( this . type === types$1 . _in ) { this . unexpected ( awaitAt ) ; }
1052
+ node . await = true ;
1053
+ } else if ( isForOf && this . options . ecmaVersion >= 8 ) {
1054
+ if ( init . start === initPos && ! containsEsc && init . type === "Identifier" && init . name === "async" ) { this . unexpected ( ) ; }
1055
+ else if ( this . options . ecmaVersion >= 9 ) { node . await = false ; }
1050
1056
}
1051
1057
if ( startsWithLet && isForOf ) { this . raise ( init . start , "The left-hand side of a for-of loop may not start with 'let'." ) ; }
1052
1058
this . toAssignable ( init , false , refDestructuringErrors ) ;
@@ -2659,8 +2665,7 @@ pp$5.parseMaybeUnary = function(refDestructuringErrors, sawUnary, incDec, forIni
2659
2665
node . argument = this . parseMaybeUnary ( null , true , update , forInit ) ;
2660
2666
this . checkExpressionErrors ( refDestructuringErrors , true ) ;
2661
2667
if ( update ) { this . checkLValSimple ( node . argument ) ; }
2662
- else if ( this . strict && node . operator === "delete" &&
2663
- node . argument . type === "Identifier" )
2668
+ else if ( this . strict && node . operator === "delete" && isLocalVariableAccess ( node . argument ) )
2664
2669
{ this . raiseRecoverable ( node . start , "Deleting local variable in strict mode" ) ; }
2665
2670
else if ( node . operator === "delete" && isPrivateFieldAccess ( node . argument ) )
2666
2671
{ this . raiseRecoverable ( node . start , "Private fields can not be deleted" ) ; }
@@ -2695,10 +2700,18 @@ pp$5.parseMaybeUnary = function(refDestructuringErrors, sawUnary, incDec, forIni
2695
2700
}
2696
2701
} ;
2697
2702
2703
+ function isLocalVariableAccess ( node ) {
2704
+ return (
2705
+ node . type === "Identifier" ||
2706
+ node . type === "ParenthesizedExpression" && isLocalVariableAccess ( node . expression )
2707
+ )
2708
+ }
2709
+
2698
2710
function isPrivateFieldAccess ( node ) {
2699
2711
return (
2700
2712
node . type === "MemberExpression" && node . property . type === "PrivateIdentifier" ||
2701
- node . type === "ChainExpression" && isPrivateFieldAccess ( node . expression )
2713
+ node . type === "ChainExpression" && isPrivateFieldAccess ( node . expression ) ||
2714
+ node . type === "ParenthesizedExpression" && isPrivateFieldAccess ( node . expression )
2702
2715
)
2703
2716
}
2704
2717
@@ -3125,7 +3138,7 @@ pp$5.parseTemplateElement = function(ref) {
3125
3138
this . raiseRecoverable ( this . start , "Bad escape sequence in untagged template literal" ) ;
3126
3139
}
3127
3140
elem . value = {
3128
- raw : this . value ,
3141
+ raw : this . value . replace ( / \r \n ? / g , "\n" ) ,
3129
3142
cooked : null
3130
3143
} ;
3131
3144
} else {
@@ -3800,6 +3813,30 @@ for (var i = 0, list = [9, 10, 11, 12, 13, 14]; i < list.length; i += 1) {
3800
3813
3801
3814
var pp$1 = Parser . prototype ;
3802
3815
3816
+ // Track disjunction structure to determine whether a duplicate
3817
+ // capture group name is allowed because it is in a separate branch.
3818
+ var BranchID = function BranchID ( parent , base ) {
3819
+ // Parent disjunction branch
3820
+ this . parent = parent ;
3821
+ // Identifies this set of sibling branches
3822
+ this . base = base || this ;
3823
+ } ;
3824
+
3825
+ BranchID . prototype . separatedFrom = function separatedFrom ( alt ) {
3826
+ // A branch is separate from another branch if they or any of
3827
+ // their parents are siblings in a given disjunction
3828
+ for ( var self = this ; self ; self = self . parent ) {
3829
+ for ( var other = alt ; other ; other = other . parent ) {
3830
+ if ( self . base === other . base && self !== other ) { return true }
3831
+ }
3832
+ }
3833
+ return false
3834
+ } ;
3835
+
3836
+ BranchID . prototype . sibling = function sibling ( ) {
3837
+ return new BranchID ( this . parent , this . base )
3838
+ } ;
3839
+
3803
3840
var RegExpValidationState = function RegExpValidationState ( parser ) {
3804
3841
this . parser = parser ;
3805
3842
this . validFlags = "gim" + ( parser . options . ecmaVersion >= 6 ? "uy" : "" ) + ( parser . options . ecmaVersion >= 9 ? "s" : "" ) + ( parser . options . ecmaVersion >= 13 ? "d" : "" ) + ( parser . options . ecmaVersion >= 15 ? "v" : "" ) ;
@@ -3816,8 +3853,9 @@ var RegExpValidationState = function RegExpValidationState(parser) {
3816
3853
this . lastAssertionIsQuantifiable = false ;
3817
3854
this . numCapturingParens = 0 ;
3818
3855
this . maxBackReference = 0 ;
3819
- this . groupNames = [ ] ;
3856
+ this . groupNames = Object . create ( null ) ;
3820
3857
this . backReferenceNames = [ ] ;
3858
+ this . branchID = null ;
3821
3859
} ;
3822
3860
3823
3861
RegExpValidationState . prototype . reset = function reset ( start , pattern , flags ) {
@@ -3949,6 +3987,11 @@ pp$1.validateRegExpFlags = function(state) {
3949
3987
}
3950
3988
} ;
3951
3989
3990
+ function hasProp ( obj ) {
3991
+ for ( var _ in obj ) { return true }
3992
+ return false
3993
+ }
3994
+
3952
3995
/**
3953
3996
* Validate the pattern part of a given RegExpLiteral.
3954
3997
*
@@ -3963,7 +4006,7 @@ pp$1.validateRegExpPattern = function(state) {
3963
4006
// |Pattern[~U, +N]| and use this result instead. Throw a *SyntaxError*
3964
4007
// exception if _P_ did not conform to the grammar, if any elements of _P_
3965
4008
// were not matched by the parse, or if any Early Error conditions exist.
3966
- if ( ! state . switchN && this . options . ecmaVersion >= 9 && state . groupNames . length > 0 ) {
4009
+ if ( ! state . switchN && this . options . ecmaVersion >= 9 && hasProp ( state . groupNames ) ) {
3967
4010
state . switchN = true ;
3968
4011
this . regexp_pattern ( state ) ;
3969
4012
}
@@ -3977,8 +4020,9 @@ pp$1.regexp_pattern = function(state) {
3977
4020
state . lastAssertionIsQuantifiable = false ;
3978
4021
state . numCapturingParens = 0 ;
3979
4022
state . maxBackReference = 0 ;
3980
- state . groupNames . length = 0 ;
4023
+ state . groupNames = Object . create ( null ) ;
3981
4024
state . backReferenceNames . length = 0 ;
4025
+ state . branchID = null ;
3982
4026
3983
4027
this . regexp_disjunction ( state ) ;
3984
4028
@@ -3997,18 +4041,22 @@ pp$1.regexp_pattern = function(state) {
3997
4041
for ( var i = 0 , list = state . backReferenceNames ; i < list . length ; i += 1 ) {
3998
4042
var name = list [ i ] ;
3999
4043
4000
- if ( state . groupNames . indexOf ( name ) === - 1 ) {
4044
+ if ( ! state . groupNames [ name ] ) {
4001
4045
state . raise ( "Invalid named capture referenced" ) ;
4002
4046
}
4003
4047
}
4004
4048
} ;
4005
4049
4006
4050
// https://www.ecma-international.org/ecma-262/8.0/#prod-Disjunction
4007
4051
pp$1 . regexp_disjunction = function ( state ) {
4052
+ var trackDisjunction = this . options . ecmaVersion >= 16 ;
4053
+ if ( trackDisjunction ) { state . branchID = new BranchID ( state . branchID , null ) ; }
4008
4054
this . regexp_alternative ( state ) ;
4009
4055
while ( state . eat ( 0x7C /* | */ ) ) {
4056
+ if ( trackDisjunction ) { state . branchID = state . branchID . sibling ( ) ; }
4010
4057
this . regexp_alternative ( state ) ;
4011
4058
}
4059
+ if ( trackDisjunction ) { state . branchID = state . branchID . parent ; }
4012
4060
4013
4061
// Make the same message as V8.
4014
4062
if ( this . regexp_eatQuantifier ( state , true ) ) {
@@ -4021,8 +4069,7 @@ pp$1.regexp_disjunction = function(state) {
4021
4069
4022
4070
// https://www.ecma-international.org/ecma-262/8.0/#prod-Alternative
4023
4071
pp$1 . regexp_alternative = function ( state ) {
4024
- while ( state . pos < state . source . length && this . regexp_eatTerm ( state ) )
4025
- { }
4072
+ while ( state . pos < state . source . length && this . regexp_eatTerm ( state ) ) { }
4026
4073
} ;
4027
4074
4028
4075
// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Term
@@ -4260,14 +4307,26 @@ pp$1.regexp_eatExtendedPatternCharacter = function(state) {
4260
4307
// `?` GroupName
4261
4308
pp$1 . regexp_groupSpecifier = function ( state ) {
4262
4309
if ( state . eat ( 0x3F /* ? */ ) ) {
4263
- if ( this . regexp_eatGroupName ( state ) ) {
4264
- if ( state . groupNames . indexOf ( state . lastStringValue ) !== - 1 ) {
4310
+ if ( ! this . regexp_eatGroupName ( state ) ) { state . raise ( "Invalid group" ) ; }
4311
+ var trackDisjunction = this . options . ecmaVersion >= 16 ;
4312
+ var known = state . groupNames [ state . lastStringValue ] ;
4313
+ if ( known ) {
4314
+ if ( trackDisjunction ) {
4315
+ for ( var i = 0 , list = known ; i < list . length ; i += 1 ) {
4316
+ var altID = list [ i ] ;
4317
+
4318
+ if ( ! altID . separatedFrom ( state . branchID ) )
4319
+ { state . raise ( "Duplicate capture group name" ) ; }
4320
+ }
4321
+ } else {
4265
4322
state . raise ( "Duplicate capture group name" ) ;
4266
4323
}
4267
- state . groupNames . push ( state . lastStringValue ) ;
4268
- return
4269
4324
}
4270
- state . raise ( "Invalid group" ) ;
4325
+ if ( trackDisjunction ) {
4326
+ ( known || ( state . groupNames [ state . lastStringValue ] = [ ] ) ) . push ( state . branchID ) ;
4327
+ } else {
4328
+ state . groupNames [ state . lastStringValue ] = true ;
4329
+ }
4271
4330
}
4272
4331
} ;
4273
4332
@@ -5772,15 +5831,18 @@ pp.readInvalidTemplateToken = function() {
5772
5831
break
5773
5832
5774
5833
case "$" :
5775
- if ( this . input [ this . pos + 1 ] !== "{" ) {
5776
- break
5777
- }
5778
-
5779
- // falls through
5834
+ if ( this . input [ this . pos + 1 ] !== "{" ) { break }
5835
+ // fall through
5780
5836
case "`" :
5781
5837
return this . finishToken ( types$1 . invalidTemplate , this . input . slice ( this . start , this . pos ) )
5782
5838
5783
- // no default
5839
+ case "\r" :
5840
+ if ( this . input [ this . pos + 1 ] === "\n" ) { ++ this . pos ; }
5841
+ // fall through
5842
+ case "\n" : case "\u2028" : case "\u2029" :
5843
+ ++ this . curLine ;
5844
+ this . lineStart = this . pos + 1 ;
5845
+ break
5784
5846
}
5785
5847
}
5786
5848
this . raise ( this . start , "Unterminated template" ) ;
@@ -5843,6 +5905,7 @@ pp.readEscapedChar = function(inTemplate) {
5843
5905
if ( isNewLine ( ch ) ) {
5844
5906
// Unicode new line characters after \ get removed from output in both
5845
5907
// template literals and strings
5908
+ if ( this . options . locations ) { this . lineStart = this . pos ; ++ this . curLine ; }
5846
5909
return ""
5847
5910
}
5848
5911
return String . fromCharCode ( ch )
@@ -5921,7 +5984,7 @@ pp.readWord = function() {
5921
5984
// [walk]: util/walk.js
5922
5985
5923
5986
5924
- var version = "8.11.3 " ;
5987
+ var version = "8.12.1 " ;
5925
5988
5926
5989
Parser . acorn = {
5927
5990
Parser : Parser ,
0 commit comments