Make JetStream 2
[WebKit-https.git] / PerformanceTests / JetStream2 / ARES-6 / Babylon / index.js
1 /*
2  * Copyright (C) 2012-2014 by various contributors (see AUTHORS)
3  * Copyright (C) 2017 Apple Inc. All rights reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy
6  * of this software and associated documentation files (the "Software"), to deal
7  * in the Software without restriction, including without limitation the rights
8  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9  * copies of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  * 
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  * 
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21  * THE SOFTWARE.
22 */
23
24 "use strict";
25
26 // util/identifier.js
27
28 const utilIdentifierJS = { };
29 {
30     /* eslint max-len: 0 */
31
32     // This is a trick taken from Esprima. It turns out that, on
33     // non-Chrome browsers, to check whether a string is in a set, a
34     // predicate containing a big ugly `switch` statement is faster than
35     // a regular expression, and on Chrome the two are about on par.
36     // This function uses `eval` (non-lexical) to produce such a
37     // predicate from a space-separated string of words.
38     //
39     // It starts by sorting the words by length.
40
41     function makePredicate(words) {
42       words = words.split(" ");
43       return function (str) {
44         return words.indexOf(str) >= 0;
45       };
46     }
47
48     // Reserved word lists for various dialects of the language
49
50     const reservedWords = {
51       6: makePredicate("enum await"),
52       strict: makePredicate("implements interface let package private protected public static yield"),
53       strictBind: makePredicate("eval arguments")
54     };
55     utilIdentifierJS.reservedWords = reservedWords;
56
57     // And the keywords
58
59     const isKeyword = makePredicate("break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this let const class extends export import yield super");
60     utilIdentifierJS.isKeyword = isKeyword;
61
62     // ## Character categories
63
64     // Big ugly regular expressions that match characters in the
65     // whitespace, identifier, and identifier-start categories. These
66     // are only applied when a character is found to actually have a
67     // code point above 128.
68     // Generated by `bin/generate-identifier-regex.js`.
69
70     let nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0-\u08b4\u08b6-\u08bd\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c88\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fd5\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7ae\ua7b0-\ua7b7\ua7f7-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab65\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc";
71     let nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08d4-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c03\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0d01-\u0d03\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf2-\u1cf4\u1cf8\u1cf9\u1dc0-\u1df5\u1dfb-\u1dff\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua900-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f";
72
73     const nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]");
74     const nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]");
75
76     nonASCIIidentifierStartChars = nonASCIIidentifierChars = null;
77
78     // These are a run-length and offset encoded representation of the
79     // >0xffff code points that are a valid part of identifiers. The
80     // offset starts at 0x10000, and each pair of numbers represents an
81     // offset to the next range, and then a size of the range. They were
82     // generated by `bin/generate-identifier-regex.js`.
83     // eslint-disable-next-line comma-spacing
84     const astralIdentifierStartCodes = [0,11,2,25,2,18,2,1,2,14,3,13,35,122,70,52,268,28,4,48,48,31,17,26,6,37,11,29,3,35,5,7,2,4,43,157,19,35,5,35,5,39,9,51,157,310,10,21,11,7,153,5,3,0,2,43,2,1,4,0,3,22,11,22,10,30,66,18,2,1,11,21,11,25,71,55,7,1,65,0,16,3,2,2,2,26,45,28,4,28,36,7,2,27,28,53,11,21,11,18,14,17,111,72,56,50,14,50,785,52,76,44,33,24,27,35,42,34,4,0,13,47,15,3,22,0,2,0,36,17,2,24,85,6,2,0,2,3,2,14,2,9,8,46,39,7,3,1,3,21,2,6,2,1,2,4,4,0,19,0,13,4,159,52,19,3,54,47,21,1,2,0,185,46,42,3,37,47,21,0,60,42,86,25,391,63,32,0,449,56,264,8,2,36,18,0,50,29,881,921,103,110,18,195,2749,1070,4050,582,8634,568,8,30,114,29,19,47,17,3,32,20,6,18,881,68,12,0,67,12,65,0,32,6124,20,754,9486,1,3071,106,6,12,4,8,8,9,5991,84,2,70,2,1,3,0,3,1,3,3,2,11,2,0,2,6,2,64,2,3,3,7,2,6,2,27,2,3,2,4,2,0,4,6,2,339,3,24,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,7,4149,196,60,67,1213,3,2,26,2,1,2,0,3,0,2,9,2,3,2,0,2,0,7,0,5,0,2,0,2,0,2,2,2,1,2,0,3,0,2,0,2,0,2,0,2,0,2,1,2,0,3,3,2,6,2,3,2,3,2,0,2,9,2,16,6,2,2,4,2,16,4421,42710,42,4148,12,221,3,5761,10591,541];
85     // eslint-disable-next-line comma-spacing
86     const astralIdentifierCodes = [509,0,227,0,150,4,294,9,1368,2,2,1,6,3,41,2,5,0,166,1,1306,2,54,14,32,9,16,3,46,10,54,9,7,2,37,13,2,9,52,0,13,2,49,13,10,2,4,9,83,11,7,0,161,11,6,9,7,3,57,0,2,6,3,1,3,2,10,0,11,1,3,6,4,4,193,17,10,9,87,19,13,9,214,6,3,8,28,1,83,16,16,9,82,12,9,9,84,14,5,9,423,9,838,7,2,7,17,9,57,21,2,13,19882,9,135,4,60,6,26,9,1016,45,17,3,19723,1,5319,4,4,5,9,7,3,6,31,3,149,2,1418,49,513,54,5,49,9,0,15,0,23,4,2,14,1361,6,2,16,3,6,2,1,2,4,2214,6,110,6,6,9,792487,239];
87
88     // This has a complexity linear to the value of the code. The
89     // assumption is that looking up astral identifier characters is
90     // rare.
91     function isInAstralSet(code, set) {
92       let pos = 0x10000;
93       for (let i = 0; i < set.length; i += 2) {
94         pos += set[i];
95         if (pos > code) return false;
96
97         pos += set[i + 1];
98         if (pos >= code) return true;
99       }
100     }
101
102     // Test whether a given character code starts an identifier.
103
104     function isIdentifierStart(code) {
105       if (code < 65) return code === 36;
106       if (code < 91) return true;
107       if (code < 97) return code === 95;
108       if (code < 123) return true;
109       if (code <= 0xffff) return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code));
110       return isInAstralSet(code, astralIdentifierStartCodes);
111     }
112     utilIdentifierJS.isIdentifierStart = isIdentifierStart;
113
114     // Test whether a given character is part of an identifier.
115
116     function isIdentifierChar(code) {
117       if (code < 48) return code === 36;
118       if (code < 58) return true;
119       if (code < 65) return false;
120       if (code < 91) return true;
121       if (code < 97) return code === 95;
122       if (code < 123) return true;
123       if (code <= 0xffff) return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code));
124       return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes);
125     }
126     utilIdentifierJS.isIdentifierChar = isIdentifierChar;
127 }
128
129 // util/whitespace.js
130 const utilWhitespaceJS = {};
131 {
132     const lineBreak = /\r\n?|\n|\u2028|\u2029/;
133     utilWhitespaceJS.lineBreak = lineBreak;
134     const lineBreakG = new RegExp(lineBreak.source, "g");
135     utilWhitespaceJS.lineBreakG = lineBreakG;
136
137     function isNewLine(code){
138       return code === 10 || code === 13 || code === 0x2028 || code === 0x2029;
139     }
140     utilWhitespaceJS.isNewLine = isNewLine;
141
142     const nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/;
143     utilWhitespaceJS.nonASCIIwhitespace = nonASCIIwhitespace;
144 }
145
146 // util/location.js
147 const utilLocationJS = {};
148 {
149     const lineBreakG = utilWhitespaceJS.lineBreakG;
150
151     // These are used when `options.locations` is on, for the
152     // `startLoc` and `endLoc` properties.
153
154     class Position {
155       constructor(line, col) {
156         this.line = line;
157         this.column = col;
158       }
159     }
160     utilLocationJS.Position = Position;
161
162     class SourceLocation {
163       constructor(start, end) {
164         this.start = start;
165         this.end = end;
166       }
167     }
168     utilLocationJS.SourceLocation = SourceLocation;
169
170     // The `getLineInfo` function is mostly useful when the
171     // `locations` option is off (for performance reasons) and you
172     // want to find the line/column position for a given character
173     // offset. `input` should be the code string that the offset refers
174     // into.
175
176     function getLineInfo(input, offset) {
177       for (let line = 1, cur = 0; ;) {
178         lineBreakG.lastIndex = cur;
179         const match = lineBreakG.exec(input);
180         if (match && match.index < offset) {
181           ++line;
182           cur = match.index + match[0].length;
183         } else {
184           return new Position(line, offset - cur);
185         }
186       }
187     }
188     utilLocationJS.getLineInfo = getLineInfo;
189 }
190
191
192 // tokenizer/types.js
193 const tokenizerTypesJS = {};
194 {
195     // ## Token types
196
197     // The assignment of fine-grained, information-carrying type objects
198     // allows the tokenizer to store the information it has about a
199     // token in a way that is very cheap for the parser to look up.
200
201     // All token type variables start with an underscore, to make them
202     // easy to recognize.
203
204     // The `beforeExpr` property is used to disambiguate between regular
205     // expressions and divisions. It is set on all token types that can
206     // be followed by an expression (thus, a slash after them would be a
207     // regular expression).
208     //
209     // `isLoop` marks a keyword as starting a loop, which is important
210     // to know when parsing a label, in order to allow or disallow
211     // continue jumps to that label.
212
213     const beforeExpr = true;
214     const startsExpr = true;
215     const isLoop = true;
216     const isAssign = true;
217     const prefix = true;
218     const postfix = true;
219
220     class TokenType {
221       constructor(label, conf = {}) {
222         this.label = label;
223         this.keyword = conf.keyword;
224         this.beforeExpr = !!conf.beforeExpr;
225         this.startsExpr = !!conf.startsExpr;
226         this.rightAssociative = !!conf.rightAssociative;
227         this.isLoop = !!conf.isLoop;
228         this.isAssign = !!conf.isAssign;
229         this.prefix = !!conf.prefix;
230         this.postfix = !!conf.postfix;
231         this.binop = conf.binop || null;
232         this.updateContext = null;
233       }
234     }
235     tokenizerTypesJS.TokenType = TokenType;
236
237     class KeywordTokenType extends TokenType {
238       constructor(name, options = {}) {
239         options.keyword = name;
240
241         super(name, options);
242       }
243     }
244
245     class BinopTokenType extends TokenType {
246       constructor(name, prec) {
247         super(name, { beforeExpr, binop: prec });
248       }
249     }
250     tokenizerTypesJS.BinopTokenType = BinopTokenType;
251
252     const types = {
253       num: new TokenType("num", { startsExpr }),
254       regexp: new TokenType("regexp", { startsExpr }),
255       string: new TokenType("string", { startsExpr }),
256       name: new TokenType("name", { startsExpr }),
257       eof: new TokenType("eof"),
258
259       // Punctuation token types.
260       bracketL: new TokenType("[", { beforeExpr, startsExpr }),
261       bracketR: new TokenType("]"),
262       braceL: new TokenType("{", { beforeExpr, startsExpr }),
263       braceBarL: new TokenType("{|", { beforeExpr, startsExpr }),
264       braceR: new TokenType("}"),
265       braceBarR: new TokenType("|}"),
266       parenL: new TokenType("(", { beforeExpr, startsExpr }),
267       parenR: new TokenType(")"),
268       comma: new TokenType(",", { beforeExpr }),
269       semi: new TokenType(";", { beforeExpr }),
270       colon: new TokenType(":", { beforeExpr }),
271       doubleColon: new TokenType("::", { beforeExpr }),
272       dot: new TokenType("."),
273       question: new TokenType("?", { beforeExpr }),
274       arrow: new TokenType("=>", { beforeExpr }),
275       template: new TokenType("template"),
276       ellipsis: new TokenType("...", { beforeExpr }),
277       backQuote: new TokenType("`", { startsExpr }),
278       dollarBraceL: new TokenType("${", { beforeExpr, startsExpr }),
279       at: new TokenType("@"),
280
281       // Operators. These carry several kinds of properties to help the
282       // parser use them properly (the presence of these properties is
283       // what categorizes them as operators).
284       //
285       // `binop`, when present, specifies that this operator is a binary
286       // operator, and will refer to its precedence.
287       //
288       // `prefix` and `postfix` mark the operator as a prefix or postfix
289       // unary operator.
290       //
291       // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as
292       // binary operators with a very low precedence, that should result
293       // in AssignmentExpression nodes.
294
295       eq: new TokenType("=", { beforeExpr, isAssign }),
296       assign: new TokenType("_=", { beforeExpr, isAssign }),
297       incDec: new TokenType("++/--", { prefix, postfix, startsExpr }),
298       prefix: new TokenType("prefix", { beforeExpr, prefix, startsExpr }),
299       logicalOR: new BinopTokenType("||", 1),
300       logicalAND: new BinopTokenType("&&", 2),
301       bitwiseOR: new BinopTokenType("|", 3),
302       bitwiseXOR: new BinopTokenType("^", 4),
303       bitwiseAND: new BinopTokenType("&", 5),
304       equality: new BinopTokenType("==/!=", 6),
305       relational: new BinopTokenType("</>", 7),
306       bitShift: new BinopTokenType("<</>>", 8),
307       plusMin: new TokenType("+/-", { beforeExpr, binop: 9, prefix, startsExpr }),
308       modulo: new BinopTokenType("%", 10),
309       star: new BinopTokenType("*", 10),
310       slash: new BinopTokenType("/", 10),
311       exponent: new TokenType("**", { beforeExpr, binop: 11, rightAssociative: true })
312     };
313     tokenizerTypesJS.types = types;
314
315     const keywords = {
316       "break": new KeywordTokenType("break"),
317       "case": new KeywordTokenType("case", { beforeExpr }),
318       "catch": new KeywordTokenType("catch"),
319       "continue": new KeywordTokenType("continue"),
320       "debugger": new KeywordTokenType("debugger"),
321       "default": new KeywordTokenType("default", { beforeExpr }),
322       "do": new KeywordTokenType("do", { isLoop, beforeExpr }),
323       "else": new KeywordTokenType("else", { beforeExpr }),
324       "finally": new KeywordTokenType("finally"),
325       "for": new KeywordTokenType("for", { isLoop }),
326       "function": new KeywordTokenType("function", { startsExpr }),
327       "if": new KeywordTokenType("if"),
328       "return": new KeywordTokenType("return", { beforeExpr }),
329       "switch": new KeywordTokenType("switch"),
330       "throw": new KeywordTokenType("throw", { beforeExpr }),
331       "try": new KeywordTokenType("try"),
332       "var": new KeywordTokenType("var"),
333       "let": new KeywordTokenType("let"),
334       "const": new KeywordTokenType("const"),
335       "while": new KeywordTokenType("while", { isLoop }),
336       "with": new KeywordTokenType("with"),
337       "new": new KeywordTokenType("new", { beforeExpr, startsExpr }),
338       "this": new KeywordTokenType("this", { startsExpr }),
339       "super": new KeywordTokenType("super", { startsExpr }),
340       "class": new KeywordTokenType("class"),
341       "extends": new KeywordTokenType("extends", { beforeExpr }),
342       "export": new KeywordTokenType("export"),
343       "import": new KeywordTokenType("import", { startsExpr }),
344       "yield": new KeywordTokenType("yield", { beforeExpr, startsExpr }),
345       "null": new KeywordTokenType("null", { startsExpr }),
346       "true": new KeywordTokenType("true", { startsExpr }),
347       "false": new KeywordTokenType("false", { startsExpr }),
348       "in": new KeywordTokenType("in", { beforeExpr, binop: 7 }),
349       "instanceof": new KeywordTokenType("instanceof", { beforeExpr, binop: 7 }),
350       "typeof": new KeywordTokenType("typeof", { beforeExpr, prefix, startsExpr }),
351       "void": new KeywordTokenType("void", { beforeExpr, prefix, startsExpr }),
352       "delete": new KeywordTokenType("delete", { beforeExpr, prefix, startsExpr })
353     };
354     tokenizerTypesJS.keywords = keywords;
355
356     // Map keyword names to token types.
357     Object.keys(keywords).forEach((name) => {
358       types["_" + name] = keywords[name];
359     });
360 }
361
362 // tokenizer/context.js
363 const tokenizerContextJS = {};
364 {
365     // The algorithm used to determine whether a regexp can appear at a
366     // given point in the program is loosely based on sweet.js' approach.
367     // See https://github.com/mozilla/sweet.js/wiki/design
368
369     const tt = tokenizerTypesJS.types;
370     const lineBreak = utilWhitespaceJS.lineBreak;
371
372     class TokContext {
373       constructor(
374         token,
375         isExpr,
376         preserveSpace,
377         override,
378       ) {
379         this.token = token;
380         this.isExpr = !!isExpr;
381         this.preserveSpace = !!preserveSpace;
382         this.override = override;
383       }
384
385       //token: string;
386       //isExpr: boolean;
387       //preserveSpace: boolean;
388       //override: ?Function;
389     }
390     tokenizerContextJS.TokContext = TokContext;
391
392     const types = {
393       braceStatement: new TokContext("{", false),
394       braceExpression: new TokContext("{", true),
395       templateQuasi: new TokContext("${", true),
396       parenStatement: new TokContext("(", false),
397       parenExpression: new TokContext("(", true),
398       template: new TokContext("`", true, true, (p) => p.readTmplToken()),
399       functionExpression: new TokContext("function", true)
400     };
401     tokenizerContextJS.types = types;
402
403     // Token-specific context update code
404
405     tt.parenR.updateContext = tt.braceR.updateContext = function () {
406       if (this.state.context.length === 1) {
407         this.state.exprAllowed = true;
408         return;
409       }
410
411       const out = this.state.context.pop();
412       if (out === types.braceStatement && this.curContext() === types.functionExpression) {
413         this.state.context.pop();
414         this.state.exprAllowed = false;
415       } else if (out === types.templateQuasi) {
416         this.state.exprAllowed = true;
417       } else {
418         this.state.exprAllowed = !out.isExpr;
419       }
420     };
421
422     tt.name.updateContext = function (prevType) {
423       this.state.exprAllowed = false;
424
425       if (prevType === tt._let || prevType === tt._const || prevType === tt._var) {
426         if (lineBreak.test(this.input.slice(this.state.end))) {
427           this.state.exprAllowed = true;
428         }
429       }
430     };
431
432     tt.braceL.updateContext = function (prevType) {
433       this.state.context.push(this.braceIsBlock(prevType) ? types.braceStatement : types.braceExpression);
434       this.state.exprAllowed = true;
435     };
436
437     tt.dollarBraceL.updateContext = function () {
438       this.state.context.push(types.templateQuasi);
439       this.state.exprAllowed = true;
440     };
441
442     tt.parenL.updateContext = function (prevType) {
443       const statementParens = prevType === tt._if || prevType === tt._for ||
444                             prevType === tt._with || prevType === tt._while;
445       this.state.context.push(statementParens ? types.parenStatement : types.parenExpression);
446       this.state.exprAllowed = true;
447     };
448
449     tt.incDec.updateContext = function () {
450       // tokExprAllowed stays unchanged
451     };
452
453     tt._function.updateContext = function () {
454       if (this.curContext() !== types.braceStatement) {
455         this.state.context.push(types.functionExpression);
456       }
457
458       this.state.exprAllowed = false;
459     };
460
461     tt.backQuote.updateContext = function () {
462       if (this.curContext() === types.template) {
463         this.state.context.pop();
464       } else {
465         this.state.context.push(types.template);
466       }
467       this.state.exprAllowed = false;
468     };
469 }
470
471 // tokenizer/state.js
472 let tokenizerStateJS = {};
473 {
474     const TokContext = tokenizerContextJS.TokContext;
475     const TokenType = tokenizerTypesJS.TokenType;
476     const Position = utilLocationJS.Position;
477     const ct = tokenizerContextJS.types;
478     const tt = tokenizerTypesJS.types;
479
480     //export default class State {
481     class State {
482       init(options, input) {
483         this.strict = options.strictMode === false ? false : options.sourceType === "module";
484
485         this.input = input;
486
487         this.potentialArrowAt = -1;
488
489         this.inMethod =
490           this.inFunction =
491           this.inGenerator =
492           this.inAsync =
493           this.inPropertyName =
494           this.inType =
495           this.noAnonFunctionType =
496             false;
497
498         this.labels = [];
499
500         this.decorators = [];
501
502         this.tokens = [];
503
504         this.comments = [];
505
506         this.trailingComments = [];
507         this.leadingComments  = [];
508         this.commentStack     = [];
509
510         this.pos = this.lineStart = 0;
511         this.curLine = options.startLine;
512
513         this.type = tt.eof;
514         this.value = null;
515         this.start = this.end = this.pos;
516         this.startLoc = this.endLoc = this.curPosition();
517
518         this.lastTokEndLoc = this.lastTokStartLoc = null;
519         this.lastTokStart = this.lastTokEnd = this.pos;
520
521         this.context = [ct.braceStatement];
522         this.exprAllowed = true;
523
524         this.containsEsc = this.containsOctal = false;
525         this.octalPosition = null;
526
527         this.invalidTemplateEscapePosition = null;
528
529         this.exportedIdentifiers = [];
530
531         return this;
532       }
533
534       //// TODO
535       //strict: boolean;
536
537       //// TODO
538       //input: string;
539
540       //// Used to signify the start of a potential arrow function
541       //potentialArrowAt: number;
542
543       //// Flags to track whether we are in a function, a generator.
544       //inFunction: boolean;
545       //inGenerator: boolean;
546       //inMethod: boolean;
547       //inAsync: boolean;
548       //inType: boolean;
549       //inPropertyName: boolean;
550
551       //// Labels in scope.
552       //labels: Array<Object>;
553
554       //// Leading decorators.
555       //decorators: Array<Object>;
556
557       //// Token store.
558       //tokens: Array<Object>;
559
560       //// Comment store.
561       //comments: Array<Object>;
562
563       //// Comment attachment store
564       //trailingComments: Array<Object>;
565       //leadingComments: Array<Object>;
566       //commentStack: Array<Object>;
567
568       //// The current position of the tokenizer in the input.
569       //pos: number;
570       //lineStart: number;
571       //curLine: number;
572
573       //// Properties of the current token:
574       //// Its type
575       //type: TokenType;
576
577       //// For tokens that include more information than their type, the value
578       //value: any;
579
580       //// Its start and end offset
581       //start: number;
582       //end: number;
583
584       //// And, if locations are used, the {line, column} object
585       //// corresponding to those offsets
586       //startLoc: Position;
587       //endLoc: Position;
588
589       //// Position information for the previous token
590       //lastTokEndLoc: ?Position;
591       //lastTokStartLoc: ?Position;
592       //lastTokStart: number;
593       //lastTokEnd: number;
594
595       //// The context stack is used to superficially track syntactic
596       //// context to predict whether a regular expression is allowed in a
597       //// given position.
598       //context: Array<TokContext>;
599       //exprAllowed: boolean;
600
601       //// Used to signal to callers of `readWord1` whether the word
602       //// contained any escape sequences. This is needed because words with
603       //// escape sequences must not be interpreted as keywords.
604       //containsEsc: boolean;
605
606       //// TODO
607       //containsOctal: boolean;
608       //octalPosition: ?number;
609
610       //// Names of exports store. `default` is stored as a name for both
611       //// `export default foo;` and `export { foo as default };`.
612       //exportedIdentifiers: Array<string>;
613
614       curPosition() {
615         return new Position(this.curLine, this.pos - this.lineStart);
616       }
617
618       clone(skipArrays) {
619         const state = new State;
620         for (const key in this) {
621           let val = this[key];
622
623           if ((!skipArrays || key === "context") && Array.isArray(val)) {
624             val = val.slice();
625           }
626
627           state[key] = val;
628         }
629         return state;
630       }
631     }
632     tokenizerStateJS = State;
633 }
634
635 // tokenizer/index.js
636 let tokenizerIndexJS = {};
637 {
638     /* eslint max-len: 0 */
639
640     const TokenType = tokenizerTypesJS.TokenType;
641     const {isIdentifierStart, isIdentifierChar, isKeyword} = utilIdentifierJS;
642
643     const { types: tt , keywords: keywordTypes } = tokenizerTypesJS;
644     const { types: ct } = tokenizerContextJS;
645     const { SourceLocation } = utilLocationJS;
646     const { lineBreak, lineBreakG, isNewLine, nonASCIIwhitespace } = utilWhitespaceJS;
647     const State = tokenizerStateJS;
648
649     // Object type used to represent tokens. Note that normally, tokens
650     // simply exist as properties on the parser object. This is only
651     // used for the onToken callback and the external tokenizer.
652
653     //export class Token {
654     class Token {
655       constructor(state) {
656         this.type = state.type;
657         this.value = state.value;
658         this.start = state.start;
659         this.end = state.end;
660         this.loc = new SourceLocation(state.startLoc, state.endLoc);
661       }
662     }
663
664     // ## Tokenizer
665
666     function codePointToString(code) {
667       // UTF-16 Decoding
668       if (code <= 0xFFFF) {
669         return String.fromCharCode(code);
670       } else {
671         return String.fromCharCode(((code - 0x10000) >> 10) + 0xD800, ((code - 0x10000) & 1023) + 0xDC00);
672       }
673     }
674
675     class Tokenizer {
676       constructor(options, input) {
677         this.state = new State;
678         this.state.init(options, input);
679       }
680
681       // Move to the next token
682
683       next() {
684         if (!this.isLookahead) {
685           this.state.tokens.push(new Token(this.state));
686         }
687
688         this.state.lastTokEnd = this.state.end;
689         this.state.lastTokStart = this.state.start;
690         this.state.lastTokEndLoc = this.state.endLoc;
691         this.state.lastTokStartLoc = this.state.startLoc;
692         this.nextToken();
693       }
694
695       // TODO
696
697       eat(type) {
698         if (this.match(type)) {
699           this.next();
700           return true;
701         } else {
702           return false;
703         }
704       }
705
706       // TODO
707
708       match(type) {
709         return this.state.type === type;
710       }
711
712       // TODO
713
714       isKeyword(word) {
715         return isKeyword(word);
716       }
717
718       // TODO
719
720       lookahead() {
721         const old = this.state;
722         this.state = old.clone(true);
723
724         this.isLookahead = true;
725         this.next();
726         this.isLookahead = false;
727
728         const curr = this.state.clone(true);
729         this.state = old;
730         return curr;
731       }
732
733       // Toggle strict mode. Re-reads the next number or string to please
734       // pedantic tests (`"use strict"; 010;` should fail).
735
736       setStrict(strict) {
737         this.state.strict = strict;
738         if (!this.match(tt.num) && !this.match(tt.string)) return;
739         this.state.pos = this.state.start;
740         while (this.state.pos < this.state.lineStart) {
741           this.state.lineStart = this.input.lastIndexOf("\n", this.state.lineStart - 2) + 1;
742           --this.state.curLine;
743         }
744         this.nextToken();
745       }
746
747       curContext() {
748         return this.state.context[this.state.context.length - 1];
749       }
750
751       // Read a single token, updating the parser object's token-related
752       // properties.
753
754       nextToken() {
755         const curContext = this.curContext();
756         if (!curContext || !curContext.preserveSpace) this.skipSpace();
757
758         this.state.containsOctal = false;
759         this.state.octalPosition = null;
760         this.state.start = this.state.pos;
761         this.state.startLoc = this.state.curPosition();
762         if (this.state.pos >= this.input.length) return this.finishToken(tt.eof);
763
764         if (curContext.override) {
765           return curContext.override(this);
766         } else {
767           return this.readToken(this.fullCharCodeAtPos());
768         }
769       }
770
771       readToken(code) {
772         // Identifier or keyword. '\uXXXX' sequences are allowed in
773         // identifiers, so '\' also dispatches to that.
774         if (isIdentifierStart(code) || code === 92 /* '\' */) {
775           return this.readWord();
776         } else {
777           return this.getTokenFromCode(code);
778         }
779       }
780
781       fullCharCodeAtPos() {
782         const code = this.input.charCodeAt(this.state.pos);
783         if (code <= 0xd7ff || code >= 0xe000) return code;
784
785         const next = this.input.charCodeAt(this.state.pos + 1);
786         return (code << 10) + next - 0x35fdc00;
787       }
788
789       pushComment(block, text, start, end, startLoc, endLoc) {
790         const comment = {
791           type: block ? "CommentBlock" : "CommentLine",
792           value: text,
793           start: start,
794           end: end,
795           loc: new SourceLocation(startLoc, endLoc)
796         };
797
798         if (!this.isLookahead) {
799           this.state.tokens.push(comment);
800           this.state.comments.push(comment);
801           this.addComment(comment);
802         }
803       }
804
805       skipBlockComment() {
806         const startLoc = this.state.curPosition();
807         const start = this.state.pos;
808         const end = this.input.indexOf("*/", this.state.pos += 2);
809         if (end === -1) this.raise(this.state.pos - 2, "Unterminated comment");
810
811         this.state.pos = end + 2;
812         lineBreakG.lastIndex = start;
813         let match;
814         while ((match = lineBreakG.exec(this.input)) && match.index < this.state.pos) {
815           ++this.state.curLine;
816           this.state.lineStart = match.index + match[0].length;
817         }
818
819         this.pushComment(true, this.input.slice(start + 2, end), start, this.state.pos, startLoc, this.state.curPosition());
820       }
821
822       skipLineComment(startSkip) {
823         const start = this.state.pos;
824         const startLoc = this.state.curPosition();
825         let ch = this.input.charCodeAt(this.state.pos += startSkip);
826         while (this.state.pos < this.input.length && ch !== 10 && ch !== 13 && ch !== 8232 && ch !== 8233) {
827           ++this.state.pos;
828           ch = this.input.charCodeAt(this.state.pos);
829         }
830
831         this.pushComment(false, this.input.slice(start + startSkip, this.state.pos), start, this.state.pos, startLoc, this.state.curPosition());
832       }
833
834       // Called at the start of the parse and after every token. Skips
835       // whitespace and comments, and.
836
837       skipSpace() {
838         loop: while (this.state.pos < this.input.length) {
839           const ch = this.input.charCodeAt(this.state.pos);
840           switch (ch) {
841             case 32: case 160: // ' '
842               ++this.state.pos;
843               break;
844
845             case 13:
846               if (this.input.charCodeAt(this.state.pos + 1) === 10) {
847                 ++this.state.pos;
848               }
849
850             case 10: case 8232: case 8233:
851               ++this.state.pos;
852               ++this.state.curLine;
853               this.state.lineStart = this.state.pos;
854               break;
855
856             case 47: // '/'
857               switch (this.input.charCodeAt(this.state.pos + 1)) {
858                 case 42: // '*'
859                   this.skipBlockComment();
860                   break;
861
862                 case 47:
863                   this.skipLineComment(2);
864                   break;
865
866                 default:
867                   break loop;
868               }
869               break;
870
871             default:
872               if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) {
873                 ++this.state.pos;
874               } else {
875                 break loop;
876               }
877           }
878         }
879       }
880
881       // Called at the end of every token. Sets `end`, `val`, and
882       // maintains `context` and `exprAllowed`, and skips the space after
883       // the token, so that the next one's `start` will point at the
884       // right position.
885
886       finishToken(type, val) {
887         this.state.end = this.state.pos;
888         this.state.endLoc = this.state.curPosition();
889         const prevType = this.state.type;
890         this.state.type = type;
891         this.state.value = val;
892
893         this.updateContext(prevType);
894       }
895
896       // ### Token reading
897
898       // This is the function that is called to fetch the next token. It
899       // is somewhat obscure, because it works in character codes rather
900       // than characters, and because operator parsing has been inlined
901       // into it.
902       //
903       // All in the name of speed.
904       //
905       readToken_dot() {
906         const next = this.input.charCodeAt(this.state.pos + 1);
907         if (next >= 48 && next <= 57) {
908           return this.readNumber(true);
909         }
910
911         const next2 = this.input.charCodeAt(this.state.pos + 2);
912         if (next === 46 && next2 === 46) { // 46 = dot '.'
913           this.state.pos += 3;
914           return this.finishToken(tt.ellipsis);
915         } else {
916           ++this.state.pos;
917           return this.finishToken(tt.dot);
918         }
919       }
920
921       readToken_slash() { // '/'
922         if (this.state.exprAllowed) {
923           ++this.state.pos;
924           return this.readRegexp();
925         }
926
927         const next = this.input.charCodeAt(this.state.pos + 1);
928         if (next === 61) {
929           return this.finishOp(tt.assign, 2);
930         } else {
931           return this.finishOp(tt.slash, 1);
932         }
933       }
934
935       readToken_mult_modulo(code) { // '%*'
936         let type = code === 42 ? tt.star : tt.modulo;
937         let width = 1;
938         let next = this.input.charCodeAt(this.state.pos + 1);
939
940         if (next === 42) { // '*'
941           width++;
942           next = this.input.charCodeAt(this.state.pos + 2);
943           type = tt.exponent;
944         }
945
946         if (next === 61) {
947           width++;
948           type = tt.assign;
949         }
950
951         return this.finishOp(type, width);
952       }
953
954       readToken_pipe_amp(code) { // '|&'
955         const next = this.input.charCodeAt(this.state.pos + 1);
956         if (next === code) return this.finishOp(code === 124 ? tt.logicalOR : tt.logicalAND, 2);
957         if (next === 61) return this.finishOp(tt.assign, 2);
958         if (code === 124 && next === 125 && this.hasPlugin("flow")) return this.finishOp(tt.braceBarR, 2);
959         return this.finishOp(code === 124 ? tt.bitwiseOR : tt.bitwiseAND, 1);
960       }
961
962       readToken_caret() { // '^'
963         const next = this.input.charCodeAt(this.state.pos + 1);
964         if (next === 61) {
965           return this.finishOp(tt.assign, 2);
966         } else {
967           return this.finishOp(tt.bitwiseXOR, 1);
968         }
969       }
970
971       readToken_plus_min(code) { // '+-'
972         const next = this.input.charCodeAt(this.state.pos + 1);
973
974         if (next === code) {
975           if (next === 45 && this.input.charCodeAt(this.state.pos + 2) === 62 && lineBreak.test(this.input.slice(this.state.lastTokEnd, this.state.pos))) {
976             // A `-->` line comment
977             this.skipLineComment(3);
978             this.skipSpace();
979             return this.nextToken();
980           }
981           return this.finishOp(tt.incDec, 2);
982         }
983
984         if (next === 61) {
985           return this.finishOp(tt.assign, 2);
986         } else {
987           return this.finishOp(tt.plusMin, 1);
988         }
989       }
990
991       readToken_lt_gt(code) { // '<>'
992         const next = this.input.charCodeAt(this.state.pos + 1);
993         let size = 1;
994
995         if (next === code) {
996           size = code === 62 && this.input.charCodeAt(this.state.pos + 2) === 62 ? 3 : 2;
997           if (this.input.charCodeAt(this.state.pos + size) === 61) return this.finishOp(tt.assign, size + 1);
998           return this.finishOp(tt.bitShift, size);
999         }
1000
1001         if (next === 33 && code === 60 && this.input.charCodeAt(this.state.pos + 2) === 45 && this.input.charCodeAt(this.state.pos + 3) === 45) {
1002           if (this.inModule) this.unexpected();
1003           // `<!--`, an XML-style comment that should be interpreted as a line comment
1004           this.skipLineComment(4);
1005           this.skipSpace();
1006           return this.nextToken();
1007         }
1008
1009         if (next === 61) {
1010           // <= | >=
1011           size = 2;
1012         }
1013
1014         return this.finishOp(tt.relational, size);
1015       }
1016
1017       readToken_eq_excl(code) { // '=!'
1018         const next = this.input.charCodeAt(this.state.pos + 1);
1019         if (next === 61) return this.finishOp(tt.equality, this.input.charCodeAt(this.state.pos + 2) === 61 ? 3 : 2);
1020         if (code === 61 && next === 62) { // '=>'
1021           this.state.pos += 2;
1022           return this.finishToken(tt.arrow);
1023         }
1024         return this.finishOp(code === 61 ? tt.eq : tt.prefix, 1);
1025       }
1026
1027       getTokenFromCode(code) {
1028         switch (code) {
1029           // The interpretation of a dot depends on whether it is followed
1030           // by a digit or another two dots.
1031           case 46: // '.'
1032             return this.readToken_dot();
1033
1034           // Punctuation tokens.
1035           case 40: ++this.state.pos; return this.finishToken(tt.parenL);
1036           case 41: ++this.state.pos; return this.finishToken(tt.parenR);
1037           case 59: ++this.state.pos; return this.finishToken(tt.semi);
1038           case 44: ++this.state.pos; return this.finishToken(tt.comma);
1039           case 91: ++this.state.pos; return this.finishToken(tt.bracketL);
1040           case 93: ++this.state.pos; return this.finishToken(tt.bracketR);
1041
1042           case 123:
1043             if (this.hasPlugin("flow") && this.input.charCodeAt(this.state.pos + 1) === 124) {
1044               return this.finishOp(tt.braceBarL, 2);
1045             } else {
1046               ++this.state.pos;
1047               return this.finishToken(tt.braceL);
1048             }
1049
1050           case 125:
1051             ++this.state.pos; return this.finishToken(tt.braceR);
1052
1053           case 58:
1054             if (this.hasPlugin("functionBind") && this.input.charCodeAt(this.state.pos + 1) === 58) {
1055               return this.finishOp(tt.doubleColon, 2);
1056             } else {
1057               ++this.state.pos;
1058               return this.finishToken(tt.colon);
1059             }
1060
1061           case 63: ++this.state.pos; return this.finishToken(tt.question);
1062           case 64: ++this.state.pos; return this.finishToken(tt.at);
1063
1064           case 96: // '`'
1065             ++this.state.pos;
1066             return this.finishToken(tt.backQuote);
1067
1068           case 48: // '0'
1069             const next = this.input.charCodeAt(this.state.pos + 1);
1070             if (next === 120 || next === 88) return this.readRadixNumber(16); // '0x', '0X' - hex number
1071             if (next === 111 || next === 79) return this.readRadixNumber(8); // '0o', '0O' - octal number
1072             if (next === 98 || next === 66) return this.readRadixNumber(2); // '0b', '0B' - binary number
1073             // Anything else beginning with a digit is an integer, octal
1074             // number, or float.
1075           case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: // 1-9
1076             return this.readNumber(false);
1077
1078             // Quotes produce strings.
1079           case 34: case 39: // '"', "'"
1080             return this.readString(code);
1081
1082           // Operators are parsed inline in tiny state machines. '=' (61) is
1083           // often referred to. `finishOp` simply skips the amount of
1084           // characters it is given as second argument, and returns a token
1085           // of the type given by its first argument.
1086
1087           case 47: // '/'
1088             return this.readToken_slash();
1089
1090           case 37: case 42: // '%*'
1091             return this.readToken_mult_modulo(code);
1092
1093           case 124: case 38: // '|&'
1094             return this.readToken_pipe_amp(code);
1095
1096           case 94: // '^'
1097             return this.readToken_caret();
1098
1099           case 43: case 45: // '+-'
1100             return this.readToken_plus_min(code);
1101
1102           case 60: case 62: // '<>'
1103             return this.readToken_lt_gt(code);
1104
1105           case 61: case 33: // '=!'
1106             return this.readToken_eq_excl(code);
1107
1108           case 126: // '~'
1109             return this.finishOp(tt.prefix, 1);
1110         }
1111
1112         this.raise(this.state.pos, `Unexpected character '${codePointToString(code)}'`);
1113       }
1114
1115       finishOp(type, size) {
1116         const str = this.input.slice(this.state.pos, this.state.pos + size);
1117         this.state.pos += size;
1118         return this.finishToken(type, str);
1119       }
1120
1121       readRegexp() {
1122         const start = this.state.pos;
1123         let escaped, inClass;
1124         for (;;) {
1125           if (this.state.pos >= this.input.length) this.raise(start, "Unterminated regular expression");
1126           const ch = this.input.charAt(this.state.pos);
1127           if (lineBreak.test(ch)) {
1128             this.raise(start, "Unterminated regular expression");
1129           }
1130           if (escaped) {
1131             escaped = false;
1132           } else {
1133             if (ch === "[") {
1134               inClass = true;
1135             } else if (ch === "]" && inClass) {
1136               inClass = false;
1137             } else if (ch === "/" && !inClass) {
1138               break;
1139             }
1140             escaped = ch === "\\";
1141           }
1142           ++this.state.pos;
1143         }
1144         const content = this.input.slice(start, this.state.pos);
1145         ++this.state.pos;
1146         // Need to use `readWord1` because '\uXXXX' sequences are allowed
1147         // here (don't ask).
1148         const mods = this.readWord1();
1149         if (mods) {
1150           const validFlags = /^[gmsiyu]*$/;
1151           if (!validFlags.test(mods)) this.raise(start, "Invalid regular expression flag");
1152         }
1153         return this.finishToken(tt.regexp, {
1154           pattern: content,
1155           flags: mods
1156         });
1157       }
1158
1159       // Read an integer in the given radix. Return null if zero digits
1160       // were read, the integer value otherwise. When `len` is given, this
1161       // will return `null` unless the integer has exactly `len` digits.
1162
1163       readInt(radix, len) {
1164         const start = this.state.pos;
1165         let total = 0;
1166
1167         for (let i = 0, e = len == null ? Infinity : len; i < e; ++i) {
1168           const code = this.input.charCodeAt(this.state.pos);
1169           let val;
1170           if (code >= 97) {
1171             val = code - 97 + 10; // a
1172           } else if (code >= 65) {
1173             val = code - 65 + 10; // A
1174           } else if (code >= 48 && code <= 57) {
1175             val = code - 48; // 0-9
1176           } else  {
1177             val = Infinity;
1178           }
1179           if (val >= radix) break;
1180           ++this.state.pos;
1181           total = total * radix + val;
1182         }
1183         if (this.state.pos === start || len != null && this.state.pos - start !== len) return null;
1184
1185         return total;
1186       }
1187
1188       readRadixNumber(radix) {
1189         this.state.pos += 2; // 0x
1190         const val = this.readInt(radix);
1191         if (val == null) this.raise(this.state.start + 2, "Expected number in radix " + radix);
1192         if (isIdentifierStart(this.fullCharCodeAtPos())) this.raise(this.state.pos, "Identifier directly after number");
1193         return this.finishToken(tt.num, val);
1194       }
1195
1196       // Read an integer, octal integer, or floating-point number.
1197
1198       readNumber(startsWithDot) {
1199         const start = this.state.pos;
1200         const octal = this.input.charCodeAt(this.state.pos) === 48;
1201         let isFloat = false;
1202
1203         if (!startsWithDot && this.readInt(10) === null) this.raise(start, "Invalid number");
1204         let next = this.input.charCodeAt(this.state.pos);
1205         if (next === 46) { // '.'
1206           ++this.state.pos;
1207           this.readInt(10);
1208           isFloat = true;
1209           next = this.input.charCodeAt(this.state.pos);
1210         }
1211         if (next === 69 || next === 101) { // 'eE'
1212           next = this.input.charCodeAt(++this.state.pos);
1213           if (next === 43 || next === 45) ++this.state.pos; // '+-'
1214           if (this.readInt(10) === null) this.raise(start, "Invalid number");
1215           isFloat = true;
1216         }
1217         if (isIdentifierStart(this.fullCharCodeAtPos())) this.raise(this.state.pos, "Identifier directly after number");
1218
1219         const str = this.input.slice(start, this.state.pos);
1220         let val;
1221         if (isFloat) {
1222           val = parseFloat(str);
1223         } else if (!octal || str.length === 1) {
1224           val = parseInt(str, 10);
1225         } else if (/[89]/.test(str) || this.state.strict) {
1226           this.raise(start, "Invalid number");
1227         } else {
1228           val = parseInt(str, 8);
1229         }
1230         return this.finishToken(tt.num, val);
1231       }
1232
1233       // Read a string value, interpreting backslash-escapes.
1234
1235       readCodePoint(throwOnInvalid) {
1236         const ch = this.input.charCodeAt(this.state.pos);
1237         let code;
1238
1239         if (ch === 123) { // '{'
1240           const codePos = ++this.state.pos;
1241           code = this.readHexChar(this.input.indexOf("}", this.state.pos) - this.state.pos, throwOnInvalid);
1242           ++this.state.pos;
1243           if (code === null) {
1244             --this.state.invalidTemplateEscapePosition; // to point to the '\'' instead of the 'u'
1245           } else if (code > 0x10FFFF) {
1246             if (throwOnInvalid) {
1247               this.raise(codePos, "Code point out of bounds");
1248             } else {
1249               this.state.invalidTemplateEscapePosition = codePos - 2;
1250               return null;
1251             }
1252           }
1253         } else {
1254           code = this.readHexChar(4, throwOnInvalid);
1255         }
1256         return code;
1257       }
1258
1259       readString(quote) {
1260         let out = "", chunkStart = ++this.state.pos;
1261         for (;;) {
1262           if (this.state.pos >= this.input.length) this.raise(this.state.start, "Unterminated string constant");
1263           const ch = this.input.charCodeAt(this.state.pos);
1264           if (ch === quote) break;
1265           if (ch === 92) { // '\'
1266             out += this.input.slice(chunkStart, this.state.pos);
1267             out += this.readEscapedChar(false);
1268             chunkStart = this.state.pos;
1269           } else {
1270             if (isNewLine(ch)) this.raise(this.state.start, "Unterminated string constant");
1271             ++this.state.pos;
1272           }
1273         }
1274         out += this.input.slice(chunkStart, this.state.pos++);
1275         return this.finishToken(tt.string, out);
1276       }
1277
1278       // Reads template string tokens.
1279
1280       readTmplToken() {
1281         let out = "", chunkStart = this.state.pos, containsInvalid = false;
1282         for (;;) {
1283           if (this.state.pos >= this.input.length) this.raise(this.state.start, "Unterminated template");
1284           const ch = this.input.charCodeAt(this.state.pos);
1285           if (ch === 96 || ch === 36 && this.input.charCodeAt(this.state.pos + 1) === 123) { // '`', '${'
1286             if (this.state.pos === this.state.start && this.match(tt.template)) {
1287               if (ch === 36) {
1288                 this.state.pos += 2;
1289                 return this.finishToken(tt.dollarBraceL);
1290               } else {
1291                 ++this.state.pos;
1292                 return this.finishToken(tt.backQuote);
1293               }
1294             }
1295             out += this.input.slice(chunkStart, this.state.pos);
1296             return this.finishToken(tt.template, containsInvalid ? null : out);
1297           }
1298           if (ch === 92) { // '\'
1299             out += this.input.slice(chunkStart, this.state.pos);
1300             const escaped = this.readEscapedChar(true);
1301             if (escaped === null) {
1302               containsInvalid = true;
1303             } else {
1304               out += escaped;
1305             }
1306             chunkStart = this.state.pos;
1307           } else if (isNewLine(ch)) {
1308             out += this.input.slice(chunkStart, this.state.pos);
1309             ++this.state.pos;
1310             switch (ch) {
1311               case 13:
1312                 if (this.input.charCodeAt(this.state.pos) === 10) ++this.state.pos;
1313               case 10:
1314                 out += "\n";
1315                 break;
1316               default:
1317                 out += String.fromCharCode(ch);
1318                 break;
1319             }
1320             ++this.state.curLine;
1321             this.state.lineStart = this.state.pos;
1322             chunkStart = this.state.pos;
1323           } else {
1324             ++this.state.pos;
1325           }
1326         }
1327       }
1328
1329       // Used to read escaped characters
1330
1331       readEscapedChar(inTemplate) {
1332         const throwOnInvalid = !inTemplate;
1333         const ch = this.input.charCodeAt(++this.state.pos);
1334         ++this.state.pos;
1335         switch (ch) {
1336           case 110: return "\n"; // 'n' -> '\n'
1337           case 114: return "\r"; // 'r' -> '\r'
1338           case 120: { // 'x'
1339             const code = this.readHexChar(2, throwOnInvalid);
1340             return code === null ? null : String.fromCharCode(code);
1341           }
1342           case 117: { // 'u'
1343             const code = this.readCodePoint(throwOnInvalid);
1344             return code === null ? null : codePointToString(code);
1345           }
1346           case 116: return "\t"; // 't' -> '\t'
1347           case 98: return "\b"; // 'b' -> '\b'
1348           case 118: return "\u000b"; // 'v' -> '\u000b'
1349           case 102: return "\f"; // 'f' -> '\f'
1350           case 13: if (this.input.charCodeAt(this.state.pos) === 10) ++this.state.pos; // '\r\n'
1351           case 10: // ' \n'
1352             this.state.lineStart = this.state.pos;
1353             ++this.state.curLine;
1354             return "";
1355           default:
1356             if (ch >= 48 && ch <= 55) {
1357               const codePos = this.state.pos - 1;
1358               let octalStr = this.input.substr(this.state.pos - 1, 3).match(/^[0-7]+/)[0];
1359               let octal = parseInt(octalStr, 8);
1360               if (octal > 255) {
1361                 octalStr = octalStr.slice(0, -1);
1362                 octal = parseInt(octalStr, 8);
1363               }
1364               if (octal > 0) {
1365                 if (inTemplate) {
1366                   this.state.invalidTemplateEscapePosition = codePos;
1367                   return null;
1368                 } else if (this.state.strict) {
1369                   this.raise(codePos, "Octal literal in strict mode");
1370                 } else if (!this.state.containsOctal) {
1371                   // These properties are only used to throw an error for an octal which occurs
1372                   // in a directive which occurs prior to a "use strict" directive.
1373                   this.state.containsOctal = true;
1374                   this.state.octalPosition = codePos;
1375                 }
1376               }
1377               this.state.pos += octalStr.length - 1;
1378               return String.fromCharCode(octal);
1379             }
1380             return String.fromCharCode(ch);
1381         }
1382       }
1383
1384       // Used to read character escape sequences ('\x', '\u').
1385
1386       readHexChar(len, throwOnInvalid) {
1387         const codePos = this.state.pos;
1388         const n = this.readInt(16, len);
1389         if (n === null) {
1390           if (throwOnInvalid) {
1391             this.raise(codePos, "Bad character escape sequence");
1392           } else {
1393             this.state.pos = codePos - 1;
1394             this.state.invalidTemplateEscapePosition = codePos - 1;
1395           }
1396         }
1397         return n;
1398       }
1399
1400       // Read an identifier, and return it as a string. Sets `this.state.containsEsc`
1401       // to whether the word contained a '\u' escape.
1402       //
1403       // Incrementally adds only escaped chars, adding other chunks as-is
1404       // as a micro-optimization.
1405
1406       readWord1() {
1407         this.state.containsEsc = false;
1408         let word = "", first = true, chunkStart = this.state.pos;
1409         while (this.state.pos < this.input.length) {
1410           const ch = this.fullCharCodeAtPos();
1411           if (isIdentifierChar(ch)) {
1412             this.state.pos += ch <= 0xffff ? 1 : 2;
1413           } else if (ch === 92) { // "\"
1414             this.state.containsEsc = true;
1415
1416             word += this.input.slice(chunkStart, this.state.pos);
1417             const escStart = this.state.pos;
1418
1419             if (this.input.charCodeAt(++this.state.pos) !== 117) { // "u"
1420               this.raise(this.state.pos, "Expecting Unicode escape sequence \\uXXXX");
1421             }
1422
1423             ++this.state.pos;
1424             const esc = this.readCodePoint(true);
1425             if (!(first ? isIdentifierStart : isIdentifierChar)(esc, true)) {
1426               this.raise(escStart, "Invalid Unicode escape");
1427             }
1428
1429             word += codePointToString(esc);
1430             chunkStart = this.state.pos;
1431           } else {
1432             break;
1433           }
1434           first = false;
1435         }
1436         return word + this.input.slice(chunkStart, this.state.pos);
1437       }
1438
1439       // Read an identifier or keyword token. Will check for reserved
1440       // words when necessary.
1441
1442       readWord() {
1443         const word = this.readWord1();
1444         let type = tt.name;
1445         if (!this.state.containsEsc && this.isKeyword(word)) {
1446           type = keywordTypes[word];
1447         }
1448         return this.finishToken(type, word);
1449       }
1450
1451       braceIsBlock(prevType) {
1452         if (prevType === tt.colon) {
1453           const parent = this.curContext();
1454           if (parent === ct.braceStatement || parent === ct.braceExpression) {
1455             return !parent.isExpr;
1456           }
1457         }
1458
1459         if (prevType === tt._return) {
1460           return lineBreak.test(this.input.slice(this.state.lastTokEnd, this.state.start));
1461         }
1462
1463         if (prevType === tt._else || prevType === tt.semi || prevType === tt.eof || prevType === tt.parenR) {
1464           return true;
1465         }
1466
1467         if (prevType === tt.braceL) {
1468           return this.curContext() === ct.braceStatement;
1469         }
1470
1471         return !this.state.exprAllowed;
1472       }
1473
1474       updateContext(prevType) {
1475         const type = this.state.type;
1476         let update;
1477
1478         if (type.keyword && prevType === tt.dot) {
1479           this.state.exprAllowed = false;
1480         } else if (update = type.updateContext) {
1481           update.call(this, prevType);
1482         } else {
1483           this.state.exprAllowed = type.beforeExpr;
1484         }
1485       }
1486     }
1487     
1488     tokenizerIndexJS = Tokenizer;
1489     tokenizerIndexJS.Token = Token;
1490 }
1491
1492
1493 // options.js
1494 const optionsJS = {};
1495 {
1496     // A second optional argument can be given to further configure
1497     // the parser process. These options are recognized:
1498
1499     const defaultOptions = {
1500       // Source type ("script" or "module") for different semantics
1501       sourceType: "script",
1502       // Source filename.
1503       sourceFilename: undefined,
1504       // Line from which to start counting source. Useful for
1505       // integration with other tools.
1506       startLine: 1,
1507       // When enabled, a return at the top level is not considered an
1508       // error.
1509       allowReturnOutsideFunction: false,
1510       // When enabled, import/export statements are not constrained to
1511       // appearing at the top of the program.
1512       allowImportExportEverywhere: false,
1513       // TODO
1514       allowSuperOutsideMethod: false,
1515       // An array of plugins to enable
1516       plugins: [],
1517       // TODO
1518       strictMode: null,
1519       // Nodes have their start and end characters offsets recorded in
1520       // `start` and `end` properties (directly on the node, rather than
1521       // the `loc` object, which holds line/column data. To also add a
1522       // [semi-standardized][range] `range` property holding a `[start,
1523       // end]` array with the same numbers, set the `ranges` option to
1524       // `true`.
1525       //
1526       // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678
1527       ranges: false,
1528     };
1529     optionsJS.defaultOptions = defaultOptions;
1530
1531     // Interpret and default an options object
1532
1533     function getOptions(opts) {
1534       const options = {};
1535       for (const key in defaultOptions) {
1536         options[key] = opts && key in opts ? opts[key] : defaultOptions[key];
1537       }
1538       return options;
1539     }
1540     optionsJS.getOptions = getOptions;
1541 }
1542
1543
1544 // parser/index.js
1545 let parserIndexJS = {};
1546 {
1547     const { reservedWords } = utilIdentifierJS;
1548     const { getOptions } = optionsJS;
1549     const Tokenizer = tokenizerIndexJS;
1550
1551     const plugins = {};
1552
1553     class Parser extends Tokenizer {
1554       constructor(options, input) {
1555         options = getOptions(options);
1556         super(options, input);
1557
1558         this.options = options;
1559         this.inModule = this.options.sourceType === "module";
1560         this.input = input;
1561         this.plugins = this.loadPlugins(this.options.plugins);
1562         this.filename = options.sourceFilename;
1563
1564         // If enabled, skip leading hashbang line.
1565         if (this.state.pos === 0 && this.input[0] === "#" && this.input[1] === "!") {
1566           this.skipLineComment(2);
1567         }
1568       }
1569
1570       isReservedWord(word) {
1571         if (word === "await") {
1572           return this.inModule;
1573         } else {
1574           return reservedWords[6](word);
1575         }
1576       }
1577
1578       hasPlugin(name) {
1579         return !!this.plugins[name];
1580       }
1581
1582       extend(name, f) {
1583         this[name] = f(this[name]);
1584       }
1585
1586       loadPlugins(pluginList)  {
1587         const pluginMap = {};
1588
1589         if (pluginList.indexOf("flow") >= 0) {
1590           // ensure flow plugin loads last
1591           pluginList = pluginList.filter((plugin) => plugin !== "flow");
1592           pluginList.push("flow");
1593         }
1594
1595         if (pluginList.indexOf("estree") >= 0) {
1596           // ensure estree plugin loads first
1597           pluginList = pluginList.filter((plugin) => plugin !== "estree");
1598           pluginList.unshift("estree");
1599         }
1600
1601         for (const name of pluginList) {
1602           if (!pluginMap[name]) {
1603             pluginMap[name] = true;
1604
1605             const plugin = plugins[name];
1606             if (plugin) plugin(this);
1607           }
1608         }
1609
1610         return pluginMap;
1611       }
1612
1613       parse() {
1614         const file = this.startNode();
1615         const program = this.startNode();
1616         this.nextToken();
1617         return this.parseTopLevel(file, program);
1618       }
1619     }
1620
1621     parserIndexJS = Parser;
1622     parserIndexJS.plugins = plugins;
1623 }
1624
1625 // parser/comments.js
1626 const parserCommentsJS = {};
1627 {
1628     /* eslint max-len: 0 */
1629
1630     /**
1631      * Based on the comment attachment algorithm used in espree and estraverse.
1632      *
1633      * Redistribution and use in source and binary forms, with or without
1634      * modification, are permitted provided that the following conditions are met:
1635      *
1636      * * Redistributions of source code must retain the above copyright
1637      *   notice, this list of conditions and the following disclaimer.
1638      * * Redistributions in binary form must reproduce the above copyright
1639      *   notice, this list of conditions and the following disclaimer in the
1640      *   documentation and/or other materials provided with the distribution.
1641      *
1642      * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1643      * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1644      * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1645      * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
1646      * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1647      * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1648      * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1649      * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1650      * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
1651      * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1652      */
1653
1654
1655     {
1656         const Parser = parserIndexJS;
1657
1658         function last(stack) {
1659           return stack[stack.length - 1];
1660         }
1661
1662         const pp = Parser.prototype;
1663
1664         pp.addComment = function (comment) {
1665           if (this.filename) comment.loc.filename = this.filename;
1666           this.state.trailingComments.push(comment);
1667           this.state.leadingComments.push(comment);
1668         };
1669
1670         pp.processComment = function (node) {
1671           if (node.type === "Program" && node.body.length > 0) return;
1672
1673           const stack = this.state.commentStack;
1674
1675           let lastChild, trailingComments, i, j;
1676
1677           if (this.state.trailingComments.length > 0) {
1678             // If the first comment in trailingComments comes after the
1679             // current node, then we're good - all comments in the array will
1680             // come after the node and so it's safe to add them as official
1681             // trailingComments.
1682             if (this.state.trailingComments[0].start >= node.end) {
1683               trailingComments = this.state.trailingComments;
1684               this.state.trailingComments = [];
1685             } else {
1686               // Otherwise, if the first comment doesn't come after the
1687               // current node, that means we have a mix of leading and trailing
1688               // comments in the array and that leadingComments contains the
1689               // same items as trailingComments. Reset trailingComments to
1690               // zero items and we'll handle this by evaluating leadingComments
1691               // later.
1692               this.state.trailingComments.length = 0;
1693             }
1694           } else {
1695             const lastInStack = last(stack);
1696             if (stack.length > 0 && lastInStack.trailingComments && lastInStack.trailingComments[0].start >= node.end) {
1697               trailingComments = lastInStack.trailingComments;
1698               lastInStack.trailingComments = null;
1699             }
1700           }
1701
1702           // Eating the stack.
1703           while (stack.length > 0 && last(stack).start >= node.start) {
1704             lastChild = stack.pop();
1705           }
1706
1707           if (lastChild) {
1708             if (lastChild.leadingComments) {
1709               if (lastChild !== node && last(lastChild.leadingComments).end <= node.start) {
1710                 node.leadingComments = lastChild.leadingComments;
1711                 lastChild.leadingComments = null;
1712               } else {
1713                 // A leading comment for an anonymous class had been stolen by its first ClassMethod,
1714                 // so this takes back the leading comment.
1715                 // See also: https://github.com/eslint/espree/issues/158
1716                 for (i = lastChild.leadingComments.length - 2; i >= 0; --i) {
1717                   if (lastChild.leadingComments[i].end <= node.start) {
1718                     node.leadingComments = lastChild.leadingComments.splice(0, i + 1);
1719                     break;
1720                   }
1721                 }
1722               }
1723             }
1724           } else if (this.state.leadingComments.length > 0) {
1725             if (last(this.state.leadingComments).end <= node.start) {
1726               if (this.state.commentPreviousNode) {
1727                 for (j = 0; j < this.state.leadingComments.length; j++) {
1728                   if (this.state.leadingComments[j].end < this.state.commentPreviousNode.end) {
1729                     this.state.leadingComments.splice(j, 1);
1730                     j--;
1731                   }
1732                 }
1733               }
1734               if (this.state.leadingComments.length > 0) {
1735                 node.leadingComments = this.state.leadingComments;
1736                 this.state.leadingComments = [];
1737               }
1738             } else {
1739               // https://github.com/eslint/espree/issues/2
1740               //
1741               // In special cases, such as return (without a value) and
1742               // debugger, all comments will end up as leadingComments and
1743               // will otherwise be eliminated. This step runs when the
1744               // commentStack is empty and there are comments left
1745               // in leadingComments.
1746               //
1747               // This loop figures out the stopping point between the actual
1748               // leading and trailing comments by finding the location of the
1749               // first comment that comes after the given node.
1750               for (i = 0; i < this.state.leadingComments.length; i++) {
1751                 if (this.state.leadingComments[i].end > node.start) {
1752                   break;
1753                 }
1754               }
1755
1756               // Split the array based on the location of the first comment
1757               // that comes after the node. Keep in mind that this could
1758               // result in an empty array, and if so, the array must be
1759               // deleted.
1760               node.leadingComments = this.state.leadingComments.slice(0, i);
1761               if ((node.leadingComments).length === 0) {
1762                 node.leadingComments = null;
1763               }
1764
1765               // Similarly, trailing comments are attached later. The variable
1766               // must be reset to null if there are no trailing comments.
1767               trailingComments = this.state.leadingComments.slice(i);
1768               if (trailingComments.length === 0) {
1769                 trailingComments = null;
1770               }
1771             }
1772           }
1773
1774           this.state.commentPreviousNode = node;
1775
1776           if (trailingComments) {
1777             if (trailingComments.length && trailingComments[0].start >= node.start && last(trailingComments).end <= node.end) {
1778               node.innerComments = trailingComments;
1779             } else {
1780               node.trailingComments = trailingComments;
1781             }
1782           }
1783
1784           stack.push(node);
1785         };
1786     }
1787
1788 }
1789
1790 // parser/expression.js
1791 const parserExpressionJS = {};
1792 {
1793     /* eslint max-len: 0 */
1794
1795     // A recursive descent parser operates by defining functions for all
1796     // syntactic elements, and recursively calling those, each function
1797     // advancing the input stream and returning an AST node. Precedence
1798     // of constructs (for example, the fact that `!x[1]` means `!(x[1])`
1799     // instead of `(!x)[1]` is handled by the fact that the parser
1800     // function that parses unary prefix operators is called first, and
1801     // in turn calls the function that parses `[]` subscripts — that
1802     // way, it'll receive the node for `x[1]` already parsed, and wraps
1803     // *that* in the unary operator node.
1804     //
1805     // Acorn uses an [operator precedence parser][opp] to handle binary
1806     // operator precedence, because it is much more compact than using
1807     // the technique outlined above, which uses different, nesting
1808     // functions to specify precedence, for all of the ten binary
1809     // precedence levels that JavaScript defines.
1810     //
1811     // [opp]: http://en.wikipedia.org/wiki/Operator-precedence_parser
1812
1813     const { types: tt } = tokenizerTypesJS;
1814     const Parser = parserIndexJS;
1815     const { reservedWords } = utilIdentifierJS;
1816
1817     const pp = Parser.prototype;
1818
1819     // Check if property name clashes with already added.
1820     // Object/class getters and setters are not allowed to clash —
1821     // either with each other or with an init property — and in
1822     // strict mode, init properties are also not allowed to be repeated.
1823
1824     pp.checkPropClash = function (prop, propHash) {
1825       if (prop.computed || prop.kind) return;
1826
1827       const key = prop.key;
1828       // It is either an Identifier or a String/NumericLiteral
1829       const name = key.type === "Identifier" ? key.name : String(key.value);
1830
1831       if (name === "__proto__") {
1832         if (propHash.proto) this.raise(key.start, "Redefinition of __proto__ property");
1833         propHash.proto = true;
1834       }
1835     };
1836
1837     // Convenience method to parse an Expression only
1838     pp.getExpression = function() {
1839       this.nextToken();
1840       const expr = this.parseExpression();
1841       if (!this.match(tt.eof)) {
1842         this.unexpected();
1843       }
1844       return expr;
1845     };
1846
1847     // ### Expression parsing
1848
1849     // These nest, from the most general expression type at the top to
1850     // 'atomic', nondivisible expression types at the bottom. Most of
1851     // the functions will simply let the function (s) below them parse,
1852     // and, *if* the syntactic construct they handle is present, wrap
1853     // the AST node that the inner parser gave them in another node.
1854
1855     // Parse a full expression. The optional arguments are used to
1856     // forbid the `in` operator (in for loops initialization expressions)
1857     // and provide reference for storing '=' operator inside shorthand
1858     // property assignment in contexts where both object expression
1859     // and object pattern might appear (so it's possible to raise
1860     // delayed syntax error at correct position).
1861
1862     pp.parseExpression = function (noIn, refShorthandDefaultPos) {
1863       const startPos = this.state.start;
1864       const startLoc = this.state.startLoc;
1865       const expr = this.parseMaybeAssign(noIn, refShorthandDefaultPos);
1866       if (this.match(tt.comma)) {
1867         const node = this.startNodeAt(startPos, startLoc);
1868         node.expressions = [expr];
1869         while (this.eat(tt.comma)) {
1870           node.expressions.push(this.parseMaybeAssign(noIn, refShorthandDefaultPos));
1871         }
1872         this.toReferencedList(node.expressions);
1873         return this.finishNode(node, "SequenceExpression");
1874       }
1875       return expr;
1876     };
1877
1878     // Parse an assignment expression. This includes applications of
1879     // operators like `+=`.
1880
1881     pp.parseMaybeAssign = function (noIn, refShorthandDefaultPos, afterLeftParse, refNeedsArrowPos) {
1882       const startPos = this.state.start;
1883       const startLoc = this.state.startLoc;
1884
1885       if (this.match(tt._yield) && this.state.inGenerator) {
1886         let left = this.parseYield();
1887         if (afterLeftParse) left = afterLeftParse.call(this, left, startPos, startLoc);
1888         return left;
1889       }
1890
1891       let failOnShorthandAssign;
1892       if (refShorthandDefaultPos) {
1893         failOnShorthandAssign = false;
1894       } else {
1895         refShorthandDefaultPos = { start: 0 };
1896         failOnShorthandAssign = true;
1897       }
1898
1899       if (this.match(tt.parenL) || this.match(tt.name)) {
1900         this.state.potentialArrowAt = this.state.start;
1901       }
1902
1903       let left = this.parseMaybeConditional(noIn, refShorthandDefaultPos, refNeedsArrowPos);
1904       if (afterLeftParse) left = afterLeftParse.call(this, left, startPos, startLoc);
1905       if (this.state.type.isAssign) {
1906         const node = this.startNodeAt(startPos, startLoc);
1907         node.operator = this.state.value;
1908         node.left = this.match(tt.eq) ? this.toAssignable(left, undefined, "assignment expression") : left;
1909         refShorthandDefaultPos.start = 0; // reset because shorthand default was used correctly
1910
1911         this.checkLVal(left, undefined, undefined, "assignment expression");
1912
1913         if (left.extra && left.extra.parenthesized) {
1914           let errorMsg;
1915           if (left.type === "ObjectPattern") {
1916             errorMsg = "`({a}) = 0` use `({a} = 0)`";
1917           } else if (left.type === "ArrayPattern") {
1918             errorMsg = "`([a]) = 0` use `([a] = 0)`";
1919           }
1920           if (errorMsg) {
1921             this.raise(left.start, `You're trying to assign to a parenthesized expression, eg. instead of ${errorMsg}`);
1922           }
1923         }
1924
1925         this.next();
1926         node.right = this.parseMaybeAssign(noIn);
1927         return this.finishNode(node, "AssignmentExpression");
1928       } else if (failOnShorthandAssign && refShorthandDefaultPos.start) {
1929         this.unexpected(refShorthandDefaultPos.start);
1930       }
1931
1932       return left;
1933     };
1934
1935     // Parse a ternary conditional (`?:`) operator.
1936
1937     pp.parseMaybeConditional = function (noIn, refShorthandDefaultPos, refNeedsArrowPos) {
1938       const startPos = this.state.start;
1939       const startLoc = this.state.startLoc;
1940       const expr = this.parseExprOps(noIn, refShorthandDefaultPos);
1941       if (refShorthandDefaultPos && refShorthandDefaultPos.start) return expr;
1942
1943       return this.parseConditional(expr, noIn, startPos, startLoc, refNeedsArrowPos);
1944     };
1945
1946     pp.parseConditional = function (expr, noIn, startPos, startLoc) {
1947       if (this.eat(tt.question)) {
1948         const node = this.startNodeAt(startPos, startLoc);
1949         node.test = expr;
1950         node.consequent = this.parseMaybeAssign();
1951         this.expect(tt.colon);
1952         node.alternate = this.parseMaybeAssign(noIn);
1953         return this.finishNode(node, "ConditionalExpression");
1954       }
1955       return expr;
1956     };
1957
1958     // Start the precedence parser.
1959
1960     pp.parseExprOps = function (noIn, refShorthandDefaultPos) {
1961       const startPos = this.state.start;
1962       const startLoc = this.state.startLoc;
1963       const expr = this.parseMaybeUnary(refShorthandDefaultPos);
1964       if (refShorthandDefaultPos && refShorthandDefaultPos.start) {
1965         return expr;
1966       } else {
1967         return this.parseExprOp(expr, startPos, startLoc, -1, noIn);
1968       }
1969     };
1970
1971     // Parse binary operators with the operator precedence parsing
1972     // algorithm. `left` is the left-hand side of the operator.
1973     // `minPrec` provides context that allows the function to stop and
1974     // defer further parser to one of its callers when it encounters an
1975     // operator that has a lower precedence than the set it is parsing.
1976
1977     pp.parseExprOp = function(left, leftStartPos, leftStartLoc, minPrec, noIn) {
1978       const prec = this.state.type.binop;
1979       if (prec != null && (!noIn || !this.match(tt._in))) {
1980         if (prec > minPrec) {
1981           const node = this.startNodeAt(leftStartPos, leftStartLoc);
1982           node.left = left;
1983           node.operator = this.state.value;
1984
1985           if (
1986             node.operator === "**" &&
1987             left.type === "UnaryExpression" &&
1988             left.extra &&
1989             !left.extra.parenthesizedArgument &&
1990             !left.extra.parenthesized
1991           ) {
1992             this.raise(left.argument.start, "Illegal expression. Wrap left hand side or entire exponentiation in parentheses.");
1993           }
1994
1995           const op = this.state.type;
1996           this.next();
1997
1998           const startPos = this.state.start;
1999           const startLoc = this.state.startLoc;
2000           node.right = this.parseExprOp(this.parseMaybeUnary(), startPos, startLoc, op.rightAssociative ? prec - 1 : prec, noIn);
2001
2002           this.finishNode(node, (op === tt.logicalOR || op === tt.logicalAND) ? "LogicalExpression" : "BinaryExpression");
2003           return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, noIn);
2004         }
2005       }
2006       return left;
2007     };
2008
2009     // Parse unary operators, both prefix and postfix.
2010
2011     pp.parseMaybeUnary = function (refShorthandDefaultPos) {
2012       if (this.state.type.prefix) {
2013         const node = this.startNode();
2014         const update = this.match(tt.incDec);
2015         node.operator = this.state.value;
2016         node.prefix = true;
2017         this.next();
2018
2019         const argType = this.state.type;
2020         node.argument = this.parseMaybeUnary();
2021
2022         this.addExtra(node, "parenthesizedArgument", argType === tt.parenL && (!node.argument.extra || !node.argument.extra.parenthesized));
2023
2024         if (refShorthandDefaultPos && refShorthandDefaultPos.start) {
2025           this.unexpected(refShorthandDefaultPos.start);
2026         }
2027
2028         if (update) {
2029           this.checkLVal(node.argument, undefined, undefined, "prefix operation");
2030         } else if (this.state.strict && node.operator === "delete" && node.argument.type === "Identifier") {
2031           this.raise(node.start, "Deleting local variable in strict mode");
2032         }
2033
2034         return this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression");
2035       }
2036
2037       const startPos = this.state.start;
2038       const startLoc = this.state.startLoc;
2039       let expr = this.parseExprSubscripts(refShorthandDefaultPos);
2040       if (refShorthandDefaultPos && refShorthandDefaultPos.start) return expr;
2041       while (this.state.type.postfix && !this.canInsertSemicolon()) {
2042         const node = this.startNodeAt(startPos, startLoc);
2043         node.operator = this.state.value;
2044         node.prefix = false;
2045         node.argument = expr;
2046         this.checkLVal(expr, undefined, undefined, "postfix operation");
2047         this.next();
2048         expr = this.finishNode(node, "UpdateExpression");
2049       }
2050       return expr;
2051     };
2052
2053     // Parse call, dot, and `[]`-subscript expressions.
2054
2055     pp.parseExprSubscripts = function (refShorthandDefaultPos) {
2056       const startPos = this.state.start;
2057       const startLoc = this.state.startLoc;
2058       const potentialArrowAt = this.state.potentialArrowAt;
2059       const expr = this.parseExprAtom(refShorthandDefaultPos);
2060
2061       if (expr.type === "ArrowFunctionExpression" && expr.start === potentialArrowAt) {
2062         return expr;
2063       }
2064
2065       if (refShorthandDefaultPos && refShorthandDefaultPos.start) {
2066         return expr;
2067       }
2068
2069       return this.parseSubscripts(expr, startPos, startLoc);
2070     };
2071
2072     pp.parseSubscripts = function (base, startPos, startLoc, noCalls) {
2073       for (;;) {
2074         if (!noCalls && this.eat(tt.doubleColon)) {
2075           const node = this.startNodeAt(startPos, startLoc);
2076           node.object = base;
2077           node.callee = this.parseNoCallExpr();
2078           return this.parseSubscripts(this.finishNode(node, "BindExpression"), startPos, startLoc, noCalls);
2079         } else if (this.eat(tt.dot)) {
2080           const node = this.startNodeAt(startPos, startLoc);
2081           node.object = base;
2082           node.property = this.parseIdentifier(true);
2083           node.computed = false;
2084           base = this.finishNode(node, "MemberExpression");
2085         } else if (this.eat(tt.bracketL)) {
2086           const node = this.startNodeAt(startPos, startLoc);
2087           node.object = base;
2088           node.property = this.parseExpression();
2089           node.computed = true;
2090           this.expect(tt.bracketR);
2091           base = this.finishNode(node, "MemberExpression");
2092         } else if (!noCalls && this.match(tt.parenL)) {
2093           const possibleAsync = this.state.potentialArrowAt === base.start && base.type === "Identifier" && base.name === "async" && !this.canInsertSemicolon();
2094           this.next();
2095
2096           const node = this.startNodeAt(startPos, startLoc);
2097           node.callee = base;
2098           node.arguments = this.parseCallExpressionArguments(tt.parenR, possibleAsync);
2099           if (node.callee.type === "Import" && node.arguments.length !== 1) {
2100             this.raise(node.start, "import() requires exactly one argument");
2101           }
2102           base = this.finishNode(node, "CallExpression");
2103
2104           if (possibleAsync && this.shouldParseAsyncArrow()) {
2105             return this.parseAsyncArrowFromCallExpression(this.startNodeAt(startPos, startLoc), node);
2106           } else {
2107             this.toReferencedList(node.arguments);
2108           }
2109         } else if (this.match(tt.backQuote)) {
2110           const node = this.startNodeAt(startPos, startLoc);
2111           node.tag = base;
2112           node.quasi = this.parseTemplate(true);
2113           base = this.finishNode(node, "TaggedTemplateExpression");
2114         } else {
2115           return base;
2116         }
2117       }
2118     };
2119
2120     pp.parseCallExpressionArguments = function (close, possibleAsyncArrow) {
2121       const elts = [];
2122       let innerParenStart;
2123       let first = true;
2124
2125       while (!this.eat(close)) {
2126         if (first) {
2127           first = false;
2128         } else {
2129           this.expect(tt.comma);
2130           if (this.eat(close)) break;
2131         }
2132
2133         // we need to make sure that if this is an async arrow functions, that we don't allow inner parens inside the params
2134         if (this.match(tt.parenL) && !innerParenStart) {
2135           innerParenStart = this.state.start;
2136         }
2137
2138         elts.push(this.parseExprListItem(false, possibleAsyncArrow ? { start: 0 } : undefined, possibleAsyncArrow ? { start: 0 } : undefined));
2139       }
2140
2141       // we found an async arrow function so let's not allow any inner parens
2142       if (possibleAsyncArrow && innerParenStart && this.shouldParseAsyncArrow()) {
2143         this.unexpected();
2144       }
2145
2146       return elts;
2147     };
2148
2149     pp.shouldParseAsyncArrow = function () {
2150       return this.match(tt.arrow);
2151     };
2152
2153     pp.parseAsyncArrowFromCallExpression = function (node, call) {
2154       this.expect(tt.arrow);
2155       return this.parseArrowExpression(node, call.arguments, true);
2156     };
2157
2158     // Parse a no-call expression (like argument of `new` or `::` operators).
2159
2160     pp.parseNoCallExpr = function () {
2161       const startPos = this.state.start;
2162       const startLoc = this.state.startLoc;
2163       return this.parseSubscripts(this.parseExprAtom(), startPos, startLoc, true);
2164     };
2165
2166     // Parse an atomic expression — either a single token that is an
2167     // expression, an expression started by a keyword like `function` or
2168     // `new`, or an expression wrapped in punctuation like `()`, `[]`,
2169     // or `{}`.
2170
2171     pp.parseExprAtom = function (refShorthandDefaultPos) {
2172       const canBeArrow = this.state.potentialArrowAt === this.state.start;
2173       let node;
2174
2175       switch (this.state.type) {
2176         case tt._super:
2177           if (!this.state.inMethod && !this.options.allowSuperOutsideMethod) {
2178             this.raise(this.state.start, "'super' outside of function or class");
2179           }
2180
2181           node = this.startNode();
2182           this.next();
2183           if (!this.match(tt.parenL) && !this.match(tt.bracketL) && !this.match(tt.dot)) {
2184             this.unexpected();
2185           }
2186           if (this.match(tt.parenL) && this.state.inMethod !== "constructor" && !this.options.allowSuperOutsideMethod) {
2187             this.raise(node.start, "super() is only valid inside a class constructor. Make sure the method name is spelled exactly as 'constructor'.");
2188           }
2189           return this.finishNode(node, "Super");
2190
2191         case tt._import:
2192           if (!this.hasPlugin("dynamicImport")) this.unexpected();
2193
2194           node = this.startNode();
2195           this.next();
2196           if (!this.match(tt.parenL)) {
2197             this.unexpected(null, tt.parenL);
2198           }
2199           return this.finishNode(node, "Import");
2200
2201         case tt._this:
2202           node = this.startNode();
2203           this.next();
2204           return this.finishNode(node, "ThisExpression");
2205
2206         case tt._yield:
2207           if (this.state.inGenerator) this.unexpected();
2208
2209         case tt.name:
2210           node = this.startNode();
2211           const allowAwait = this.state.value === "await" && this.state.inAsync;
2212           const allowYield = this.shouldAllowYieldIdentifier();
2213           const id = this.parseIdentifier(allowAwait || allowYield);
2214
2215           if (id.name === "await") {
2216             if (this.state.inAsync || this.inModule) {
2217               return this.parseAwait(node);
2218             }
2219           } else if (id.name === "async" && this.match(tt._function) && !this.canInsertSemicolon()) {
2220             this.next();
2221             return this.parseFunction(node, false, false, true);
2222           } else if (canBeArrow && id.name === "async" && this.match(tt.name)) {
2223             const params = [this.parseIdentifier()];
2224             this.expect(tt.arrow);
2225             // let foo = bar => {};
2226             return this.parseArrowExpression(node, params, true);
2227           }
2228
2229           if (canBeArrow && !this.canInsertSemicolon() && this.eat(tt.arrow)) {
2230             return this.parseArrowExpression(node, [id]);
2231           }
2232
2233           return id;
2234
2235         case tt._do:
2236           if (this.hasPlugin("doExpressions")) {
2237             const node = this.startNode();
2238             this.next();
2239             const oldInFunction = this.state.inFunction;
2240             const oldLabels = this.state.labels;
2241             this.state.labels = [];
2242             this.state.inFunction = false;
2243             node.body = this.parseBlock(false, true);
2244             this.state.inFunction = oldInFunction;
2245             this.state.labels = oldLabels;
2246             return this.finishNode(node, "DoExpression");
2247           }
2248
2249         case tt.regexp:
2250           const value = this.state.value;
2251           node = this.parseLiteral(value.value, "RegExpLiteral");
2252           node.pattern = value.pattern;
2253           node.flags = value.flags;
2254           return node;
2255
2256         case tt.num:
2257           return this.parseLiteral(this.state.value, "NumericLiteral");
2258
2259         case tt.string:
2260           return this.parseLiteral(this.state.value, "StringLiteral");
2261
2262         case tt._null:
2263           node = this.startNode();
2264           this.next();
2265           return this.finishNode(node, "NullLiteral");
2266
2267         case tt._true: case tt._false:
2268           node = this.startNode();
2269           node.value = this.match(tt._true);
2270           this.next();
2271           return this.finishNode(node, "BooleanLiteral");
2272
2273         case tt.parenL:
2274           return this.parseParenAndDistinguishExpression(null, null, canBeArrow);
2275
2276         case tt.bracketL:
2277           node = this.startNode();
2278           this.next();
2279           node.elements = this.parseExprList(tt.bracketR, true, refShorthandDefaultPos);
2280           this.toReferencedList(node.elements);
2281           return this.finishNode(node, "ArrayExpression");
2282
2283         case tt.braceL:
2284           return this.parseObj(false, refShorthandDefaultPos);
2285
2286         case tt._function:
2287           return this.parseFunctionExpression();
2288
2289         case tt.at:
2290           this.parseDecorators();
2291
2292         case tt._class:
2293           node = this.startNode();
2294           this.takeDecorators(node);
2295           return this.parseClass(node, false);
2296
2297         case tt._new:
2298           return this.parseNew();
2299
2300         case tt.backQuote:
2301           return this.parseTemplate(false);
2302
2303         case tt.doubleColon:
2304           node = this.startNode();
2305           this.next();
2306           node.object = null;
2307           const callee = node.callee = this.parseNoCallExpr();
2308           if (callee.type === "MemberExpression") {
2309             return this.finishNode(node, "BindExpression");
2310           } else {
2311             this.raise(callee.start, "Binding should be performed on object property.");
2312           }
2313
2314         default:
2315           this.unexpected();
2316       }
2317     };
2318
2319     pp.parseFunctionExpression = function () {
2320       const node = this.startNode();
2321       const meta = this.parseIdentifier(true);
2322       if (this.state.inGenerator && this.eat(tt.dot) && this.hasPlugin("functionSent")) {
2323         return this.parseMetaProperty(node, meta, "sent");
2324       } else {
2325         return this.parseFunction(node, false);
2326       }
2327     };
2328
2329     pp.parseMetaProperty = function (node, meta, propertyName) {
2330       node.meta = meta;
2331       node.property = this.parseIdentifier(true);
2332
2333       if (node.property.name !== propertyName) {
2334         this.raise(node.property.start, `The only valid meta property for new is ${meta.name}.${propertyName}`);
2335       }
2336
2337       return this.finishNode(node, "MetaProperty");
2338     };
2339
2340     pp.parseLiteral = function (value, type, startPos, startLoc) {
2341       startPos = startPos || this.state.start;
2342       startLoc = startLoc || this.state.startLoc;
2343
2344       const node = this.startNodeAt(startPos, startLoc);
2345       this.addExtra(node, "rawValue", value);
2346       this.addExtra(node, "raw", this.input.slice(startPos, this.state.end));
2347       node.value = value;
2348       this.next();
2349       return this.finishNode(node, type);
2350     };
2351
2352     pp.parseParenExpression = function () {
2353       this.expect(tt.parenL);
2354       const val = this.parseExpression();
2355       this.expect(tt.parenR);
2356       return val;
2357     };
2358
2359     pp.parseParenAndDistinguishExpression = function (startPos, startLoc, canBeArrow) {
2360       startPos = startPos || this.state.start;
2361       startLoc = startLoc || this.state.startLoc;
2362
2363       let val;
2364       this.expect(tt.parenL);
2365
2366       const innerStartPos = this.state.start;
2367       const innerStartLoc = this.state.startLoc;
2368       const exprList = [];
2369       const refShorthandDefaultPos = { start: 0 };
2370       const refNeedsArrowPos = { start: 0 };
2371       let first = true;
2372       let spreadStart;
2373       let optionalCommaStart;
2374
2375       while (!this.match(tt.parenR)) {
2376         if (first) {
2377           first = false;
2378         } else {
2379           this.expect(tt.comma, refNeedsArrowPos.start || null);
2380           if (this.match(tt.parenR)) {
2381             optionalCommaStart = this.state.start;
2382             break;
2383           }
2384         }
2385
2386         if (this.match(tt.ellipsis)) {
2387           const spreadNodeStartPos = this.state.start;
2388           const spreadNodeStartLoc = this.state.startLoc;
2389           spreadStart = this.state.start;
2390           exprList.push(this.parseParenItem(this.parseRest(), spreadNodeStartPos, spreadNodeStartLoc));
2391           break;
2392         } else {
2393           exprList.push(this.parseMaybeAssign(false, refShorthandDefaultPos, this.parseParenItem, refNeedsArrowPos));
2394         }
2395       }
2396
2397       const innerEndPos = this.state.start;
2398       const innerEndLoc = this.state.startLoc;
2399       this.expect(tt.parenR);
2400
2401       let arrowNode = this.startNodeAt(startPos, startLoc);
2402       if (canBeArrow && this.shouldParseArrow() && (arrowNode = this.parseArrow(arrowNode))) {
2403         for (const param of exprList) {
2404           if (param.extra && param.extra.parenthesized) this.unexpected(param.extra.parenStart);
2405         }
2406
2407         return this.parseArrowExpression(arrowNode, exprList);
2408       }
2409
2410       if (!exprList.length) {
2411         this.unexpected(this.state.lastTokStart);
2412       }
2413       if (optionalCommaStart) this.unexpected(optionalCommaStart);
2414       if (spreadStart) this.unexpected(spreadStart);
2415       if (refShorthandDefaultPos.start) this.unexpected(refShorthandDefaultPos.start);
2416       if (refNeedsArrowPos.start) this.unexpected(refNeedsArrowPos.start);
2417
2418       if (exprList.length > 1) {
2419         val = this.startNodeAt(innerStartPos, innerStartLoc);
2420         val.expressions = exprList;
2421         this.toReferencedList(val.expressions);
2422         this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc);
2423       } else {
2424         val = exprList[0];
2425       }
2426
2427
2428       this.addExtra(val, "parenthesized", true);
2429       this.addExtra(val, "parenStart", startPos);
2430
2431       return val;
2432     };
2433
2434     pp.shouldParseArrow = function () {
2435       return !this.canInsertSemicolon();
2436     };
2437
2438     pp.parseArrow = function (node) {
2439       if (this.eat(tt.arrow)) {
2440         return node;
2441       }
2442     };
2443
2444     pp.parseParenItem = function (node) {
2445       return node;
2446     };
2447
2448     // New's precedence is slightly tricky. It must allow its argument
2449     // to be a `[]` or dot subscript expression, but not a call — at
2450     // least, not without wrapping it in parentheses. Thus, it uses the
2451
2452     pp.parseNew = function () {
2453       const node = this.startNode();
2454       const meta = this.parseIdentifier(true);
2455
2456       if (this.eat(tt.dot)) {
2457         const metaProp = this.parseMetaProperty(node, meta, "target");
2458
2459         if (!this.state.inFunction) {
2460           this.raise(metaProp.property.start, "new.target can only be used in functions");
2461         }
2462
2463         return metaProp;
2464       }
2465
2466       node.callee = this.parseNoCallExpr();
2467
2468       if (this.eat(tt.parenL)) {
2469         node.arguments = this.parseExprList(tt.parenR);
2470         this.toReferencedList(node.arguments);
2471       } else {
2472         node.arguments = [];
2473       }
2474
2475       return this.finishNode(node, "NewExpression");
2476     };
2477
2478     // Parse template expression.
2479
2480     pp.parseTemplateElement = function (isTagged) {
2481       const elem = this.startNode();
2482       if (this.state.value === null) {
2483         if (!isTagged) {
2484           this.raise(this.state.invalidTemplateEscapePosition, "Invalid escape sequence in template");
2485         } else {
2486           this.state.invalidTemplateEscapePosition = null;
2487         }
2488       }
2489       elem.value = {
2490         raw: this.input.slice(this.state.start, this.state.end).replace(/\r\n?/g, "\n"),
2491         cooked: this.state.value
2492       };
2493       this.next();
2494       elem.tail = this.match(tt.backQuote);
2495       return this.finishNode(elem, "TemplateElement");
2496     };
2497
2498     pp.parseTemplate = function (isTagged) {
2499       const node = this.startNode();
2500       this.next();
2501       node.expressions = [];
2502       let curElt = this.parseTemplateElement(isTagged);
2503       node.quasis = [curElt];
2504       while (!curElt.tail) {
2505         this.expect(tt.dollarBraceL);
2506         node.expressions.push(this.parseExpression());
2507         this.expect(tt.braceR);
2508         node.quasis.push(curElt = this.parseTemplateElement(isTagged));
2509       }
2510       this.next();
2511       return this.finishNode(node, "TemplateLiteral");
2512     };
2513
2514     // Parse an object literal or binding pattern.
2515
2516     pp.parseObj = function (isPattern, refShorthandDefaultPos) {
2517       let decorators = [];
2518       const propHash = Object.create(null);
2519       let first = true;
2520       const node = this.startNode();
2521
2522       node.properties = [];
2523       this.next();
2524
2525       let firstRestLocation = null;
2526
2527       while (!this.eat(tt.braceR)) {
2528         if (first) {
2529           first = false;
2530         } else {
2531           this.expect(tt.comma);
2532           if (this.eat(tt.braceR)) break;
2533         }
2534
2535         while (this.match(tt.at)) {
2536           decorators.push(this.parseDecorator());
2537         }
2538
2539         let prop = this.startNode(), isGenerator = false, isAsync = false, startPos, startLoc;
2540         if (decorators.length) {
2541           prop.decorators = decorators;
2542           decorators = [];
2543         }
2544
2545         if (this.hasPlugin("objectRestSpread") && this.match(tt.ellipsis)) {
2546           prop = this.parseSpread(isPattern ? { start: 0 } : undefined);
2547           prop.type = isPattern ? "RestElement" : "SpreadElement";
2548           if (isPattern) this.toAssignable(prop.argument, true, "object pattern");
2549           node.properties.push(prop);
2550           if (isPattern) {
2551             const position = this.state.start;
2552             if (firstRestLocation !== null) {
2553               this.unexpected(firstRestLocation, "Cannot have multiple rest elements when destructuring");
2554             } else if (this.eat(tt.braceR)) {
2555               break;
2556             } else if (this.match(tt.comma) && this.lookahead().type === tt.braceR) {
2557               this.unexpected(position, "A trailing comma is not permitted after the rest element");
2558             } else {
2559               firstRestLocation = position;
2560               continue;
2561             }
2562           } else {
2563             continue;
2564           }
2565         }
2566
2567         prop.method = false;
2568         prop.shorthand = false;
2569
2570         if (isPattern || refShorthandDefaultPos) {
2571           startPos = this.state.start;
2572           startLoc = this.state.startLoc;
2573         }
2574
2575         if (!isPattern) {
2576           isGenerator = this.eat(tt.star);
2577         }
2578
2579         if (!isPattern && this.isContextual("async")) {
2580           if (isGenerator) this.unexpected();
2581
2582           const asyncId = this.parseIdentifier();
2583           if (this.match(tt.colon) || this.match(tt.parenL) || this.match(tt.braceR) || this.match(tt.eq) || this.match(tt.comma)) {
2584             prop.key = asyncId;
2585             prop.computed = false;
2586           } else {
2587             isAsync = true;
2588             if (this.hasPlugin("asyncGenerators")) isGenerator = this.eat(tt.star);
2589             this.parsePropertyName(prop);
2590           }
2591         } else {
2592           this.parsePropertyName(prop);
2593         }
2594
2595         this.parseObjPropValue(prop, startPos, startLoc, isGenerator, isAsync, isPattern, refShorthandDefaultPos);
2596         this.checkPropClash(prop, propHash);
2597
2598         if (prop.shorthand) {
2599           this.addExtra(prop, "shorthand", true);
2600         }
2601
2602         node.properties.push(prop);
2603       }
2604
2605       if (firstRestLocation !== null) {
2606         this.unexpected(firstRestLocation, "The rest element has to be the last element when destructuring");
2607       }
2608
2609       if (decorators.length) {
2610         this.raise(this.state.start, "You have trailing decorators with no property");
2611       }
2612
2613       return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression");
2614     };
2615
2616     pp.isGetterOrSetterMethod = function (prop, isPattern) {
2617       return !isPattern &&
2618         !prop.computed &&
2619         prop.key.type === "Identifier" &&
2620         (prop.key.name === "get" || prop.key.name === "set") &&
2621         (
2622           this.match(tt.string) || // get "string"() {}
2623           this.match(tt.num) || // get 1() {}
2624           this.match(tt.bracketL) || // get ["string"]() {}
2625           this.match(tt.name) || // get foo() {}
2626           this.state.type.keyword // get debugger() {}
2627         );
2628     };
2629
2630     // get methods aren't allowed to have any parameters
2631     // set methods must have exactly 1 parameter
2632     pp.checkGetterSetterParamCount = function (method) {
2633       const paramCount = method.kind === "get" ? 0 : 1;
2634       if (method.params.length !== paramCount) {
2635         const start = method.start;
2636         if (method.kind === "get") {
2637           this.raise(start, "getter should have no params");
2638         } else {
2639           this.raise(start, "setter should have exactly one param");
2640         }
2641       }
2642     };
2643
2644     pp.parseObjectMethod = function (prop, isGenerator, isAsync, isPattern) {
2645       if (isAsync || isGenerator || this.match(tt.parenL)) {
2646         if (isPattern) this.unexpected();
2647         prop.kind = "method";
2648         prop.method = true;
2649         this.parseMethod(prop, isGenerator, isAsync);
2650
2651         return this.finishNode(prop, "ObjectMethod");
2652       }
2653
2654       if (this.isGetterOrSetterMethod(prop, isPattern)) {
2655         if (isGenerator || isAsync) this.unexpected();
2656         prop.kind = prop.key.name;
2657         this.parsePropertyName(prop);
2658         this.parseMethod(prop);
2659         this.checkGetterSetterParamCount(prop);
2660
2661         return this.finishNode(prop, "ObjectMethod");
2662       }
2663     };
2664
2665     pp.parseObjectProperty = function (prop, startPos, startLoc, isPattern, refShorthandDefaultPos) {
2666       if (this.eat(tt.colon)) {
2667         prop.value = isPattern ? this.parseMaybeDefault(this.state.start, this.state.startLoc) : this.parseMaybeAssign(false, refShorthandDefaultPos);
2668
2669         return this.finishNode(prop, "ObjectProperty");
2670       }
2671
2672       if (!prop.computed && prop.key.type === "Identifier") {
2673         if (isPattern) {
2674           this.checkReservedWord(prop.key.name, prop.key.start, true, true);
2675           prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key.__clone());
2676         } else if (this.match(tt.eq) && refShorthandDefaultPos) {
2677           if (!refShorthandDefaultPos.start) {
2678             refShorthandDefaultPos.start = this.state.start;
2679           }
2680           prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key.__clone());
2681         } else {
2682           prop.value = prop.key.__clone();
2683         }
2684         prop.shorthand = true;
2685
2686         return this.finishNode(prop, "ObjectProperty");
2687       }
2688     };
2689
2690     pp.parseObjPropValue = function (prop, startPos, startLoc, isGenerator, isAsync, isPattern, refShorthandDefaultPos) {
2691       const node =
2692         this.parseObjectMethod(prop, isGenerator, isAsync, isPattern) ||
2693         this.parseObjectProperty(prop, startPos, startLoc, isPattern, refShorthandDefaultPos);
2694
2695       if (!node) this.unexpected();
2696
2697       return node;
2698     };
2699
2700     pp.parsePropertyName = function (prop) {
2701       if (this.eat(tt.bracketL)) {
2702         prop.computed = true;
2703         prop.key = this.parseMaybeAssign();
2704         this.expect(tt.bracketR);
2705       } else {
2706         prop.computed = false;
2707         const oldInPropertyName = this.state.inPropertyName;
2708         this.state.inPropertyName = true;
2709         prop.key = (this.match(tt.num) || this.match(tt.string)) ? this.parseExprAtom() : this.parseIdentifier(true);
2710         this.state.inPropertyName = oldInPropertyName;
2711       }
2712       return prop.key;
2713     };
2714
2715     // Initialize empty function node.
2716
2717     pp.initFunction = function (node, isAsync) {
2718       node.id = null;
2719       node.generator = false;
2720       node.expression = false;
2721       node.async = !!isAsync;
2722     };
2723
2724     // Parse object or class method.
2725
2726     pp.parseMethod = function (node, isGenerator, isAsync) {
2727       const oldInMethod = this.state.inMethod;
2728       this.state.inMethod = node.kind || true;
2729       this.initFunction(node, isAsync);
2730       this.expect(tt.parenL);
2731       node.params = this.parseBindingList(tt.parenR);
2732       node.generator = !!isGenerator;
2733       this.parseFunctionBody(node);
2734       this.state.inMethod = oldInMethod;
2735       return node;
2736     };
2737
2738     // Parse arrow function expression with given parameters.
2739
2740     pp.parseArrowExpression = function (node, params, isAsync) {
2741       this.initFunction(node, isAsync);
2742       node.params = this.toAssignableList(params, true, "arrow function parameters");
2743       this.parseFunctionBody(node, true);
2744       return this.finishNode(node, "ArrowFunctionExpression");
2745     };
2746
2747     pp.isStrictBody = function (node, isExpression) {
2748       if (!isExpression && node.body.directives.length) {
2749         for (const directive of (node.body.directives)) {
2750           if (directive.value.value === "use strict") {
2751             return true;
2752           }
2753         }
2754       }
2755
2756       return false;
2757     };
2758
2759     // Parse function body and check parameters.
2760     pp.parseFunctionBody = function (node, allowExpression) {
2761       const isExpression = allowExpression && !this.match(tt.braceL);
2762
2763       const oldInAsync = this.state.inAsync;
2764       this.state.inAsync = node.async;
2765       if (isExpression) {
2766         node.body = this.parseMaybeAssign();
2767         node.expression = true;
2768       } else {
2769         // Start a new scope with regard to labels and the `inFunction`
2770         // flag (restore them to their old value afterwards).
2771         const oldInFunc = this.state.inFunction;
2772         const oldInGen = this.state.inGenerator;
2773         const oldLabels = this.state.labels;
2774         this.state.inFunction = true; this.state.inGenerator = node.generator; this.state.labels = [];
2775         node.body = this.parseBlock(true);
2776         node.expression = false;
2777         this.state.inFunction = oldInFunc; this.state.inGenerator = oldInGen; this.state.labels = oldLabels;
2778       }
2779       this.state.inAsync = oldInAsync;
2780
2781       // If this is a strict mode function, verify that argument names
2782       // are not repeated, and it does not try to bind the words `eval`
2783       // or `arguments`.
2784       const isStrict = this.isStrictBody(node, isExpression);
2785       // Also check when allowExpression === true for arrow functions
2786       const checkLVal = this.state.strict || allowExpression || isStrict;
2787
2788       if (isStrict && node.id && node.id.type === "Identifier" && node.id.name === "yield") {
2789         this.raise(node.id.start, "Binding yield in strict mode");
2790       }
2791
2792       if (checkLVal) {
2793         const nameHash = Object.create(null);
2794         const oldStrict = this.state.strict;
2795         if (isStrict) this.state.strict = true;
2796         if (node.id) {
2797           this.checkLVal(node.id, true, undefined, "function name");
2798         }
2799         for (const param of (node.params)) {
2800           if (isStrict && param.type !== "Identifier") {
2801             this.raise(param.start, "Non-simple parameter in strict mode");
2802           }
2803           this.checkLVal(param, true, nameHash, "function parameter list");
2804         }
2805         this.state.strict = oldStrict;
2806       }
2807     };
2808
2809     // Parses a comma-separated list of expressions, and returns them as
2810     // an array. `close` is the token type that ends the list, and
2811     // `allowEmpty` can be turned on to allow subsequent commas with
2812     // nothing in between them to be parsed as `null` (which is needed
2813     // for array literals).
2814
2815     pp.parseExprList = function (close, allowEmpty, refShorthandDefaultPos) {
2816       const elts = [];
2817       let first = true;
2818
2819       while (!this.eat(close)) {
2820         if (first) {
2821           first = false;
2822         } else {
2823           this.expect(tt.comma);
2824           if (this.eat(close)) break;
2825         }
2826
2827         elts.push(this.parseExprListItem(allowEmpty, refShorthandDefaultPos));
2828       }
2829       return elts;
2830     };
2831
2832     pp.parseExprListItem = function (allowEmpty, refShorthandDefaultPos, refNeedsArrowPos) {
2833       let elt;
2834       if (allowEmpty && this.match(tt.comma)) {
2835         elt = null;
2836       } else if (this.match(tt.ellipsis)) {
2837         elt = this.parseSpread(refShorthandDefaultPos);
2838       } else {
2839         elt = this.parseMaybeAssign(false, refShorthandDefaultPos, this.parseParenItem, refNeedsArrowPos);
2840       }
2841       return elt;
2842     };
2843
2844     // Parse the next token as an identifier. If `liberal` is true (used
2845     // when parsing properties), it will also convert keywords into
2846     // identifiers.
2847
2848     pp.parseIdentifier = function (liberal) {
2849       const node = this.startNode();
2850       if (!liberal) {
2851         this.checkReservedWord(this.state.value, this.state.start, !!this.state.type.keyword, false);
2852       }
2853
2854       if (this.match(tt.name)) {
2855         node.name = this.state.value;
2856       } else if (this.state.type.keyword) {
2857         node.name = this.state.type.keyword;
2858       } else {
2859         this.unexpected();
2860       }
2861
2862       if (!liberal && node.name === "await" && this.state.inAsync) {
2863         this.raise(node.start, "invalid use of await inside of an async function");
2864       }
2865
2866       node.loc.identifierName = node.name;
2867
2868       this.next();
2869       return this.finishNode(node, "Identifier");
2870     };
2871
2872     pp.checkReservedWord = function (word, startLoc, checkKeywords, isBinding) {
2873       if (this.isReservedWord(word) || (checkKeywords && this.isKeyword(word))) {
2874         this.raise(startLoc, word + " is a reserved word");
2875       }
2876
2877       if (this.state.strict && (reservedWords.strict(word) || (isBinding && reservedWords.strictBind(word)))) {
2878         this.raise(startLoc, word + " is a reserved word in strict mode");
2879       }
2880     };
2881
2882     // Parses await expression inside async function.
2883
2884     pp.parseAwait = function (node) {
2885       // istanbul ignore next: this condition is checked at the call site so won't be hit here
2886       if (!this.state.inAsync) {
2887         this.unexpected();
2888       }
2889       if (this.match(tt.star)) {
2890         this.raise(node.start, "await* has been removed from the async functions proposal. Use Promise.all() instead.");
2891       }
2892       node.argument = this.parseMaybeUnary();
2893       return this.finishNode(node, "AwaitExpression");
2894     };
2895
2896     // Parses yield expression inside generator.
2897
2898     pp.parseYield = function () {
2899       const node = this.startNode();
2900       this.next();
2901       if (
2902         this.match(tt.semi) ||
2903         this.canInsertSemicolon() ||
2904         (!this.match(tt.star) && !this.state.type.startsExpr)
2905       ) {
2906         node.delegate = false;
2907         node.argument = null;
2908       } else {
2909         node.delegate = this.eat(tt.star);
2910         node.argument = this.parseMaybeAssign();
2911       }
2912       return this.finishNode(node, "YieldExpression");
2913     };
2914
2915 }
2916
2917 // parser/location.js
2918 const parserLocationJS = {};
2919 {
2920     const { getLineInfo } = utilLocationJS;
2921     const Parser = parserIndexJS;
2922
2923     const pp = Parser.prototype;
2924
2925     // This function is used to raise exceptions on parse errors. It
2926     // takes an offset integer (into the current `input`) to indicate
2927     // the location of the error, attaches the position to the end
2928     // of the error message, and then raises a `SyntaxError` with that
2929     // message.
2930
2931     pp.raise = function (pos, message) {
2932       const loc = getLineInfo(this.input, pos);
2933       message += ` (${loc.line}:${loc.column})`;
2934       const err = new SyntaxError(message);
2935       err.pos = pos;
2936       err.loc = loc;
2937       throw err;
2938     };
2939 }
2940
2941 // parser/lval.js
2942 const parserLvalJS = {};
2943 {
2944     const { types: tt } = tokenizerTypesJS;
2945     const Parser = parserIndexJS;
2946
2947     const pp = Parser.prototype;
2948
2949     // Convert existing expression atom to assignable pattern
2950     // if possible.
2951
2952     pp.toAssignable = function (node, isBinding, contextDescription) {
2953       if (node) {
2954         switch (node.type) {
2955           case "Identifier":
2956           case "ObjectPattern":
2957           case "ArrayPattern":
2958           case "AssignmentPattern":
2959             break;
2960
2961           case "ObjectExpression":
2962             node.type = "ObjectPattern";
2963             for (const prop of (node.properties)) {
2964               if (prop.type === "ObjectMethod") {
2965                 if (prop.kind === "get" || prop.kind === "set") {
2966                   this.raise(prop.key.start, "Object pattern can't contain getter or setter");
2967                 } else {
2968                   this.raise(prop.key.start, "Object pattern can't contain methods");
2969                 }
2970               } else {
2971                 this.toAssignable(prop, isBinding, "object destructuring pattern");
2972               }
2973             }
2974             break;
2975
2976           case "ObjectProperty":
2977             this.toAssignable(node.value, isBinding, contextDescription);
2978             break;
2979
2980           case "SpreadElement":
2981             node.type = "RestElement";
2982             break;
2983
2984           case "ArrayExpression":
2985             node.type = "ArrayPattern";
2986             this.toAssignableList(node.elements, isBinding, contextDescription);
2987             break;
2988
2989           case "AssignmentExpression":
2990             if (node.operator === "=") {
2991               node.type = "AssignmentPattern";
2992               delete node.operator;
2993             } else {
2994               this.raise(node.left.end, "Only '=' operator can be used for specifying default value.");
2995             }
2996             break;
2997
2998           case "MemberExpression":
2999             if (!isBinding) break;
3000
3001           default: {
3002             const message = "Invalid left-hand side" +
3003               (contextDescription ? " in " + contextDescription : /* istanbul ignore next */ "expression");
3004             this.raise(node.start, message);
3005           }
3006         }
3007       }
3008       return node;
3009     };
3010
3011     // Convert list of expression atoms to binding list.
3012
3013     pp.toAssignableList = function (exprList, isBinding, contextDescription) {
3014       let end = exprList.length;
3015       if (end) {
3016         const last = exprList[end - 1];
3017         if (last && last.type === "RestElement") {
3018           --end;
3019         } else if (last && last.type === "SpreadElement") {
3020           last.type = "RestElement";
3021           const arg = last.argument;
3022           this.toAssignable(arg, isBinding, contextDescription);
3023           if (arg.type !== "Identifier" && arg.type !== "MemberExpression" && arg.type !== "ArrayPattern") {
3024             this.unexpected(arg.start);
3025           }
3026           --end;
3027         }
3028       }
3029       for (let i = 0; i < end; i++) {
3030         const elt = exprList[i];
3031         if (elt && elt.type === "SpreadElement")
3032           this.raise(elt.start, "The rest element has to be the last element when destructuring");
3033         if (elt) this.toAssignable(elt, isBinding, contextDescription);
3034       }
3035       return exprList;
3036     };
3037
3038     // Convert list of expression atoms to a list of
3039
3040     pp.toReferencedList = function (exprList) {
3041       return exprList;
3042     };
3043
3044     // Parses spread element.
3045
3046     pp.parseSpread = function (refShorthandDefaultPos) {
3047       const node = this.startNode();
3048       this.next();
3049       node.argument = this.parseMaybeAssign(false, refShorthandDefaultPos);
3050       return this.finishNode(node, "SpreadElement");
3051     };
3052
3053     pp.parseRest = function () {
3054       const node = this.startNode();
3055       this.next();
3056       node.argument = this.parseBindingIdentifier();
3057       return this.finishNode(node, "RestElement");
3058     };
3059
3060     pp.shouldAllowYieldIdentifier = function () {
3061       return this.match(tt._yield) && !this.state.strict && !this.state.inGenerator;
3062     };
3063
3064     pp.parseBindingIdentifier = function () {
3065       return this.parseIdentifier(this.shouldAllowYieldIdentifier());
3066     };
3067
3068     // Parses lvalue (assignable) atom.
3069
3070     pp.parseBindingAtom = function () {
3071       switch (this.state.type) {
3072         case tt._yield:
3073           if (this.state.strict || this.state.inGenerator) this.unexpected();
3074           // fall-through
3075         case tt.name:
3076           return this.parseIdentifier(true);
3077
3078         case tt.bracketL:
3079           const node = this.startNode();
3080           this.next();
3081           node.elements = this.parseBindingList(tt.bracketR, true);
3082           return this.finishNode(node, "ArrayPattern");
3083
3084         case tt.braceL:
3085           return this.parseObj(true);
3086
3087         default:
3088           this.unexpected();
3089       }
3090     };
3091
3092     pp.parseBindingList = function (close, allowEmpty) {
3093       const elts = [];
3094       let first = true;
3095       while (!this.eat(close)) {
3096         if (first) {
3097           first = false;
3098         } else {
3099           this.expect(tt.comma);
3100         }
3101         if (allowEmpty && this.match(tt.comma)) {
3102           elts.push(null);
3103         } else if (this.eat(close)) {
3104           break;
3105         } else if (this.match(tt.ellipsis)) {
3106           elts.push(this.parseAssignableListItemTypes(this.parseRest()));
3107           this.expect(close);
3108           break;
3109         } else {
3110           const decorators = [];
3111           while (this.match(tt.at)) {
3112             decorators.push(this.parseDecorator());
3113           }
3114           const left = this.parseMaybeDefault();
3115           if (decorators.length) {
3116             left.decorators = decorators;
3117           }
3118           this.parseAssignableListItemTypes(left);
3119           elts.push(this.parseMaybeDefault(left.start, left.loc.start, left));
3120         }
3121       }
3122       return elts;
3123     };
3124
3125     pp.parseAssignableListItemTypes = function (param) {
3126       return param;
3127     };
3128
3129     // Parses assignment pattern around given atom if possible.
3130
3131     pp.parseMaybeDefault = function (startPos, startLoc, left) {
3132       startLoc = startLoc || this.state.startLoc;
3133       startPos = startPos || this.state.start;
3134       left = left || this.parseBindingAtom();
3135       if (!this.eat(tt.eq)) return left;
3136
3137       const node = this.startNodeAt(startPos, startLoc);
3138       node.left = left;
3139       node.right = this.parseMaybeAssign();
3140       return this.finishNode(node, "AssignmentPattern");
3141     };
3142
3143     // Verify that a node is an lval — something that can be assigned
3144     // to.
3145
3146     pp.checkLVal = function (expr, isBinding, checkClashes, contextDescription) {
3147       switch (expr.type) {
3148         case "Identifier":
3149           this.checkReservedWord(expr.name, expr.start, false, true);
3150
3151           if (checkClashes) {
3152             // we need to prefix this with an underscore for the cases where we have a key of
3153             // `__proto__`. there's a bug in old V8 where the following wouldn't work:
3154             //
3155             //   > var obj = Object.create(null);
3156             //   undefined
3157             //   > obj.__proto__
3158             //   null
3159             //   > obj.__proto__ = true;
3160             //   true
3161             //   > obj.__proto__
3162             //   null
3163             const key = `_${expr.name}`;
3164
3165             if (checkClashes[key]) {
3166               this.raise(expr.start, "Argument name clash in strict mode");
3167             } else {
3168               checkClashes[key] = true;
3169             }
3170           }
3171           break;
3172
3173         case "MemberExpression":
3174           if (isBinding) this.raise(expr.start, (isBinding ? "Binding" : "Assigning to") + " member expression");
3175           break;
3176
3177         case "ObjectPattern":
3178           for (let prop of (expr.properties)) {
3179             if (prop.type === "ObjectProperty") prop = prop.value;
3180             this.checkLVal(prop, isBinding, checkClashes, "object destructuring pattern");
3181           }
3182           break;
3183