@@ -47,6 +47,7 @@ var Token = tokenInfo.Token,
47
47
TokenName = tokenInfo . TokenName ,
48
48
FnExprTokens = tokenInfo . FnExprTokens ,
49
49
Regex = syntax . Regex ,
50
+ PlaceHolders ,
50
51
PropertyKind ,
51
52
source ,
52
53
strict ,
@@ -58,6 +59,12 @@ var Token = tokenInfo.Token,
58
59
state ,
59
60
extra ;
60
61
62
+ PlaceHolders = {
63
+ ArrowParameterPlaceHolder : {
64
+ type : "ArrowParameterPlaceHolder"
65
+ }
66
+ } ;
67
+
61
68
PropertyKind = {
62
69
Data : 1 ,
63
70
Get : 2 ,
@@ -2747,6 +2754,13 @@ function parseGroupExpression() {
2747
2754
2748
2755
expect ( "(" ) ;
2749
2756
2757
+ ++ state . parenthesisCount ;
2758
+
2759
+ if ( match ( ")" ) ) {
2760
+ lex ( ) ;
2761
+ return PlaceHolders . ArrowParameterPlaceHolder ;
2762
+ }
2763
+
2750
2764
expr = parseExpression ( ) ;
2751
2765
2752
2766
expect ( ")" ) ;
@@ -2823,10 +2837,9 @@ function parsePrimaryExpression() {
2823
2837
peek ( ) ;
2824
2838
} else if ( type === Token . Template ) {
2825
2839
return parseTemplateLiteral ( ) ;
2826
- } else {
2840
+ } else if ( ! expr ) {
2827
2841
throwUnexpected ( lex ( ) ) ;
2828
2842
}
2829
-
2830
2843
return markerApply ( marker , expr ) ;
2831
2844
}
2832
2845
@@ -3178,11 +3191,89 @@ function parseConditionalExpression() {
3178
3191
return expr ;
3179
3192
}
3180
3193
3194
+ // [ES6] 14.2 Arrow Function
3195
+
3196
+ function parseConciseBody ( ) {
3197
+ if ( match ( "{" ) ) {
3198
+ return parseFunctionSourceElements ( ) ;
3199
+ }
3200
+ return parseAssignmentExpression ( ) ;
3201
+ }
3202
+
3203
+ function reinterpretAsCoverFormalsList ( expressions ) {
3204
+ var i , len , param , params , defaults , defaultCount , options , rest ;
3205
+
3206
+ params = [ ] ;
3207
+ defaults = [ ] ;
3208
+ defaultCount = 0 ;
3209
+ rest = null ;
3210
+ options = {
3211
+ paramSet : { }
3212
+ } ;
3213
+
3214
+ for ( i = 0 , len = expressions . length ; i < len ; i += 1 ) {
3215
+ param = expressions [ i ] ;
3216
+ if ( param . type === astNodeTypes . Identifier ) {
3217
+ params . push ( param ) ;
3218
+ defaults . push ( null ) ;
3219
+ validateParam ( options , param , param . name ) ;
3220
+ } else if ( param . type === astNodeTypes . AssignmentExpression ) {
3221
+ params . push ( param . left ) ;
3222
+ defaults . push ( param . right ) ;
3223
+ ++ defaultCount ;
3224
+ validateParam ( options , param . left , param . left . name ) ;
3225
+ } else {
3226
+ return null ;
3227
+ }
3228
+ }
3229
+
3230
+ if ( options . message === Messages . StrictParamDupe ) {
3231
+ throwError (
3232
+ strict ? options . stricted : options . firstRestricted ,
3233
+ options . message
3234
+ ) ;
3235
+ }
3236
+
3237
+ // must be here so it's not an array of [null, null]
3238
+ if ( defaultCount === 0 ) {
3239
+ defaults = [ ] ;
3240
+ }
3241
+
3242
+ return {
3243
+ params : params ,
3244
+ defaults : defaults ,
3245
+ rest : rest ,
3246
+ stricted : options . stricted ,
3247
+ firstRestricted : options . firstRestricted ,
3248
+ message : options . message
3249
+ } ;
3250
+ }
3251
+
3252
+ function parseArrowFunctionExpression ( options , marker ) {
3253
+ var previousStrict , body ;
3254
+
3255
+ expect ( "=>" ) ;
3256
+ previousStrict = strict ;
3257
+
3258
+ body = parseConciseBody ( ) ;
3259
+
3260
+ if ( strict && options . firstRestricted ) {
3261
+ throwError ( options . firstRestricted , options . message ) ;
3262
+ }
3263
+ if ( strict && options . stricted ) {
3264
+ throwErrorTolerant ( options . stricted , options . message ) ;
3265
+ }
3266
+
3267
+ strict = previousStrict ;
3268
+ return markerApply ( marker , astNodeFactory . createArrowFunctionExpression ( options . params , options . defaults , body , body . type !== astNodeTypes . BlockStatement ) ) ;
3269
+ }
3270
+
3181
3271
// 11.13 Assignment Operators
3182
3272
3183
3273
function parseAssignmentExpression ( ) {
3184
- var token , left , right , node ,
3274
+ var token , left , right , list , node , params ,
3185
3275
marker ,
3276
+ oldParenthesisCount = state . parenthesisCount ,
3186
3277
allowGenerators = extra . ecmaFeatures . generators ;
3187
3278
3188
3279
// Note that 'yield' is treated as a keyword in strict mode, but a
@@ -3193,10 +3284,41 @@ function parseAssignmentExpression() {
3193
3284
}
3194
3285
3195
3286
marker = markerCreate ( ) ;
3196
- token = lookahead ;
3197
3287
3288
+ if ( match ( "(" ) ) {
3289
+ token = lookahead2 ( ) ;
3290
+ if ( token . value === ")" && token . type === Token . Punctuator ) {
3291
+ params = parseParams ( ) ;
3292
+ list = {
3293
+ defaults : [ ] ,
3294
+ params : params . params
3295
+ } ;
3296
+ return markerApply ( marker , parseArrowFunctionExpression ( list , marker ) ) ;
3297
+ }
3298
+ }
3299
+
3300
+ // revert to the previous lookahead style object
3301
+ token = lookahead ;
3198
3302
node = left = parseConditionalExpression ( ) ;
3199
3303
3304
+ if ( node === PlaceHolders . ArrowParameterPlaceHolder || match ( "=>" ) ) {
3305
+ if ( state . parenthesisCount === oldParenthesisCount ||
3306
+ state . parenthesisCount === ( oldParenthesisCount + 1 ) ) {
3307
+ if ( node . type === astNodeTypes . Identifier ) {
3308
+ list = reinterpretAsCoverFormalsList ( [ node ] ) ;
3309
+ } else if ( node . type === astNodeTypes . AssignmentExpression ) {
3310
+ list = reinterpretAsCoverFormalsList ( [ node ] ) ;
3311
+ } else if ( node . type === astNodeTypes . SequenceExpression ) {
3312
+ list = reinterpretAsCoverFormalsList ( node . expressions ) ;
3313
+ } else if ( node === PlaceHolders . ArrowParameterPlaceHolder ) {
3314
+ list = reinterpretAsCoverFormalsList ( [ ] ) ;
3315
+ }
3316
+ if ( list ) {
3317
+ return parseArrowFunctionExpression ( list , marker ) ;
3318
+ }
3319
+ }
3320
+ }
3321
+
3200
3322
if ( matchAssign ( ) ) {
3201
3323
// LeftHandSideExpression
3202
3324
if ( ! isLeftHandSide ( left ) ) {
@@ -3947,7 +4069,7 @@ function parseStatement() {
3947
4069
3948
4070
function parseFunctionSourceElements ( ) {
3949
4071
var sourceElement , sourceElements = [ ] , token , directive , firstRestricted ,
3950
- oldLabelSet , oldInIteration , oldInSwitch , oldInFunctionBody ,
4072
+ oldLabelSet , oldInIteration , oldInSwitch , oldInFunctionBody , oldParenthesisCount ,
3951
4073
marker = markerCreate ( ) ;
3952
4074
3953
4075
expect ( "{" ) ;
@@ -3981,6 +4103,7 @@ function parseFunctionSourceElements() {
3981
4103
oldInIteration = state . inIteration ;
3982
4104
oldInSwitch = state . inSwitch ;
3983
4105
oldInFunctionBody = state . inFunctionBody ;
4106
+ oldParenthesisCount = state . parenthesizedCount ;
3984
4107
3985
4108
state . labelSet = { } ;
3986
4109
state . inIteration = false ;
@@ -4008,10 +4131,37 @@ function parseFunctionSourceElements() {
4008
4131
state . inIteration = oldInIteration ;
4009
4132
state . inSwitch = oldInSwitch ;
4010
4133
state . inFunctionBody = oldInFunctionBody ;
4134
+ state . parenthesizedCount = oldParenthesisCount ;
4011
4135
4012
4136
return markerApply ( marker , astNodeFactory . createBlockStatement ( sourceElements ) ) ;
4013
4137
}
4014
4138
4139
+ function validateParam ( options , param , name ) {
4140
+ var key = "$" + name ;
4141
+ if ( strict ) {
4142
+ if ( syntax . isRestrictedWord ( name ) ) {
4143
+ options . stricted = param ;
4144
+ options . message = Messages . StrictParamName ;
4145
+ }
4146
+ if ( Object . prototype . hasOwnProperty . call ( options . paramSet , key ) ) {
4147
+ options . stricted = param ;
4148
+ options . message = Messages . StrictParamDupe ;
4149
+ }
4150
+ } else if ( ! options . firstRestricted ) {
4151
+ if ( syntax . isRestrictedWord ( name ) ) {
4152
+ options . firstRestricted = param ;
4153
+ options . message = Messages . StrictParamName ;
4154
+ } else if ( syntax . isStrictModeReservedWord ( name ) ) {
4155
+ options . firstRestricted = param ;
4156
+ options . message = Messages . StrictReservedWord ;
4157
+ } else if ( Object . prototype . hasOwnProperty . call ( options . paramSet , key ) ) {
4158
+ options . firstRestricted = param ;
4159
+ options . message = Messages . StrictParamDupe ;
4160
+ }
4161
+ }
4162
+ options . paramSet [ key ] = true ;
4163
+ }
4164
+
4015
4165
function parseParams ( firstRestricted ) {
4016
4166
var param , params = [ ] , defaults = [ ] , defaultCount = 0 , token , stricted , paramSet , key , message , def ,
4017
4167
allowDefaultParams = extra . ecmaFeatures . defaultParams ;
@@ -4357,6 +4507,7 @@ function tokenize(code, options) {
4357
4507
state = {
4358
4508
allowIn : true ,
4359
4509
labelSet : { } ,
4510
+ parenthesisCount : 0 ,
4360
4511
inFunctionBody : false ,
4361
4512
inIteration : false ,
4362
4513
inSwitch : false ,
@@ -4461,6 +4612,7 @@ function parse(code, options) {
4461
4612
state = {
4462
4613
allowIn : true ,
4463
4614
labelSet : { } ,
4615
+ parenthesisCount : 0 ,
4464
4616
inFunctionBody : false ,
4465
4617
inIteration : false ,
4466
4618
inSwitch : false ,
0 commit comments