@@ -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 ( ")" ) ;
@@ -2815,10 +2829,9 @@ function parsePrimaryExpression() {
2815
2829
peek ( ) ;
2816
2830
} else if ( type === Token . Template ) {
2817
2831
return parseTemplateLiteral ( ) ;
2818
- } else {
2832
+ } else if ( ! expr ) {
2819
2833
throwUnexpected ( lex ( ) ) ;
2820
2834
}
2821
-
2822
2835
return markerApply ( marker , expr ) ;
2823
2836
}
2824
2837
@@ -3170,11 +3183,89 @@ function parseConditionalExpression() {
3170
3183
return expr ;
3171
3184
}
3172
3185
3186
+ // [ES6] 14.2 Arrow Function
3187
+
3188
+ function parseConciseBody ( ) {
3189
+ if ( match ( "{" ) ) {
3190
+ return parseFunctionSourceElements ( ) ;
3191
+ }
3192
+ return parseAssignmentExpression ( ) ;
3193
+ }
3194
+
3195
+ function reinterpretAsCoverFormalsList ( expressions ) {
3196
+ var i , len , param , params , defaults , defaultCount , options , rest ;
3197
+
3198
+ params = [ ] ;
3199
+ defaults = [ ] ;
3200
+ defaultCount = 0 ;
3201
+ rest = null ;
3202
+ options = {
3203
+ paramSet : { }
3204
+ } ;
3205
+
3206
+ for ( i = 0 , len = expressions . length ; i < len ; i += 1 ) {
3207
+ param = expressions [ i ] ;
3208
+ if ( param . type === astNodeTypes . Identifier ) {
3209
+ params . push ( param ) ;
3210
+ defaults . push ( null ) ;
3211
+ validateParam ( options , param , param . name ) ;
3212
+ } else if ( param . type === astNodeTypes . AssignmentExpression ) {
3213
+ params . push ( param . left ) ;
3214
+ defaults . push ( param . right ) ;
3215
+ ++ defaultCount ;
3216
+ validateParam ( options , param . left , param . left . name ) ;
3217
+ } else {
3218
+ return null ;
3219
+ }
3220
+ }
3221
+
3222
+ if ( options . message === Messages . StrictParamDupe ) {
3223
+ throwError (
3224
+ strict ? options . stricted : options . firstRestricted ,
3225
+ options . message
3226
+ ) ;
3227
+ }
3228
+
3229
+ // must be here so it's not an array of [null, null]
3230
+ if ( defaultCount === 0 ) {
3231
+ defaults = [ ] ;
3232
+ }
3233
+
3234
+ return {
3235
+ params : params ,
3236
+ defaults : defaults ,
3237
+ rest : rest ,
3238
+ stricted : options . stricted ,
3239
+ firstRestricted : options . firstRestricted ,
3240
+ message : options . message
3241
+ } ;
3242
+ }
3243
+
3244
+ function parseArrowFunctionExpression ( options , marker ) {
3245
+ var previousStrict , body ;
3246
+
3247
+ expect ( "=>" ) ;
3248
+ previousStrict = strict ;
3249
+
3250
+ body = parseConciseBody ( ) ;
3251
+
3252
+ if ( strict && options . firstRestricted ) {
3253
+ throwError ( options . firstRestricted , options . message ) ;
3254
+ }
3255
+ if ( strict && options . stricted ) {
3256
+ throwErrorTolerant ( options . stricted , options . message ) ;
3257
+ }
3258
+
3259
+ strict = previousStrict ;
3260
+ return markerApply ( marker , astNodeFactory . createArrowFunctionExpression ( options . params , options . defaults , body , body . type !== astNodeTypes . BlockStatement ) ) ;
3261
+ }
3262
+
3173
3263
// 11.13 Assignment Operators
3174
3264
3175
3265
function parseAssignmentExpression ( ) {
3176
- var token , left , right , node ,
3266
+ var token , left , right , list , node , params ,
3177
3267
marker ,
3268
+ oldParenthesisCount = state . parenthesisCount ,
3178
3269
allowGenerators = extra . ecmaFeatures . generators ;
3179
3270
3180
3271
// Note that 'yield' is treated as a keyword in strict mode, but a
@@ -3185,10 +3276,41 @@ function parseAssignmentExpression() {
3185
3276
}
3186
3277
3187
3278
marker = markerCreate ( ) ;
3188
- token = lookahead ;
3189
3279
3280
+ if ( match ( "(" ) ) {
3281
+ token = lookahead2 ( ) ;
3282
+ if ( token . value === ")" && token . type === Token . Punctuator ) {
3283
+ params = parseParams ( ) ;
3284
+ list = {
3285
+ defaults : [ ] ,
3286
+ params : params . params
3287
+ } ;
3288
+ return markerApply ( marker , parseArrowFunctionExpression ( list , marker ) ) ;
3289
+ }
3290
+ }
3291
+
3292
+ // revert to the previous lookahead style object
3293
+ token = lookahead ;
3190
3294
node = left = parseConditionalExpression ( ) ;
3191
3295
3296
+ if ( node === PlaceHolders . ArrowParameterPlaceHolder || match ( "=>" ) ) {
3297
+ if ( state . parenthesisCount === oldParenthesisCount ||
3298
+ state . parenthesisCount === ( oldParenthesisCount + 1 ) ) {
3299
+ if ( node . type === astNodeTypes . Identifier ) {
3300
+ list = reinterpretAsCoverFormalsList ( [ node ] ) ;
3301
+ } else if ( node . type === astNodeTypes . AssignmentExpression ) {
3302
+ list = reinterpretAsCoverFormalsList ( [ node ] ) ;
3303
+ } else if ( node . type === astNodeTypes . SequenceExpression ) {
3304
+ list = reinterpretAsCoverFormalsList ( node . expressions ) ;
3305
+ } else if ( node === PlaceHolders . ArrowParameterPlaceHolder ) {
3306
+ list = reinterpretAsCoverFormalsList ( [ ] ) ;
3307
+ }
3308
+ if ( list ) {
3309
+ return parseArrowFunctionExpression ( list , marker ) ;
3310
+ }
3311
+ }
3312
+ }
3313
+
3192
3314
if ( matchAssign ( ) ) {
3193
3315
// LeftHandSideExpression
3194
3316
if ( ! isLeftHandSide ( left ) ) {
@@ -3939,7 +4061,7 @@ function parseStatement() {
3939
4061
3940
4062
function parseFunctionSourceElements ( ) {
3941
4063
var sourceElement , sourceElements = [ ] , token , directive , firstRestricted ,
3942
- oldLabelSet , oldInIteration , oldInSwitch , oldInFunctionBody ,
4064
+ oldLabelSet , oldInIteration , oldInSwitch , oldInFunctionBody , oldParenthesisCount ,
3943
4065
marker = markerCreate ( ) ;
3944
4066
3945
4067
expect ( "{" ) ;
@@ -3973,6 +4095,7 @@ function parseFunctionSourceElements() {
3973
4095
oldInIteration = state . inIteration ;
3974
4096
oldInSwitch = state . inSwitch ;
3975
4097
oldInFunctionBody = state . inFunctionBody ;
4098
+ oldParenthesisCount = state . parenthesizedCount ;
3976
4099
3977
4100
state . labelSet = { } ;
3978
4101
state . inIteration = false ;
@@ -4000,10 +4123,37 @@ function parseFunctionSourceElements() {
4000
4123
state . inIteration = oldInIteration ;
4001
4124
state . inSwitch = oldInSwitch ;
4002
4125
state . inFunctionBody = oldInFunctionBody ;
4126
+ state . parenthesizedCount = oldParenthesisCount ;
4003
4127
4004
4128
return markerApply ( marker , astNodeFactory . createBlockStatement ( sourceElements ) ) ;
4005
4129
}
4006
4130
4131
+ function validateParam ( options , param , name ) {
4132
+ var key = "$" + name ;
4133
+ if ( strict ) {
4134
+ if ( syntax . isRestrictedWord ( name ) ) {
4135
+ options . stricted = param ;
4136
+ options . message = Messages . StrictParamName ;
4137
+ }
4138
+ if ( Object . prototype . hasOwnProperty . call ( options . paramSet , key ) ) {
4139
+ options . stricted = param ;
4140
+ options . message = Messages . StrictParamDupe ;
4141
+ }
4142
+ } else if ( ! options . firstRestricted ) {
4143
+ if ( syntax . isRestrictedWord ( name ) ) {
4144
+ options . firstRestricted = param ;
4145
+ options . message = Messages . StrictParamName ;
4146
+ } else if ( syntax . isStrictModeReservedWord ( name ) ) {
4147
+ options . firstRestricted = param ;
4148
+ options . message = Messages . StrictReservedWord ;
4149
+ } else if ( Object . prototype . hasOwnProperty . call ( options . paramSet , key ) ) {
4150
+ options . firstRestricted = param ;
4151
+ options . message = Messages . StrictParamDupe ;
4152
+ }
4153
+ }
4154
+ options . paramSet [ key ] = true ;
4155
+ }
4156
+
4007
4157
function parseParams ( firstRestricted ) {
4008
4158
var param , params = [ ] , defaults = [ ] , defaultCount = 0 , token , stricted , paramSet , key , message , def ,
4009
4159
allowDefaultParams = extra . ecmaFeatures . defaultParams ;
@@ -4349,6 +4499,7 @@ function tokenize(code, options) {
4349
4499
state = {
4350
4500
allowIn : true ,
4351
4501
labelSet : { } ,
4502
+ parenthesisCount : 0 ,
4352
4503
inFunctionBody : false ,
4353
4504
inIteration : false ,
4354
4505
inSwitch : false ,
@@ -4453,6 +4604,7 @@ function parse(code, options) {
4453
4604
state = {
4454
4605
allowIn : true ,
4455
4606
labelSet : { } ,
4607
+ parenthesisCount : 0 ,
4456
4608
inFunctionBody : false ,
4457
4609
inIteration : false ,
4458
4610
inSwitch : false ,
0 commit comments