esperanto-source 0.6.17.1 → 0.6.17.2

Sign up to get free protection for your applications and to get access to all the features.
data/vendor/acorn.js CHANGED
@@ -28,7 +28,7 @@
28
28
  })(this, function(exports) {
29
29
  "use strict";
30
30
 
31
- exports.version = "0.11.0";
31
+ exports.version = "0.12.0";
32
32
 
33
33
  // The main exported interface (under `self.acorn` when in the
34
34
  // browser) is a `parse` function that takes a code string and
@@ -74,6 +74,9 @@
74
74
  // When enabled, import/export statements are not constrained to
75
75
  // appearing at the top of the program.
76
76
  allowImportExportEverywhere: false,
77
+ // When enabled, hashbang directive in the beginning of file
78
+ // is allowed and treated as a line comment.
79
+ allowHashBang: false,
77
80
  // When `locations` is on, `loc` properties holding objects with
78
81
  // `start` and `end` properties in `{line, column}` form (with
79
82
  // line being 1-based and column 0-based) will be attached to the
@@ -197,9 +200,6 @@
197
200
  if (options.locations) {
198
201
  this.loc = new SourceLocation();
199
202
  this.loc.end = tokEndLoc;
200
- // TODO: remove in next major release
201
- this.startLoc = tokStartLoc;
202
- this.endLoc = tokEndLoc;
203
203
  }
204
204
  if (options.ranges)
205
205
  this.range = [tokStart, tokEnd];
@@ -220,12 +220,12 @@
220
220
  initTokenState();
221
221
  skipSpace();
222
222
 
223
- function getToken(forceRegexp) {
223
+ function getToken() {
224
224
  lastEnd = tokEnd;
225
- readToken(forceRegexp);
225
+ readToken();
226
226
  return new Token();
227
227
  }
228
- getToken.jumpTo = function(pos, reAllowed) {
228
+ getToken.jumpTo = function(pos, exprAllowed) {
229
229
  tokPos = pos;
230
230
  if (options.locations) {
231
231
  tokCurLine = 1;
@@ -236,12 +236,23 @@
236
236
  tokLineStart = match.index + match[0].length;
237
237
  }
238
238
  }
239
- tokRegexpAllowed = reAllowed;
239
+ tokExprAllowed = !!exprAllowed;
240
240
  skipSpace();
241
241
  };
242
- getToken.noRegexp = function() {
243
- tokRegexpAllowed = false;
244
- };
242
+ getToken.current = function() { return new Token(); };
243
+ if (typeof Symbol !== 'undefined') {
244
+ getToken[Symbol.iterator] = function () {
245
+ return {
246
+ next: function () {
247
+ var token = getToken();
248
+ return {
249
+ done: token.type === _eof,
250
+ value: token
251
+ };
252
+ }
253
+ };
254
+ };
255
+ }
245
256
  getToken.options = options;
246
257
  return getToken;
247
258
  };
@@ -274,12 +285,13 @@
274
285
 
275
286
  // Internal state for the tokenizer. To distinguish between division
276
287
  // operators and regular expressions, it remembers whether the last
277
- // token was one that is allowed to be followed by an expression.
278
- // (If it is, a slash is probably a regexp, if it isn't it's a
279
- // division operator. See the `parseStatement` function for a
280
- // caveat.)
288
+ // token was one that is allowed to be followed by an expression. In
289
+ // some cases, notably after ')' or '}' tokens, the situation
290
+ // depends on the context before the matching opening bracket, so
291
+ // tokContext keeps a stack of information about current bracketed
292
+ // forms.
281
293
 
282
- var tokRegexpAllowed;
294
+ var tokContext, tokExprAllowed;
283
295
 
284
296
  // When `options.locations` is true, these are used to keep
285
297
  // track of the current line, and know when a new line has been
@@ -300,22 +312,10 @@
300
312
 
301
313
  var inFunction, inGenerator, labels, strict;
302
314
 
303
- // This counter is used for checking that arrow expressions did
304
- // not contain nested parentheses in argument list.
305
-
306
- var metParenL;
307
-
308
- // This is used by the tokenizer to track the template strings it is
309
- // inside, and count the amount of open braces seen inside them, to
310
- // be able to switch back to a template token when the } to match ${
311
- // is encountered. It will hold an array of integers.
312
-
313
- var templates;
314
-
315
315
  function initParserState() {
316
316
  lastStart = lastEnd = tokPos;
317
317
  if (options.locations) lastEndLoc = curPosition();
318
- inFunction = inGenerator = strict = false;
318
+ inFunction = inGenerator = false;
319
319
  labels = [];
320
320
  skipSpace();
321
321
  readToken();
@@ -413,8 +413,9 @@
413
413
  var _braceR = {type: "}"}, _parenL = {type: "(", beforeExpr: true}, _parenR = {type: ")"};
414
414
  var _comma = {type: ",", beforeExpr: true}, _semi = {type: ";", beforeExpr: true};
415
415
  var _colon = {type: ":", beforeExpr: true}, _dot = {type: "."}, _question = {type: "?", beforeExpr: true};
416
- var _arrow = {type: "=>", beforeExpr: true}, _template = {type: "template"}, _templateContinued = {type: "templateContinued"};
417
- var _ellipsis = {type: "...", prefix: true, beforeExpr: true};
416
+ var _arrow = {type: "=>", beforeExpr: true}, _template = {type: "template"};
417
+ var _ellipsis = {type: "...", beforeExpr: true};
418
+ var _backQuote = {type: "`"}, _dollarBraceL = {type: "${", beforeExpr: true};
418
419
 
419
420
  // Operators. These carry several kinds of properties to help the
420
421
  // parser use them properly (the presence of these properties is
@@ -456,8 +457,8 @@
456
457
  parenL: _parenL, parenR: _parenR, comma: _comma, semi: _semi, colon: _colon,
457
458
  dot: _dot, ellipsis: _ellipsis, question: _question, slash: _slash, eq: _eq,
458
459
  name: _name, eof: _eof, num: _num, regexp: _regexp, string: _string,
459
- arrow: _arrow, template: _template, templateContinued: _templateContinued, star: _star,
460
- assign: _assign};
460
+ arrow: _arrow, template: _template, star: _star, assign: _assign,
461
+ backQuote: _backQuote, dollarBraceL: _dollarBraceL};
461
462
  for (var kw in keywordTypes) exports.tokTypes["_" + kw] = keywordTypes[kw];
462
463
 
463
464
  // This is a trick taken from Esprima. It turns out that, on
@@ -595,7 +596,7 @@
595
596
 
596
597
  Position.prototype.offset = function(n) {
597
598
  return new Position(this.line, this.column + n);
598
- }
599
+ };
599
600
 
600
601
  function curPosition() {
601
602
  return new Position(tokCurLine, tokPos - tokLineStart);
@@ -612,25 +613,95 @@
612
613
  tokCurLine = 1;
613
614
  tokPos = tokLineStart = 0;
614
615
  }
615
- tokRegexpAllowed = true;
616
- metParenL = 0;
617
- templates = [];
616
+ tokType = _eof;
617
+ tokContext = [b_stat];
618
+ tokExprAllowed = true;
619
+ strict = false;
620
+ if (tokPos === 0 && options.allowHashBang && input.slice(0, 2) === '#!') {
621
+ skipLineComment(2);
622
+ }
623
+ }
624
+
625
+ // The algorithm used to determine whether a regexp can appear at a
626
+ // given point in the program is loosely based on sweet.js' approach.
627
+ // See https://github.com/mozilla/sweet.js/wiki/design
628
+
629
+ var b_stat = {token: "{", isExpr: false}, b_expr = {token: "{", isExpr: true}, b_tmpl = {token: "${", isExpr: true};
630
+ var p_stat = {token: "(", isExpr: false}, p_expr = {token: "(", isExpr: true};
631
+ var q_tmpl = {token: "`", isExpr: true}, f_expr = {token: "function", isExpr: true};
632
+
633
+ function curTokContext() {
634
+ return tokContext[tokContext.length - 1];
635
+ }
636
+
637
+ function braceIsBlock(prevType) {
638
+ var parent;
639
+ if (prevType === _colon && (parent = curTokContext()).token == "{")
640
+ return !parent.isExpr;
641
+ if (prevType === _return)
642
+ return newline.test(input.slice(lastEnd, tokStart));
643
+ if (prevType === _else || prevType === _semi || prevType === _eof)
644
+ return true;
645
+ if (prevType == _braceL)
646
+ return curTokContext() === b_stat;
647
+ return !tokExprAllowed;
618
648
  }
619
649
 
620
650
  // Called at the end of every token. Sets `tokEnd`, `tokVal`, and
621
- // `tokRegexpAllowed`, and skips the space after the token, so that
622
- // the next one's `tokStart` will point at the right position.
651
+ // maintains `tokContext` and `tokExprAllowed`, and skips the space
652
+ // after the token, so that the next one's `tokStart` will point at
653
+ // the right position.
623
654
 
624
- function finishToken(type, val, shouldSkipSpace) {
655
+ function finishToken(type, val) {
625
656
  tokEnd = tokPos;
626
657
  if (options.locations) tokEndLoc = curPosition();
658
+ var prevType = tokType, preserveSpace = false;
627
659
  tokType = type;
628
- if (shouldSkipSpace !== false) skipSpace();
629
660
  tokVal = val;
630
- tokRegexpAllowed = type.beforeExpr;
631
- if (options.onToken) {
632
- options.onToken(new Token());
661
+
662
+ // Update context info
663
+ if (type === _parenR || type === _braceR) {
664
+ var out = tokContext.pop();
665
+ if (out === b_tmpl) {
666
+ preserveSpace = true;
667
+ } else if (out === b_stat && curTokContext() === f_expr) {
668
+ tokContext.pop();
669
+ tokExprAllowed = false;
670
+ } else {
671
+ tokExprAllowed = !(out && out.isExpr);
672
+ }
673
+ } else if (type === _braceL) {
674
+ tokContext.push(braceIsBlock(prevType) ? b_stat : b_expr);
675
+ tokExprAllowed = true;
676
+ } else if (type === _dollarBraceL) {
677
+ tokContext.push(b_tmpl);
678
+ tokExprAllowed = true;
679
+ } else if (type == _parenL) {
680
+ var statementParens = prevType === _if || prevType === _for || prevType === _with || prevType === _while;
681
+ tokContext.push(statementParens ? p_stat : p_expr);
682
+ tokExprAllowed = true;
683
+ } else if (type == _incDec) {
684
+ // tokExprAllowed stays unchanged
685
+ } else if (type.keyword && prevType == _dot) {
686
+ tokExprAllowed = false;
687
+ } else if (type == _function) {
688
+ if (curTokContext() !== b_stat) {
689
+ tokContext.push(f_expr);
690
+ }
691
+ tokExprAllowed = false;
692
+ } else if (type === _backQuote) {
693
+ if (curTokContext() === q_tmpl) {
694
+ tokContext.pop();
695
+ } else {
696
+ tokContext.push(q_tmpl);
697
+ preserveSpace = true;
698
+ }
699
+ tokExprAllowed = false;
700
+ } else {
701
+ tokExprAllowed = type.beforeExpr;
633
702
  }
703
+
704
+ if (!preserveSpace) skipSpace();
634
705
  }
635
706
 
636
707
  function skipBlockComment() {
@@ -716,9 +787,6 @@
716
787
  //
717
788
  // All in the name of speed.
718
789
  //
719
- // The `forceRegexp` parameter is used in the one case where the
720
- // `tokRegexpAllowed` trick does not work. See `parseStatement`.
721
-
722
790
  function readToken_dot() {
723
791
  var next = input.charCodeAt(tokPos + 1);
724
792
  if (next >= 48 && next <= 57) return readNumber(true);
@@ -734,7 +802,7 @@
734
802
 
735
803
  function readToken_slash() { // '/'
736
804
  var next = input.charCodeAt(tokPos + 1);
737
- if (tokRegexpAllowed) {++tokPos; return readRegexp();}
805
+ if (tokExprAllowed) {++tokPos; return readRegexp();}
738
806
  if (next === 61) return finishOp(_assign, 2);
739
807
  return finishOp(_slash, 1);
740
808
  }
@@ -818,23 +886,17 @@
818
886
  case 44: ++tokPos; return finishToken(_comma);
819
887
  case 91: ++tokPos; return finishToken(_bracketL);
820
888
  case 93: ++tokPos; return finishToken(_bracketR);
821
- case 123:
822
- ++tokPos;
823
- if (templates.length) ++templates[templates.length - 1];
824
- return finishToken(_braceL);
825
- case 125:
826
- ++tokPos;
827
- if (templates.length && --templates[templates.length - 1] === 0)
828
- return readTemplateString(_templateContinued);
829
- else
830
- return finishToken(_braceR);
889
+ case 123: ++tokPos; return finishToken(_braceL);
890
+ case 125: ++tokPos; return finishToken(_braceR);
831
891
  case 58: ++tokPos; return finishToken(_colon);
832
892
  case 63: ++tokPos; return finishToken(_question);
833
893
 
834
894
  case 96: // '`'
835
895
  if (options.ecmaVersion >= 6) {
836
896
  ++tokPos;
837
- return readTemplateString(_template);
897
+ return finishToken(_backQuote);
898
+ } else {
899
+ return false;
838
900
  }
839
901
 
840
902
  case 48: // '0'
@@ -886,13 +948,15 @@
886
948
  return false;
887
949
  }
888
950
 
889
- function readToken(forceRegexp) {
890
- if (!forceRegexp) tokStart = tokPos;
891
- else tokPos = tokStart + 1;
951
+ function readToken() {
952
+ tokStart = tokPos;
892
953
  if (options.locations) tokStartLoc = curPosition();
893
- if (forceRegexp) return readRegexp();
894
954
  if (tokPos >= inputLen) return finishToken(_eof);
895
955
 
956
+ if (curTokContext() === q_tmpl) {
957
+ return readTmplToken();
958
+ }
959
+
896
960
  var code = input.charCodeAt(tokPos);
897
961
 
898
962
  // Identifier or keyword. '\uXXXX' sequences are allowed in
@@ -1056,55 +1120,64 @@
1056
1120
  }
1057
1121
 
1058
1122
  function readString(quote) {
1059
- ++tokPos;
1060
- var out = "";
1123
+ var out = "", chunkStart = ++tokPos;
1061
1124
  for (;;) {
1062
1125
  if (tokPos >= inputLen) raise(tokStart, "Unterminated string constant");
1063
1126
  var ch = input.charCodeAt(tokPos);
1064
- if (ch === quote) {
1065
- ++tokPos;
1066
- return finishToken(_string, out);
1067
- }
1127
+ if (ch === quote) break;
1068
1128
  if (ch === 92) { // '\'
1129
+ out += input.slice(chunkStart, tokPos);
1069
1130
  out += readEscapedChar();
1131
+ chunkStart = tokPos;
1070
1132
  } else {
1133
+ if (isNewLine(ch)) raise(tokStart, "Unterminated string constant");
1071
1134
  ++tokPos;
1072
- if (newline.test(String.fromCharCode(ch))) {
1073
- raise(tokStart, "Unterminated string constant");
1074
- }
1075
- out += String.fromCharCode(ch); // '\'
1076
1135
  }
1077
1136
  }
1137
+ out += input.slice(chunkStart, tokPos++);
1138
+ return finishToken(_string, out);
1078
1139
  }
1079
1140
 
1080
- function readTemplateString(type) {
1081
- if (type == _templateContinued) templates.pop();
1082
- var out = "", start = tokPos;;
1141
+ // Reads template string tokens.
1142
+
1143
+ function readTmplToken() {
1144
+ var out = "", chunkStart = tokPos;
1083
1145
  for (;;) {
1084
1146
  if (tokPos >= inputLen) raise(tokStart, "Unterminated template");
1085
- var ch = input.charAt(tokPos);
1086
- if (ch === "`" || ch === "$" && input.charCodeAt(tokPos + 1) === 123) { // '`', '${'
1087
- var raw = input.slice(start, tokPos);
1088
- ++tokPos;
1089
- if (ch == "$") { ++tokPos; templates.push(1); }
1090
- return finishToken(type, {cooked: out, raw: raw});
1147
+ var ch = input.charCodeAt(tokPos);
1148
+ if (ch === 96 || ch === 36 && input.charCodeAt(tokPos + 1) === 123) { // '`', '${'
1149
+ if (tokPos === tokStart && tokType === _template) {
1150
+ if (ch === 36) {
1151
+ tokPos += 2;
1152
+ return finishToken(_dollarBraceL);
1153
+ } else {
1154
+ ++tokPos;
1155
+ return finishToken(_backQuote);
1156
+ }
1157
+ }
1158
+ out += input.slice(chunkStart, tokPos);
1159
+ return finishToken(_template, out);
1091
1160
  }
1092
-
1093
- if (ch === "\\") { // '\'
1161
+ if (ch === 92) { // '\'
1162
+ out += input.slice(chunkStart, tokPos);
1094
1163
  out += readEscapedChar();
1095
- } else {
1164
+ chunkStart = tokPos;
1165
+ } else if (isNewLine(ch)) {
1166
+ out += input.slice(chunkStart, tokPos);
1096
1167
  ++tokPos;
1097
- if (newline.test(ch)) {
1098
- if (ch === "\r" && input.charCodeAt(tokPos) === 10) {
1099
- ++tokPos;
1100
- ch = "\n";
1101
- }
1102
- if (options.locations) {
1103
- ++tokCurLine;
1104
- tokLineStart = tokPos;
1105
- }
1168
+ if (ch === 13 && input.charCodeAt(tokPos) === 10) {
1169
+ ++tokPos;
1170
+ out += "\n";
1171
+ } else {
1172
+ out += String.fromCharCode(ch);
1106
1173
  }
1107
- out += ch;
1174
+ if (options.locations) {
1175
+ ++tokCurLine;
1176
+ tokLineStart = tokPos;
1177
+ }
1178
+ chunkStart = tokPos;
1179
+ } else {
1180
+ ++tokPos;
1108
1181
  }
1109
1182
  }
1110
1183
  }
@@ -1159,20 +1232,19 @@
1159
1232
  // Read an identifier, and return it as a string. Sets `containsEsc`
1160
1233
  // to whether the word contained a '\u' escape.
1161
1234
  //
1162
- // Only builds up the word character-by-character when it actually
1163
- // containeds an escape, as a micro-optimization.
1235
+ // Incrementally adds only escaped chars, adding other chunks as-is
1236
+ // as a micro-optimization.
1164
1237
 
1165
1238
  function readWord1() {
1166
1239
  containsEsc = false;
1167
- var word, first = true, start = tokPos;
1168
- for (;;) {
1240
+ var word = "", first = true, chunkStart = tokPos;
1241
+ while (tokPos < inputLen) {
1169
1242
  var ch = input.charCodeAt(tokPos);
1170
1243
  if (isIdentifierChar(ch)) {
1171
- if (containsEsc) word += input.charAt(tokPos);
1172
1244
  ++tokPos;
1173
1245
  } else if (ch === 92) { // "\"
1174
- if (!containsEsc) word = input.slice(start, tokPos);
1175
1246
  containsEsc = true;
1247
+ word += input.slice(chunkStart, tokPos);
1176
1248
  if (input.charCodeAt(++tokPos) != 117) // "u"
1177
1249
  raise(tokPos, "Expecting Unicode escape sequence \\uXXXX");
1178
1250
  ++tokPos;
@@ -1182,12 +1254,13 @@
1182
1254
  if (!(first ? isIdentifierStart(esc) : isIdentifierChar(esc)))
1183
1255
  raise(tokPos - 4, "Invalid Unicode escape");
1184
1256
  word += escStr;
1257
+ chunkStart = tokPos;
1185
1258
  } else {
1186
1259
  break;
1187
1260
  }
1188
1261
  first = false;
1189
1262
  }
1190
- return containsEsc ? word : input.slice(start, tokPos);
1263
+ return word + input.slice(chunkStart, tokPos);
1191
1264
  }
1192
1265
 
1193
1266
  // Read an identifier or keyword token. Will check for reserved
@@ -1226,17 +1299,21 @@
1226
1299
  // Continue to the next token.
1227
1300
 
1228
1301
  function next() {
1302
+ if (options.onToken)
1303
+ options.onToken(new Token());
1304
+
1229
1305
  lastStart = tokStart;
1230
1306
  lastEnd = tokEnd;
1231
1307
  lastEndLoc = tokEndLoc;
1232
1308
  readToken();
1233
1309
  }
1234
1310
 
1235
- // Enter strict mode. Re-reads the next token to please pedantic
1236
- // tests ("use strict"; 010; -- should fail).
1311
+ // Enter strict mode. Re-reads the next number or string to
1312
+ // please pedantic tests ("use strict"; 010; -- should fail).
1237
1313
 
1238
1314
  function setStrict(strct) {
1239
1315
  strict = strct;
1316
+ if (tokType !== _num && tokType !== _string) return;
1240
1317
  tokPos = tokStart;
1241
1318
  if (options.locations) {
1242
1319
  while (tokPos < tokLineStart) {
@@ -1311,6 +1388,8 @@
1311
1388
  return node;
1312
1389
  }
1313
1390
 
1391
+ // Finish node at given position
1392
+
1314
1393
  function finishNodeAt(node, type, pos) {
1315
1394
  if (options.locations) { node.loc.end = pos[1]; pos = pos[0]; }
1316
1395
  node.type = type;
@@ -1339,6 +1418,24 @@
1339
1418
  }
1340
1419
  }
1341
1420
 
1421
+ // Tests whether parsed token is a contextual keyword.
1422
+
1423
+ function isContextual(name) {
1424
+ return tokType === _name && tokVal === name;
1425
+ }
1426
+
1427
+ // Consumes contextual keyword if possible.
1428
+
1429
+ function eatContextual(name) {
1430
+ return tokVal === name && eat(_name);
1431
+ }
1432
+
1433
+ // Asserts that following token is given contextual keyword.
1434
+
1435
+ function expectContextual(name) {
1436
+ if (!eatContextual(name)) unexpected();
1437
+ }
1438
+
1342
1439
  // Test whether a semicolon can be inserted at the current position.
1343
1440
 
1344
1441
  function canInsertSemicolon() {
@@ -1371,53 +1468,139 @@
1371
1468
  function has(obj, propName) {
1372
1469
  return Object.prototype.hasOwnProperty.call(obj, propName);
1373
1470
  }
1471
+
1374
1472
  // Convert existing expression atom to assignable pattern
1375
1473
  // if possible.
1376
1474
 
1377
- function toAssignable(node, allowSpread, checkType) {
1475
+ function toAssignable(node, isBinding) {
1378
1476
  if (options.ecmaVersion >= 6 && node) {
1379
1477
  switch (node.type) {
1380
1478
  case "Identifier":
1381
- case "MemberExpression":
1479
+ case "ObjectPattern":
1480
+ case "ArrayPattern":
1481
+ case "AssignmentPattern":
1382
1482
  break;
1383
1483
 
1384
1484
  case "ObjectExpression":
1385
1485
  node.type = "ObjectPattern";
1386
1486
  for (var i = 0; i < node.properties.length; i++) {
1387
1487
  var prop = node.properties[i];
1388
- if (prop.kind !== "init") unexpected(prop.key.start);
1389
- toAssignable(prop.value, false, checkType);
1488
+ if (prop.kind !== "init") raise(prop.key.start, "Object pattern can't contain getter or setter");
1489
+ toAssignable(prop.value, isBinding);
1390
1490
  }
1391
1491
  break;
1392
1492
 
1393
1493
  case "ArrayExpression":
1394
1494
  node.type = "ArrayPattern";
1395
- for (var i = 0, lastI = node.elements.length - 1; i <= lastI; i++) {
1396
- toAssignable(node.elements[i], i === lastI, checkType);
1397
- }
1495
+ toAssignableList(node.elements, isBinding);
1398
1496
  break;
1399
1497
 
1400
- case "SpreadElement":
1401
- if (allowSpread) {
1402
- toAssignable(node.argument, false, checkType);
1403
- checkSpreadAssign(node.argument);
1498
+ case "AssignmentExpression":
1499
+ if (node.operator === "=") {
1500
+ node.type = "AssignmentPattern";
1404
1501
  } else {
1405
- unexpected(node.start);
1502
+ raise(node.left.end, "Only '=' operator can be used for specifying default value.");
1406
1503
  }
1407
1504
  break;
1408
1505
 
1506
+ case "MemberExpression":
1507
+ if (!isBinding) break;
1508
+
1409
1509
  default:
1410
- if (checkType) unexpected(node.start);
1510
+ raise(node.start, "Assigning to rvalue");
1411
1511
  }
1412
1512
  }
1413
1513
  return node;
1414
1514
  }
1415
1515
 
1416
- // Checks if node can be assignable spread argument.
1516
+ // Convert list of expression atoms to binding list.
1517
+
1518
+ function toAssignableList(exprList, isBinding) {
1519
+ if (exprList.length) {
1520
+ for (var i = 0; i < exprList.length - 1; i++) {
1521
+ toAssignable(exprList[i], isBinding);
1522
+ }
1523
+ var last = exprList[exprList.length - 1];
1524
+ switch (last.type) {
1525
+ case "RestElement":
1526
+ break;
1527
+ case "SpreadElement":
1528
+ last.type = "RestElement";
1529
+ var arg = last.argument;
1530
+ toAssignable(arg, isBinding);
1531
+ if (arg.type !== "Identifier" && arg.type !== "MemberExpression" && arg.type !== "ArrayPattern")
1532
+ unexpected(arg.start);
1533
+ break;
1534
+ default:
1535
+ toAssignable(last, isBinding);
1536
+ }
1537
+ }
1538
+ return exprList;
1539
+ }
1540
+
1541
+ // Parses spread element.
1542
+
1543
+ function parseSpread(refShorthandDefaultPos) {
1544
+ var node = startNode();
1545
+ next();
1546
+ node.argument = parseMaybeAssign(refShorthandDefaultPos);
1547
+ return finishNode(node, "SpreadElement");
1548
+ }
1549
+
1550
+ function parseRest() {
1551
+ var node = startNode();
1552
+ next();
1553
+ node.argument = tokType === _name || tokType === _bracketL ? parseBindingAtom() : unexpected();
1554
+ return finishNode(node, "RestElement");
1555
+ }
1556
+
1557
+ // Parses lvalue (assignable) atom.
1558
+
1559
+ function parseBindingAtom() {
1560
+ if (options.ecmaVersion < 6) return parseIdent();
1561
+ switch (tokType) {
1562
+ case _name:
1563
+ return parseIdent();
1564
+
1565
+ case _bracketL:
1566
+ var node = startNode();
1567
+ next();
1568
+ node.elements = parseBindingList(_bracketR, true);
1569
+ return finishNode(node, "ArrayPattern");
1570
+
1571
+ case _braceL:
1572
+ return parseObj(true);
1573
+
1574
+ default:
1575
+ unexpected();
1576
+ }
1577
+ }
1578
+
1579
+ function parseBindingList(close, allowEmpty) {
1580
+ var elts = [], first = true;
1581
+ while (!eat(close)) {
1582
+ first ? first = false : expect(_comma);
1583
+ if (tokType === _ellipsis) {
1584
+ elts.push(parseRest());
1585
+ expect(close);
1586
+ break;
1587
+ }
1588
+ elts.push(allowEmpty && tokType === _comma ? null : parseMaybeDefault());
1589
+ }
1590
+ return elts;
1591
+ }
1417
1592
 
1418
- function checkSpreadAssign(node) {
1419
- if (node.type !== "Identifier" && node.type !== "ArrayPattern")
1420
- unexpected(node.start);
1593
+ // Parses assignment pattern around given atom if possible.
1594
+
1595
+ function parseMaybeDefault(startPos, left) {
1596
+ startPos = startPos || storeCurrentPos();
1597
+ left = left || parseBindingAtom();
1598
+ if (!eat(_eq)) return left;
1599
+ var node = startNodeAt(startPos);
1600
+ node.operator = "=";
1601
+ node.left = left;
1602
+ node.right = parseMaybeAssign();
1603
+ return finishNode(node, "AssignmentPattern");
1421
1604
  }
1422
1605
 
1423
1606
  // Verify that argument names are not repeated, and it does not
@@ -1444,6 +1627,9 @@
1444
1627
  if (elem) checkFunctionParam(elem, nameHash);
1445
1628
  }
1446
1629
  break;
1630
+
1631
+ case "RestElement":
1632
+ return checkFunctionParam(param.argument, nameHash);
1447
1633
  }
1448
1634
  }
1449
1635
 
@@ -1483,14 +1669,12 @@
1483
1669
  switch (expr.type) {
1484
1670
  case "Identifier":
1485
1671
  if (strict && (isStrictBadIdWord(expr.name) || isStrictReservedWord(expr.name)))
1486
- raise(expr.start, isBinding
1487
- ? "Binding " + expr.name + " in strict mode"
1488
- : "Assigning to " + expr.name + " in strict mode"
1489
- );
1672
+ raise(expr.start, (isBinding ? "Binding " : "Assigning to ") + expr.name + " in strict mode");
1490
1673
  break;
1491
1674
 
1492
1675
  case "MemberExpression":
1493
- if (!isBinding) break;
1676
+ if (isBinding) raise(expr.start, "Binding to member expression");
1677
+ break;
1494
1678
 
1495
1679
  case "ObjectPattern":
1496
1680
  for (var i = 0; i < expr.properties.length; i++)
@@ -1504,7 +1688,12 @@
1504
1688
  }
1505
1689
  break;
1506
1690
 
1507
- case "SpreadElement":
1691
+ case "AssignmentPattern":
1692
+ checkLVal(expr.left);
1693
+ break;
1694
+
1695
+ case "RestElement":
1696
+ checkLVal(expr.argument);
1508
1697
  break;
1509
1698
 
1510
1699
  default:
@@ -1523,15 +1712,13 @@
1523
1712
  var first = true;
1524
1713
  if (!node.body) node.body = [];
1525
1714
  while (tokType !== _eof) {
1526
- var stmt = parseStatement(true);
1715
+ var stmt = parseStatement(true, true);
1527
1716
  node.body.push(stmt);
1528
1717
  if (first && isUseStrict(stmt)) setStrict(true);
1529
1718
  first = false;
1530
1719
  }
1531
1720
 
1532
- lastStart = tokStart;
1533
- lastEnd = tokEnd;
1534
- lastEndLoc = tokEndLoc;
1721
+ next();
1535
1722
  return finishNode(node, "Program");
1536
1723
  }
1537
1724
 
@@ -1544,10 +1731,7 @@
1544
1731
  // `if (foo) /blah/.exec(foo);`, where looking at the previous token
1545
1732
  // does not help.
1546
1733
 
1547
- function parseStatement(topLevel) {
1548
- if (tokType === _slash || tokType === _assign && tokVal == "/=")
1549
- readToken(true);
1550
-
1734
+ function parseStatement(declaration, topLevel) {
1551
1735
  var starttype = tokType, node = startNode();
1552
1736
 
1553
1737
  // Most types of statements are recognized by the keyword they
@@ -1559,14 +1743,19 @@
1559
1743
  case _debugger: return parseDebuggerStatement(node);
1560
1744
  case _do: return parseDoStatement(node);
1561
1745
  case _for: return parseForStatement(node);
1562
- case _function: return parseFunctionStatement(node);
1563
- case _class: return parseClass(node, true);
1746
+ case _function:
1747
+ if (!declaration && options.ecmaVersion >= 6) unexpected();
1748
+ return parseFunctionStatement(node);
1749
+ case _class:
1750
+ if (!declaration) unexpected();
1751
+ return parseClass(node, true);
1564
1752
  case _if: return parseIfStatement(node);
1565
1753
  case _return: return parseReturnStatement(node);
1566
1754
  case _switch: return parseSwitchStatement(node);
1567
1755
  case _throw: return parseThrowStatement(node);
1568
1756
  case _try: return parseTryStatement(node);
1569
- case _var: case _let: case _const: return parseVarStatement(node, starttype.keyword);
1757
+ case _let: case _const: if (!declaration) unexpected(); // NOTE: falls through to _var
1758
+ case _var: return parseVarStatement(node, starttype.keyword);
1570
1759
  case _while: return parseWhileStatement(node);
1571
1760
  case _with: return parseWithStatement(node);
1572
1761
  case _braceL: return parseBlock(); // no point creating a function for this
@@ -1622,7 +1811,7 @@
1622
1811
  function parseDoStatement(node) {
1623
1812
  next();
1624
1813
  labels.push(loopLabel);
1625
- node.body = parseStatement();
1814
+ node.body = parseStatement(false);
1626
1815
  labels.pop();
1627
1816
  expect(_while);
1628
1817
  node.test = parseParenExpression();
@@ -1651,15 +1840,19 @@
1651
1840
  next();
1652
1841
  parseVar(init, true, varKind);
1653
1842
  finishNode(init, "VariableDeclaration");
1654
- if ((tokType === _in || (options.ecmaVersion >= 6 && tokType === _name && tokVal === "of")) && init.declarations.length === 1 &&
1843
+ if ((tokType === _in || (options.ecmaVersion >= 6 && isContextual("of"))) && init.declarations.length === 1 &&
1655
1844
  !(isLet && init.declarations[0].init))
1656
1845
  return parseForIn(node, init);
1657
1846
  return parseFor(node, init);
1658
1847
  }
1659
- var init = parseExpression(false, true);
1660
- if (tokType === _in || (options.ecmaVersion >= 6 && tokType === _name && tokVal === "of")) {
1848
+ var refShorthandDefaultPos = {start: 0};
1849
+ var init = parseExpression(true, refShorthandDefaultPos);
1850
+ if (tokType === _in || (options.ecmaVersion >= 6 && isContextual("of"))) {
1851
+ toAssignable(init);
1661
1852
  checkLVal(init);
1662
1853
  return parseForIn(node, init);
1854
+ } else if (refShorthandDefaultPos.start) {
1855
+ unexpected(refShorthandDefaultPos.start);
1663
1856
  }
1664
1857
  return parseFor(node, init);
1665
1858
  }
@@ -1672,8 +1865,8 @@
1672
1865
  function parseIfStatement(node) {
1673
1866
  next();
1674
1867
  node.test = parseParenExpression();
1675
- node.consequent = parseStatement();
1676
- node.alternate = eat(_else) ? parseStatement() : null;
1868
+ node.consequent = parseStatement(false);
1869
+ node.alternate = eat(_else) ? parseStatement(false) : null;
1677
1870
  return finishNode(node, "IfStatement");
1678
1871
  }
1679
1872
 
@@ -1717,7 +1910,7 @@
1717
1910
  expect(_colon);
1718
1911
  } else {
1719
1912
  if (!cur) unexpected();
1720
- cur.consequent.push(parseStatement());
1913
+ cur.consequent.push(parseStatement(true));
1721
1914
  }
1722
1915
  }
1723
1916
  if (cur) finishNode(cur, "SwitchCase");
@@ -1743,9 +1936,8 @@
1743
1936
  var clause = startNode();
1744
1937
  next();
1745
1938
  expect(_parenL);
1746
- clause.param = parseIdent();
1747
- if (strict && isStrictBadIdWord(clause.param.name))
1748
- raise(clause.param.start, "Binding " + clause.param.name + " in strict mode");
1939
+ clause.param = parseBindingAtom();
1940
+ checkLVal(clause.param, true);
1749
1941
  expect(_parenR);
1750
1942
  clause.guard = null;
1751
1943
  clause.body = parseBlock();
@@ -1769,7 +1961,7 @@
1769
1961
  next();
1770
1962
  node.test = parseParenExpression();
1771
1963
  labels.push(loopLabel);
1772
- node.body = parseStatement();
1964
+ node.body = parseStatement(false);
1773
1965
  labels.pop();
1774
1966
  return finishNode(node, "WhileStatement");
1775
1967
  }
@@ -1778,7 +1970,7 @@
1778
1970
  if (strict) raise(tokStart, "'with' in strict mode");
1779
1971
  next();
1780
1972
  node.object = parseParenExpression();
1781
- node.body = parseStatement();
1973
+ node.body = parseStatement(false);
1782
1974
  return finishNode(node, "WithStatement");
1783
1975
  }
1784
1976
 
@@ -1792,7 +1984,7 @@
1792
1984
  if (labels[i].name === maybeName) raise(expr.start, "Label '" + maybeName + "' is already declared");
1793
1985
  var kind = tokType.isLoop ? "loop" : tokType === _switch ? "switch" : null;
1794
1986
  labels.push({name: maybeName, kind: kind});
1795
- node.body = parseStatement();
1987
+ node.body = parseStatement(true);
1796
1988
  labels.pop();
1797
1989
  node.label = expr;
1798
1990
  return finishNode(node, "LabeledStatement");
@@ -1823,7 +2015,7 @@
1823
2015
  node.body = [];
1824
2016
  expect(_braceL);
1825
2017
  while (!eat(_braceR)) {
1826
- var stmt = parseStatement();
2018
+ var stmt = parseStatement(true);
1827
2019
  node.body.push(stmt);
1828
2020
  if (first && allowStrict && isUseStrict(stmt)) {
1829
2021
  oldStrict = strict;
@@ -1846,7 +2038,7 @@
1846
2038
  expect(_semi);
1847
2039
  node.update = tokType === _parenR ? null : parseExpression();
1848
2040
  expect(_parenR);
1849
- node.body = parseStatement();
2041
+ node.body = parseStatement(false);
1850
2042
  labels.pop();
1851
2043
  return finishNode(node, "ForStatement");
1852
2044
  }
@@ -1860,7 +2052,7 @@
1860
2052
  node.left = init;
1861
2053
  node.right = parseExpression();
1862
2054
  expect(_parenR);
1863
- node.body = parseStatement();
2055
+ node.body = parseStatement(false);
1864
2056
  labels.pop();
1865
2057
  return finishNode(node, type);
1866
2058
  }
@@ -1872,9 +2064,9 @@
1872
2064
  node.kind = kind;
1873
2065
  for (;;) {
1874
2066
  var decl = startNode();
1875
- decl.id = options.ecmaVersion >= 6 ? toAssignable(parseExprAtom()) : parseIdent();
2067
+ decl.id = parseBindingAtom();
1876
2068
  checkLVal(decl.id, true);
1877
- decl.init = eat(_eq) ? parseExpression(true, noIn) : (kind === _const.keyword ? unexpected() : null);
2069
+ decl.init = eat(_eq) ? parseMaybeAssign(noIn) : (kind === _const.keyword ? unexpected() : null);
1878
2070
  node.declarations.push(finishNode(decl, "VariableDeclarator"));
1879
2071
  if (!eat(_comma)) break;
1880
2072
  }
@@ -1889,17 +2081,20 @@
1889
2081
  // and, *if* the syntactic construct they handle is present, wrap
1890
2082
  // the AST node that the inner parser gave them in another node.
1891
2083
 
1892
- // Parse a full expression. The arguments are used to forbid comma
1893
- // sequences (in argument lists, array literals, or object literals)
1894
- // or the `in` operator (in for loops initalization expressions).
2084
+ // Parse a full expression. The optional arguments are used to
2085
+ // forbid the `in` operator (in for loops initalization expressions)
2086
+ // and provide reference for storing '=' operator inside shorthand
2087
+ // property assignment in contexts where both object expression
2088
+ // and object pattern might appear (so it's possible to raise
2089
+ // delayed syntax error at correct position).
1895
2090
 
1896
- function parseExpression(noComma, noIn) {
2091
+ function parseExpression(noIn, refShorthandDefaultPos) {
1897
2092
  var start = storeCurrentPos();
1898
- var expr = parseMaybeAssign(noIn);
1899
- if (!noComma && tokType === _comma) {
2093
+ var expr = parseMaybeAssign(noIn, refShorthandDefaultPos);
2094
+ if (tokType === _comma) {
1900
2095
  var node = startNodeAt(start);
1901
2096
  node.expressions = [expr];
1902
- while (eat(_comma)) node.expressions.push(parseMaybeAssign(noIn));
2097
+ while (eat(_comma)) node.expressions.push(parseMaybeAssign(noIn, refShorthandDefaultPos));
1903
2098
  return finishNode(node, "SequenceExpression");
1904
2099
  }
1905
2100
  return expr;
@@ -1908,32 +2103,43 @@
1908
2103
  // Parse an assignment expression. This includes applications of
1909
2104
  // operators like `+=`.
1910
2105
 
1911
- function parseMaybeAssign(noIn) {
2106
+ function parseMaybeAssign(noIn, refShorthandDefaultPos) {
2107
+ var failOnShorthandAssign;
2108
+ if (!refShorthandDefaultPos) {
2109
+ refShorthandDefaultPos = {start: 0};
2110
+ failOnShorthandAssign = true;
2111
+ } else {
2112
+ failOnShorthandAssign = false;
2113
+ }
1912
2114
  var start = storeCurrentPos();
1913
- var left = parseMaybeConditional(noIn);
2115
+ var left = parseMaybeConditional(noIn, refShorthandDefaultPos);
1914
2116
  if (tokType.isAssign) {
1915
2117
  var node = startNodeAt(start);
1916
2118
  node.operator = tokVal;
1917
2119
  node.left = tokType === _eq ? toAssignable(left) : left;
2120
+ refShorthandDefaultPos.start = 0; // reset because shorthand default was used correctly
1918
2121
  checkLVal(left);
1919
2122
  next();
1920
2123
  node.right = parseMaybeAssign(noIn);
1921
2124
  return finishNode(node, "AssignmentExpression");
2125
+ } else if (failOnShorthandAssign && refShorthandDefaultPos.start) {
2126
+ unexpected(refShorthandDefaultPos.start);
1922
2127
  }
1923
2128
  return left;
1924
2129
  }
1925
2130
 
1926
2131
  // Parse a ternary conditional (`?:`) operator.
1927
2132
 
1928
- function parseMaybeConditional(noIn) {
2133
+ function parseMaybeConditional(noIn, refShorthandDefaultPos) {
1929
2134
  var start = storeCurrentPos();
1930
- var expr = parseExprOps(noIn);
2135
+ var expr = parseExprOps(noIn, refShorthandDefaultPos);
2136
+ if (refShorthandDefaultPos && refShorthandDefaultPos.start) return expr;
1931
2137
  if (eat(_question)) {
1932
2138
  var node = startNodeAt(start);
1933
2139
  node.test = expr;
1934
- node.consequent = parseExpression(true);
2140
+ node.consequent = parseMaybeAssign();
1935
2141
  expect(_colon);
1936
- node.alternate = parseExpression(true, noIn);
2142
+ node.alternate = parseMaybeAssign(noIn);
1937
2143
  return finishNode(node, "ConditionalExpression");
1938
2144
  }
1939
2145
  return expr;
@@ -1941,9 +2147,11 @@
1941
2147
 
1942
2148
  // Start the precedence parser.
1943
2149
 
1944
- function parseExprOps(noIn) {
2150
+ function parseExprOps(noIn, refShorthandDefaultPos) {
1945
2151
  var start = storeCurrentPos();
1946
- return parseExprOp(parseMaybeUnary(), start, -1, noIn);
2152
+ var expr = parseMaybeUnary(refShorthandDefaultPos);
2153
+ if (refShorthandDefaultPos && refShorthandDefaultPos.start) return expr;
2154
+ return parseExprOp(expr, start, -1, noIn);
1947
2155
  }
1948
2156
 
1949
2157
  // Parse binary operators with the operator precedence parsing
@@ -1972,27 +2180,23 @@
1972
2180
 
1973
2181
  // Parse unary operators, both prefix and postfix.
1974
2182
 
1975
- function parseMaybeUnary() {
2183
+ function parseMaybeUnary(refShorthandDefaultPos) {
1976
2184
  if (tokType.prefix) {
1977
- var node = startNode(), update = tokType.isUpdate, nodeType;
1978
- if (tokType === _ellipsis) {
1979
- nodeType = "SpreadElement";
1980
- } else {
1981
- nodeType = update ? "UpdateExpression" : "UnaryExpression";
1982
- node.operator = tokVal;
1983
- node.prefix = true;
1984
- }
1985
- tokRegexpAllowed = true;
2185
+ var node = startNode(), update = tokType.isUpdate;
2186
+ node.operator = tokVal;
2187
+ node.prefix = true;
1986
2188
  next();
1987
2189
  node.argument = parseMaybeUnary();
2190
+ if (refShorthandDefaultPos && refShorthandDefaultPos.start) unexpected(refShorthandDefaultPos.start);
1988
2191
  if (update) checkLVal(node.argument);
1989
2192
  else if (strict && node.operator === "delete" &&
1990
2193
  node.argument.type === "Identifier")
1991
2194
  raise(node.start, "Deleting local variable in strict mode");
1992
- return finishNode(node, nodeType);
2195
+ return finishNode(node, update ? "UpdateExpression" : "UnaryExpression");
1993
2196
  }
1994
2197
  var start = storeCurrentPos();
1995
- var expr = parseExprSubscripts();
2198
+ var expr = parseExprSubscripts(refShorthandDefaultPos);
2199
+ if (refShorthandDefaultPos && refShorthandDefaultPos.start) return expr;
1996
2200
  while (tokType.postfix && !canInsertSemicolon()) {
1997
2201
  var node = startNodeAt(start);
1998
2202
  node.operator = tokVal;
@@ -2007,9 +2211,11 @@
2007
2211
 
2008
2212
  // Parse call, dot, and `[]`-subscript expressions.
2009
2213
 
2010
- function parseExprSubscripts() {
2214
+ function parseExprSubscripts(refShorthandDefaultPos) {
2011
2215
  var start = storeCurrentPos();
2012
- return parseSubscripts(parseExprAtom(), start);
2216
+ var expr = parseExprAtom(refShorthandDefaultPos);
2217
+ if (refShorthandDefaultPos && refShorthandDefaultPos.start) return expr;
2218
+ return parseSubscripts(expr, start);
2013
2219
  }
2014
2220
 
2015
2221
  function parseSubscripts(base, start, noCalls) {
@@ -2031,7 +2237,7 @@
2031
2237
  node.callee = base;
2032
2238
  node.arguments = parseExprList(_parenR, false);
2033
2239
  return parseSubscripts(finishNode(node, "CallExpression"), start, noCalls);
2034
- } else if (tokType === _template) {
2240
+ } else if (tokType === _backQuote) {
2035
2241
  var node = startNodeAt(start);
2036
2242
  node.tag = base;
2037
2243
  node.quasi = parseTemplate();
@@ -2044,7 +2250,7 @@
2044
2250
  // `new`, or an expression wrapped in punctuation like `()`, `[]`,
2045
2251
  // or `{}`.
2046
2252
 
2047
- function parseExprAtom() {
2253
+ function parseExprAtom(refShorthandDefaultPos) {
2048
2254
  switch (tokType) {
2049
2255
  case _this:
2050
2256
  var node = startNode();
@@ -2057,7 +2263,7 @@
2057
2263
  case _name:
2058
2264
  var start = storeCurrentPos();
2059
2265
  var id = parseIdent(tokType !== _name);
2060
- if (eat(_arrow)) {
2266
+ if (!canInsertSemicolon() && eat(_arrow)) {
2061
2267
  return parseArrowExpression(startNodeAt(start), [id]);
2062
2268
  }
2063
2269
  return id;
@@ -2085,42 +2291,7 @@
2085
2291
  return finishNode(node, "Literal");
2086
2292
 
2087
2293
  case _parenL:
2088
- var start = storeCurrentPos();
2089
- var val, exprList;
2090
- next();
2091
- // check whether this is generator comprehension or regular expression
2092
- if (options.ecmaVersion >= 7 && tokType === _for) {
2093
- val = parseComprehension(startNodeAt(start), true);
2094
- } else {
2095
- var oldParenL = ++metParenL;
2096
- if (tokType !== _parenR) {
2097
- val = parseExpression();
2098
- exprList = val.type === "SequenceExpression" ? val.expressions : [val];
2099
- } else {
2100
- exprList = [];
2101
- }
2102
- expect(_parenR);
2103
- // if '=>' follows '(...)', convert contents to arguments
2104
- if (metParenL === oldParenL && eat(_arrow)) {
2105
- val = parseArrowExpression(startNodeAt(start), exprList);
2106
- } else {
2107
- // forbid '()' before everything but '=>'
2108
- if (!val) unexpected(lastStart);
2109
- // forbid '...' in sequence expressions
2110
- if (options.ecmaVersion >= 6) {
2111
- for (var i = 0; i < exprList.length; i++) {
2112
- if (exprList[i].type === "SpreadElement") unexpected();
2113
- }
2114
- }
2115
-
2116
- if (options.preserveParens) {
2117
- var par = startNodeAt(start);
2118
- par.expression = val;
2119
- val = finishNode(par, "ParenthesizedExpression");
2120
- }
2121
- }
2122
- }
2123
- return val;
2294
+ return parseParenAndDistinguishExpression();
2124
2295
 
2125
2296
  case _bracketL:
2126
2297
  var node = startNode();
@@ -2129,11 +2300,11 @@
2129
2300
  if (options.ecmaVersion >= 7 && tokType === _for) {
2130
2301
  return parseComprehension(node, false);
2131
2302
  }
2132
- node.elements = parseExprList(_bracketR, true, true);
2303
+ node.elements = parseExprList(_bracketR, true, true, refShorthandDefaultPos);
2133
2304
  return finishNode(node, "ArrayExpression");
2134
2305
 
2135
2306
  case _braceL:
2136
- return parseObj();
2307
+ return parseObj(false, refShorthandDefaultPos);
2137
2308
 
2138
2309
  case _function:
2139
2310
  var node = startNode();
@@ -2146,7 +2317,7 @@
2146
2317
  case _new:
2147
2318
  return parseNew();
2148
2319
 
2149
- case _template:
2320
+ case _backQuote:
2150
2321
  return parseTemplate();
2151
2322
 
2152
2323
  default:
@@ -2154,6 +2325,62 @@
2154
2325
  }
2155
2326
  }
2156
2327
 
2328
+ function parseParenAndDistinguishExpression() {
2329
+ var start = storeCurrentPos(), val;
2330
+ if (options.ecmaVersion >= 6) {
2331
+ next();
2332
+
2333
+ if (options.ecmaVersion >= 7 && tokType === _for) {
2334
+ return parseComprehension(startNodeAt(start), true);
2335
+ }
2336
+
2337
+ var innerStart = storeCurrentPos(), exprList = [], first = true;
2338
+ var refShorthandDefaultPos = {start: 0}, spreadStart, innerParenStart;
2339
+ while (tokType !== _parenR) {
2340
+ first ? first = false : expect(_comma);
2341
+ if (tokType === _ellipsis) {
2342
+ spreadStart = tokStart;
2343
+ exprList.push(parseRest());
2344
+ break;
2345
+ } else {
2346
+ if (tokType === _parenL && !innerParenStart) {
2347
+ innerParenStart = tokStart;
2348
+ }
2349
+ exprList.push(parseMaybeAssign(false, refShorthandDefaultPos));
2350
+ }
2351
+ }
2352
+ var innerEnd = storeCurrentPos();
2353
+ expect(_parenR);
2354
+
2355
+ if (!canInsertSemicolon() && eat(_arrow)) {
2356
+ if (innerParenStart) unexpected(innerParenStart);
2357
+ return parseArrowExpression(startNodeAt(start), exprList);
2358
+ }
2359
+
2360
+ if (!exprList.length) unexpected(lastStart);
2361
+ if (spreadStart) unexpected(spreadStart);
2362
+ if (refShorthandDefaultPos.start) unexpected(refShorthandDefaultPos.start);
2363
+
2364
+ if (exprList.length > 1) {
2365
+ val = startNodeAt(innerStart);
2366
+ val.expressions = exprList;
2367
+ finishNodeAt(val, "SequenceExpression", innerEnd);
2368
+ } else {
2369
+ val = exprList[0];
2370
+ }
2371
+ } else {
2372
+ val = parseParenExpression();
2373
+ }
2374
+
2375
+ if (options.preserveParens) {
2376
+ var par = startNodeAt(start);
2377
+ par.expression = val;
2378
+ return finishNode(par, "ParenthesizedExpression");
2379
+ } else {
2380
+ return val;
2381
+ }
2382
+ }
2383
+
2157
2384
  // New's precedence is slightly tricky. It must allow its argument
2158
2385
  // to be a `[]` or dot subscript expression, but not a call — at
2159
2386
  // least, not without wrapping it in parentheses. Thus, it uses the
@@ -2171,30 +2398,35 @@
2171
2398
  // Parse template expression.
2172
2399
 
2173
2400
  function parseTemplateElement() {
2174
- var elem = startNodeAt(options.locations ? [tokStart + 1, tokStartLoc.offset(1)] : tokStart + 1);
2175
- elem.value = tokVal;
2176
- elem.tail = input.charCodeAt(tokEnd - 1) !== 123; // '{'
2401
+ var elem = startNode();
2402
+ elem.value = {
2403
+ raw: input.slice(tokStart, tokEnd),
2404
+ cooked: tokVal
2405
+ };
2177
2406
  next();
2178
- var endOff = elem.tail ? 1 : 2;
2179
- return finishNodeAt(elem, "TemplateElement", options.locations ? [lastEnd - endOff, lastEndLoc.offset(-endOff)] : lastEnd - endOff);
2407
+ elem.tail = tokType === _backQuote;
2408
+ return finishNode(elem, "TemplateElement");
2180
2409
  }
2181
2410
 
2182
2411
  function parseTemplate() {
2183
2412
  var node = startNode();
2413
+ next();
2184
2414
  node.expressions = [];
2185
2415
  var curElt = parseTemplateElement();
2186
2416
  node.quasis = [curElt];
2187
2417
  while (!curElt.tail) {
2418
+ expect(_dollarBraceL);
2188
2419
  node.expressions.push(parseExpression());
2189
- if (tokType !== _templateContinued) unexpected();
2420
+ expect(_braceR);
2190
2421
  node.quasis.push(curElt = parseTemplateElement());
2191
2422
  }
2423
+ next();
2192
2424
  return finishNode(node, "TemplateLiteral");
2193
2425
  }
2194
2426
 
2195
- // Parse an object literal.
2427
+ // Parse an object literal or binding pattern.
2196
2428
 
2197
- function parseObj() {
2429
+ function parseObj(isPattern, refShorthandDefaultPos) {
2198
2430
  var node = startNode(), first = true, propHash = {};
2199
2431
  node.properties = [];
2200
2432
  next();
@@ -2204,36 +2436,51 @@
2204
2436
  if (options.allowTrailingCommas && eat(_braceR)) break;
2205
2437
  } else first = false;
2206
2438
 
2207
- var prop = startNode(), isGenerator;
2439
+ var prop = startNode(), isGenerator, start;
2208
2440
  if (options.ecmaVersion >= 6) {
2209
2441
  prop.method = false;
2210
2442
  prop.shorthand = false;
2211
- isGenerator = eat(_star);
2443
+ if (isPattern || refShorthandDefaultPos) {
2444
+ start = storeCurrentPos();
2445
+ }
2446
+ if (!isPattern) {
2447
+ isGenerator = eat(_star);
2448
+ }
2212
2449
  }
2213
2450
  parsePropertyName(prop);
2214
2451
  if (eat(_colon)) {
2215
- prop.value = parseExpression(true);
2452
+ prop.value = isPattern ? parseMaybeDefault() : parseMaybeAssign(false, refShorthandDefaultPos);
2216
2453
  prop.kind = "init";
2217
2454
  } else if (options.ecmaVersion >= 6 && tokType === _parenL) {
2455
+ if (isPattern) unexpected();
2218
2456
  prop.kind = "init";
2219
2457
  prop.method = true;
2220
2458
  prop.value = parseMethod(isGenerator);
2221
2459
  } else if (options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" &&
2222
- (prop.key.name === "get" || prop.key.name === "set")) {
2223
- if (isGenerator) unexpected();
2460
+ (prop.key.name === "get" || prop.key.name === "set") &&
2461
+ (tokType != _comma && tokType != _braceR)) {
2462
+ if (isGenerator || isPattern) unexpected();
2224
2463
  prop.kind = prop.key.name;
2225
2464
  parsePropertyName(prop);
2226
2465
  prop.value = parseMethod(false);
2227
2466
  } else if (options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") {
2228
2467
  prop.kind = "init";
2229
- prop.value = prop.key;
2468
+ if (isPattern) {
2469
+ prop.value = parseMaybeDefault(start, prop.key);
2470
+ } else if (tokType === _eq && refShorthandDefaultPos) {
2471
+ if (!refShorthandDefaultPos.start)
2472
+ refShorthandDefaultPos.start = tokStart;
2473
+ prop.value = parseMaybeDefault(start, prop.key);
2474
+ } else {
2475
+ prop.value = prop.key;
2476
+ }
2230
2477
  prop.shorthand = true;
2231
2478
  } else unexpected();
2232
2479
 
2233
2480
  checkPropClash(prop, propHash);
2234
2481
  node.properties.push(finishNode(prop, "Property"));
2235
2482
  }
2236
- return finishNode(node, "ObjectExpression");
2483
+ return finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression");
2237
2484
  }
2238
2485
 
2239
2486
  function parsePropertyName(prop) {
@@ -2254,11 +2501,9 @@
2254
2501
 
2255
2502
  function initFunction(node) {
2256
2503
  node.id = null;
2257
- node.params = [];
2258
2504
  if (options.ecmaVersion >= 6) {
2259
- node.defaults = [];
2260
- node.rest = null;
2261
2505
  node.generator = false;
2506
+ node.expression = false;
2262
2507
  }
2263
2508
  }
2264
2509
 
@@ -2273,7 +2518,8 @@
2273
2518
  if (isStatement || tokType === _name) {
2274
2519
  node.id = parseIdent();
2275
2520
  }
2276
- parseFunctionParams(node);
2521
+ expect(_parenL);
2522
+ node.params = parseBindingList(_parenR, false);
2277
2523
  parseFunctionBody(node, allowExpressionBody);
2278
2524
  return finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression");
2279
2525
  }
@@ -2283,7 +2529,8 @@
2283
2529
  function parseMethod(isGenerator) {
2284
2530
  var node = startNode();
2285
2531
  initFunction(node);
2286
- parseFunctionParams(node);
2532
+ expect(_parenL);
2533
+ node.params = parseBindingList(_parenR, false);
2287
2534
  var allowExpressionBody;
2288
2535
  if (options.ecmaVersion >= 6) {
2289
2536
  node.generator = isGenerator;
@@ -2299,76 +2546,18 @@
2299
2546
 
2300
2547
  function parseArrowExpression(node, params) {
2301
2548
  initFunction(node);
2302
-
2303
- var defaults = node.defaults, hasDefaults = false;
2304
-
2305
- for (var i = 0, lastI = params.length - 1; i <= lastI; i++) {
2306
- var param = params[i];
2307
-
2308
- if (param.type === "AssignmentExpression" && param.operator === "=") {
2309
- hasDefaults = true;
2310
- params[i] = param.left;
2311
- defaults.push(param.right);
2312
- } else {
2313
- toAssignable(param, i === lastI, true);
2314
- defaults.push(null);
2315
- if (param.type === "SpreadElement") {
2316
- params.length--;
2317
- node.rest = param.argument;
2318
- break;
2319
- }
2320
- }
2321
- }
2322
-
2323
- node.params = params;
2324
- if (!hasDefaults) node.defaults = [];
2325
-
2549
+ node.params = toAssignableList(params, true);
2326
2550
  parseFunctionBody(node, true);
2327
2551
  return finishNode(node, "ArrowFunctionExpression");
2328
2552
  }
2329
2553
 
2330
- // Parse function parameters.
2331
-
2332
- function parseFunctionParams(node) {
2333
- var defaults = [], hasDefaults = false;
2334
-
2335
- expect(_parenL);
2336
- for (;;) {
2337
- if (eat(_parenR)) {
2338
- break;
2339
- } else if (options.ecmaVersion >= 6 && eat(_ellipsis)) {
2340
- node.rest = toAssignable(parseExprAtom(), false, true);
2341
- checkSpreadAssign(node.rest);
2342
- expect(_parenR);
2343
- defaults.push(null);
2344
- break;
2345
- } else {
2346
- node.params.push(options.ecmaVersion >= 6 ? toAssignable(parseExprAtom(), false, true) : parseIdent());
2347
- if (options.ecmaVersion >= 6) {
2348
- if (eat(_eq)) {
2349
- hasDefaults = true;
2350
- defaults.push(parseExpression(true));
2351
- } else {
2352
- defaults.push(null);
2353
- }
2354
- }
2355
- if (!eat(_comma)) {
2356
- expect(_parenR);
2357
- break;
2358
- }
2359
- }
2360
- }
2361
-
2362
- if (hasDefaults) node.defaults = defaults;
2363
- }
2364
-
2365
2554
  // Parse function body and check parameters.
2366
2555
 
2367
2556
  function parseFunctionBody(node, allowExpression) {
2368
2557
  var isExpression = allowExpression && tokType !== _braceL;
2369
2558
 
2370
2559
  if (isExpression) {
2371
- node.body = parseExpression(true);
2560
+ node.body = parseMaybeAssign();
2372
2561
  node.expression = true;
2373
2562
  } else {
2374
2563
  // Start a new scope with regard to labels and the `inFunction`
@@ -2389,8 +2578,6 @@
2389
2578
  checkFunctionParam(node.id, {});
2390
2579
  for (var i = 0; i < node.params.length; i++)
2391
2580
  checkFunctionParam(node.params[i], nameHash);
2392
- if (node.rest)
2393
- checkFunctionParam(node.rest, nameHash);
2394
2581
  }
2395
2582
  }
2396
2583
 
@@ -2400,20 +2587,24 @@
2400
2587
  function parseClass(node, isStatement) {
2401
2588
  next();
2402
2589
  node.id = tokType === _name ? parseIdent() : isStatement ? unexpected() : null;
2403
- node.superClass = eat(_extends) ? parseExpression() : null;
2590
+ node.superClass = eat(_extends) ? parseExprSubscripts() : null;
2404
2591
  var classBody = startNode();
2405
2592
  classBody.body = [];
2406
2593
  expect(_braceL);
2407
2594
  while (!eat(_braceR)) {
2595
+ if (eat(_semi)) continue;
2408
2596
  var method = startNode();
2409
- if (tokType === _name && tokVal === "static") {
2410
- next();
2597
+ var isGenerator = eat(_star);
2598
+ parsePropertyName(method);
2599
+ if (tokType !== _parenL && !method.computed && method.key.type === "Identifier" &&
2600
+ method.key.name === "static") {
2601
+ if (isGenerator) unexpected();
2411
2602
  method['static'] = true;
2603
+ isGenerator = eat(_star);
2604
+ parsePropertyName(method);
2412
2605
  } else {
2413
2606
  method['static'] = false;
2414
2607
  }
2415
- var isGenerator = eat(_star);
2416
- parsePropertyName(method);
2417
2608
  if (tokType !== _parenL && !method.computed && method.key.type === "Identifier" &&
2418
2609
  (method.key.name === "get" || method.key.name === "set")) {
2419
2610
  if (isGenerator) unexpected();
@@ -2424,7 +2615,6 @@
2424
2615
  }
2425
2616
  method.value = parseMethod(isGenerator);
2426
2617
  classBody.body.push(finishNode(method, "MethodDefinition"));
2427
- eat(_semi);
2428
2618
  }
2429
2619
  node.body = finishNode(classBody, "ClassBody");
2430
2620
  return finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression");
@@ -2436,7 +2626,7 @@
2436
2626
  // nothing in between them to be parsed as `null` (which is needed
2437
2627
  // for array literals).
2438
2628
 
2439
- function parseExprList(close, allowTrailingComma, allowEmpty) {
2629
+ function parseExprList(close, allowTrailingComma, allowEmpty, refShorthandDefaultPos) {
2440
2630
  var elts = [], first = true;
2441
2631
  while (!eat(close)) {
2442
2632
  if (!first) {
@@ -2444,8 +2634,14 @@
2444
2634
  if (allowTrailingComma && options.allowTrailingCommas && eat(close)) break;
2445
2635
  } else first = false;
2446
2636
 
2447
- if (allowEmpty && tokType === _comma) elts.push(null);
2448
- else elts.push(parseExpression(true));
2637
+ if (allowEmpty && tokType === _comma) {
2638
+ elts.push(null);
2639
+ } else {
2640
+ if (tokType === _ellipsis)
2641
+ elts.push(parseSpread(refShorthandDefaultPos));
2642
+ else
2643
+ elts.push(parseMaybeAssign(false, refShorthandDefaultPos));
2644
+ }
2449
2645
  }
2450
2646
  return elts;
2451
2647
  }
@@ -2470,7 +2666,6 @@
2470
2666
  } else {
2471
2667
  unexpected();
2472
2668
  }
2473
- tokRegexpAllowed = false;
2474
2669
  next();
2475
2670
  return finishNode(node, "Identifier");
2476
2671
  }
@@ -2481,14 +2676,21 @@
2481
2676
  next();
2482
2677
  // export var|const|let|function|class ...;
2483
2678
  if (tokType === _var || tokType === _const || tokType === _let || tokType === _function || tokType === _class) {
2484
- node.declaration = parseStatement();
2679
+ node.declaration = parseStatement(true);
2485
2680
  node['default'] = false;
2486
2681
  node.specifiers = null;
2487
2682
  node.source = null;
2488
2683
  } else
2489
2684
  // export default ...;
2490
2685
  if (eat(_default)) {
2491
- node.declaration = parseExpression(true);
2686
+ var expr = parseMaybeAssign();
2687
+ if (expr.id) {
2688
+ switch (expr.type) {
2689
+ case "FunctionExpression": expr.type = "FunctionDeclaration"; break;
2690
+ case "ClassExpression": expr.type = "ClassDeclaration"; break;
2691
+ }
2692
+ }
2693
+ node.declaration = expr;
2492
2694
  node['default'] = true;
2493
2695
  node.specifiers = null;
2494
2696
  node.source = null;
@@ -2500,8 +2702,7 @@
2500
2702
  node.declaration = null;
2501
2703
  node['default'] = false;
2502
2704
  node.specifiers = parseExportSpecifiers();
2503
- if (tokType === _name && tokVal === "from") {
2504
- next();
2705
+ if (eatContextual("from")) {
2505
2706
  node.source = tokType === _string ? parseExprAtom() : unexpected();
2506
2707
  } else {
2507
2708
  if (isBatch) unexpected();
@@ -2532,12 +2733,7 @@
2532
2733
 
2533
2734
  var node = startNode();
2534
2735
  node.id = parseIdent(tokType === _default);
2535
- if (tokType === _name && tokVal === "as") {
2536
- next();
2537
- node.name = parseIdent(true);
2538
- } else {
2539
- node.name = null;
2540
- }
2736
+ node.name = eatContextual("as") ? parseIdent(true) : null;
2541
2737
  nodes.push(finishNode(node, "ExportSpecifier"));
2542
2738
  }
2543
2739
  }
@@ -2555,8 +2751,7 @@
2555
2751
  node.kind = "";
2556
2752
  } else {
2557
2753
  node.specifiers = parseImportSpecifiers();
2558
- if (tokType !== _name || tokVal !== "from") unexpected();
2559
- next();
2754
+ expectContextual("from");
2560
2755
  node.source = tokType === _string ? parseExprAtom() : unexpected();
2561
2756
  }
2562
2757
  semicolon();
@@ -2580,8 +2775,7 @@
2580
2775
  if (tokType === _star) {
2581
2776
  var node = startNode();
2582
2777
  next();
2583
- if (tokType !== _name || tokVal !== "as") unexpected();
2584
- next();
2778
+ expectContextual("as");
2585
2779
  node.name = parseIdent();
2586
2780
  checkLVal(node.name, true);
2587
2781
  nodes.push(finishNode(node, "ImportBatchSpecifier"));
@@ -2596,12 +2790,7 @@
2596
2790
 
2597
2791
  var node = startNode();
2598
2792
  node.id = parseIdent(true);
2599
- if (tokType === _name && tokVal === "as") {
2600
- next();
2601
- node.name = parseIdent();
2602
- } else {
2603
- node.name = null;
2604
- }
2793
+ node.name = eatContextual("as") ? parseIdent() : null;
2605
2794
  checkLVal(node.name || node.id, true);
2606
2795
  node['default'] = false;
2607
2796
  nodes.push(finishNode(node, "ImportSpecifier"));
@@ -2619,7 +2808,7 @@
2619
2808
  node.argument = null;
2620
2809
  } else {
2621
2810
  node.delegate = eat(_star);
2622
- node.argument = parseExpression(true);
2811
+ node.argument = parseMaybeAssign();
2623
2812
  }
2624
2813
  return finishNode(node, "YieldExpression");
2625
2814
  }
@@ -2632,13 +2821,9 @@
2632
2821
  var block = startNode();
2633
2822
  next();
2634
2823
  expect(_parenL);
2635
- block.left = toAssignable(parseExprAtom());
2824
+ block.left = parseBindingAtom();
2636
2825
  checkLVal(block.left, true);
2637
- if (tokType !== _name || tokVal !== "of") unexpected();
2638
- next();
2639
- // `of` property is here for compatibility with Esprima's AST
2640
- // which also supports deprecated [for (... in ...) expr]
2641
- block.of = true;
2826
+ expectContextual("of");
2642
2827
  block.right = parseExpression();
2643
2828
  expect(_parenR);
2644
2829
  node.blocks.push(finishNode(block, "ComprehensionBlock"));
@@ -2649,5 +2834,4 @@
2649
2834
  node.generator = isGenerator;
2650
2835
  return finishNode(node, "ComprehensionExpression");
2651
2836
  }
2652
-
2653
2837
  });