UNPKG

orionsoft-react-scripts

Version:

Orionsoft Configuration and scripts for Create React App.

1,199 lines (1,040 loc) 113 kB
// Reserved word lists for various dialects of the language var reservedWords = { 3: "abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile", 5: "class enum extends super const export import", 6: "enum", 7: "enum", strict: "implements interface let package private protected public static yield", strictBind: "eval arguments" } // And the keywords var ecma5AndLessKeywords = "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" var keywords = { 5: ecma5AndLessKeywords, 6: ecma5AndLessKeywords + " const class extends export import super" } // ## Character categories // Big ugly regular expressions that match characters in the // whitespace, identifier, and identifier-start categories. These // are only applied when a character is found to actually have a // code point above 128. // Generated by `bin/generate-identifier-regex.js`. var 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" var 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" var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]") var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]") nonASCIIidentifierStartChars = nonASCIIidentifierChars = null // These are a run-length and offset encoded representation of the // >0xffff code points that are a valid part of identifiers. The // offset starts at 0x10000, and each pair of numbers represents an // offset to the next range, and then a size of the range. They were // generated by bin/generate-identifier-regex.js var 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] var 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] // This has a complexity linear to the value of the code. The // assumption is that looking up astral identifier characters is // rare. function isInAstralSet(code, set) { var pos = 0x10000 for (var i = 0; i < set.length; i += 2) { pos += set[i] if (pos > code) return false pos += set[i + 1] if (pos >= code) return true } } // Test whether a given character code starts an identifier. function isIdentifierStart(code, astral) { if (code < 65) return code === 36 if (code < 91) return true if (code < 97) return code === 95 if (code < 123) return true if (code <= 0xffff) return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)) if (astral === false) return false return isInAstralSet(code, astralIdentifierStartCodes) } // Test whether a given character is part of an identifier. function isIdentifierChar(code, astral) { if (code < 48) return code === 36 if (code < 58) return true if (code < 65) return false if (code < 91) return true if (code < 97) return code === 95 if (code < 123) return true if (code <= 0xffff) return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)) if (astral === false) return false return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes) } // ## Token types // The assignment of fine-grained, information-carrying type objects // allows the tokenizer to store the information it has about a // token in a way that is very cheap for the parser to look up. // All token type variables start with an underscore, to make them // easy to recognize. // The `beforeExpr` property is used to disambiguate between regular // expressions and divisions. It is set on all token types that can // be followed by an expression (thus, a slash after them would be a // regular expression). // // The `startsExpr` property is used to check if the token ends a // `yield` expression. It is set on all token types that either can // directly start an expression (like a quotation mark) or can // continue an expression (like the body of a string). // // `isLoop` marks a keyword as starting a loop, which is important // to know when parsing a label, in order to allow or disallow // continue jumps to that label. var TokenType = function TokenType(label, conf) { if ( conf === void 0 ) conf = {}; this.label = label this.keyword = conf.keyword this.beforeExpr = !!conf.beforeExpr this.startsExpr = !!conf.startsExpr this.isLoop = !!conf.isLoop this.isAssign = !!conf.isAssign this.prefix = !!conf.prefix this.postfix = !!conf.postfix this.binop = conf.binop || null this.updateContext = null }; function binop(name, prec) { return new TokenType(name, {beforeExpr: true, binop: prec}) } var beforeExpr = {beforeExpr: true}; var startsExpr = {startsExpr: true}; // Map keyword names to token types. var keywordTypes = {} // Succinct definitions of keyword token types function kw(name, options) { if ( options === void 0 ) options = {}; options.keyword = name return keywordTypes[name] = new TokenType(name, options) } var tt = { num: new TokenType("num", startsExpr), regexp: new TokenType("regexp", startsExpr), string: new TokenType("string", startsExpr), name: new TokenType("name", startsExpr), eof: new TokenType("eof"), // Punctuation token types. bracketL: new TokenType("[", {beforeExpr: true, startsExpr: true}), bracketR: new TokenType("]"), braceL: new TokenType("{", {beforeExpr: true, startsExpr: true}), braceR: new TokenType("}"), parenL: new TokenType("(", {beforeExpr: true, startsExpr: true}), parenR: new TokenType(")"), comma: new TokenType(",", beforeExpr), semi: new TokenType(";", beforeExpr), colon: new TokenType(":", beforeExpr), dot: new TokenType("."), question: new TokenType("?", beforeExpr), arrow: new TokenType("=>", beforeExpr), template: new TokenType("template"), ellipsis: new TokenType("...", beforeExpr), backQuote: new TokenType("`", startsExpr), dollarBraceL: new TokenType("${", {beforeExpr: true, startsExpr: true}), // Operators. These carry several kinds of properties to help the // parser use them properly (the presence of these properties is // what categorizes them as operators). // // `binop`, when present, specifies that this operator is a binary // operator, and will refer to its precedence. // // `prefix` and `postfix` mark the operator as a prefix or postfix // unary operator. // // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as // binary operators with a very low precedence, that should result // in AssignmentExpression nodes. eq: new TokenType("=", {beforeExpr: true, isAssign: true}), assign: new TokenType("_=", {beforeExpr: true, isAssign: true}), incDec: new TokenType("++/--", {prefix: true, postfix: true, startsExpr: true}), prefix: new TokenType("prefix", {beforeExpr: true, prefix: true, startsExpr: true}), logicalOR: binop("||", 1), logicalAND: binop("&&", 2), bitwiseOR: binop("|", 3), bitwiseXOR: binop("^", 4), bitwiseAND: binop("&", 5), equality: binop("==/!=", 6), relational: binop("</>", 7), bitShift: binop("<</>>", 8), plusMin: new TokenType("+/-", {beforeExpr: true, binop: 9, prefix: true, startsExpr: true}), modulo: binop("%", 10), star: binop("*", 10), slash: binop("/", 10), starstar: new TokenType("**", {beforeExpr: true}), // Keyword token types. _break: kw("break"), _case: kw("case", beforeExpr), _catch: kw("catch"), _continue: kw("continue"), _debugger: kw("debugger"), _default: kw("default", beforeExpr), _do: kw("do", {isLoop: true, beforeExpr: true}), _else: kw("else", beforeExpr), _finally: kw("finally"), _for: kw("for", {isLoop: true}), _function: kw("function", startsExpr), _if: kw("if"), _return: kw("return", beforeExpr), _switch: kw("switch"), _throw: kw("throw", beforeExpr), _try: kw("try"), _var: kw("var"), _const: kw("const"), _while: kw("while", {isLoop: true}), _with: kw("with"), _new: kw("new", {beforeExpr: true, startsExpr: true}), _this: kw("this", startsExpr), _super: kw("super", startsExpr), _class: kw("class"), _extends: kw("extends", beforeExpr), _export: kw("export"), _import: kw("import"), _null: kw("null", startsExpr), _true: kw("true", startsExpr), _false: kw("false", startsExpr), _in: kw("in", {beforeExpr: true, binop: 7}), _instanceof: kw("instanceof", {beforeExpr: true, binop: 7}), _typeof: kw("typeof", {beforeExpr: true, prefix: true, startsExpr: true}), _void: kw("void", {beforeExpr: true, prefix: true, startsExpr: true}), _delete: kw("delete", {beforeExpr: true, prefix: true, startsExpr: true}) } // Matches a whole line break (where CRLF is considered a single // line break). Used to count lines. var lineBreak = /\r\n?|\n|\u2028|\u2029/ var lineBreakG = new RegExp(lineBreak.source, "g") function isNewLine(code) { return code === 10 || code === 13 || code === 0x2028 || code == 0x2029 } var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/ var skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g function isArray(obj) { return Object.prototype.toString.call(obj) === "[object Array]" } // Checks if an object has a property. function has(obj, propName) { return Object.prototype.hasOwnProperty.call(obj, propName) } // These are used when `options.locations` is on, for the // `startLoc` and `endLoc` properties. var Position = function Position(line, col) { this.line = line this.column = col }; Position.prototype.offset = function offset (n) { return new Position(this.line, this.column + n) }; var SourceLocation = function SourceLocation(p, start, end) { this.start = start this.end = end if (p.sourceFile !== null) this.source = p.sourceFile }; // The `getLineInfo` function is mostly useful when the // `locations` option is off (for performance reasons) and you // want to find the line/column position for a given character // offset. `input` should be the code string that the offset refers // into. function getLineInfo(input, offset) { for (var line = 1, cur = 0;;) { lineBreakG.lastIndex = cur var match = lineBreakG.exec(input) if (match && match.index < offset) { ++line cur = match.index + match[0].length } else { return new Position(line, offset - cur) } } } // A second optional argument can be given to further configure // the parser process. These options are recognized: var defaultOptions = { // `ecmaVersion` indicates the ECMAScript version to parse. Must // be either 3, or 5, or 6. This influences support for strict // mode, the set of reserved words, support for getters and // setters and other features. The default is 6. ecmaVersion: 6, // Source type ("script" or "module") for different semantics sourceType: "script", // `onInsertedSemicolon` can be a callback that will be called // when a semicolon is automatically inserted. It will be passed // th position of the comma as an offset, and if `locations` is // enabled, it is given the location as a `{line, column}` object // as second argument. onInsertedSemicolon: null, // `onTrailingComma` is similar to `onInsertedSemicolon`, but for // trailing commas. onTrailingComma: null, // By default, reserved words are only enforced if ecmaVersion >= 5. // Set `allowReserved` to a boolean value to explicitly turn this on // an off. When this option has the value "never", reserved words // and keywords can also not be used as property names. allowReserved: null, // When enabled, a return at the top level is not considered an // error. allowReturnOutsideFunction: false, // When enabled, import/export statements are not constrained to // appearing at the top of the program. allowImportExportEverywhere: false, // When enabled, hashbang directive in the beginning of file // is allowed and treated as a line comment. allowHashBang: false, // When `locations` is on, `loc` properties holding objects with // `start` and `end` properties in `{line, column}` form (with // line being 1-based and column 0-based) will be attached to the // nodes. locations: false, // A function can be passed as `onToken` option, which will // cause Acorn to call that function with object in the same // format as tokens returned from `tokenizer().getToken()`. Note // that you are not allowed to call the parser from the // callback—that will corrupt its internal state. onToken: null, // A function can be passed as `onComment` option, which will // cause Acorn to call that function with `(block, text, start, // end)` parameters whenever a comment is skipped. `block` is a // boolean indicating whether this is a block (`/* */`) comment, // `text` is the content of the comment, and `start` and `end` are // character offsets that denote the start and end of the comment. // When the `locations` option is on, two more parameters are // passed, the full `{line, column}` locations of the start and // end of the comments. Note that you are not allowed to call the // parser from the callback—that will corrupt its internal state. onComment: null, // Nodes have their start and end characters offsets recorded in // `start` and `end` properties (directly on the node, rather than // the `loc` object, which holds line/column data. To also add a // [semi-standardized][range] `range` property holding a `[start, // end]` array with the same numbers, set the `ranges` option to // `true`. // // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678 ranges: false, // It is possible to parse multiple files into a single AST by // passing the tree produced by parsing the first file as // `program` option in subsequent parses. This will add the // toplevel forms of the parsed file to the `Program` (top) node // of an existing parse tree. program: null, // When `locations` is on, you can pass this to record the source // file in every node's `loc` object. sourceFile: null, // This value, if given, is stored in every node, whether // `locations` is on or off. directSourceFile: null, // When enabled, parenthesized expressions are represented by // (non-standard) ParenthesizedExpression nodes preserveParens: false, plugins: {} } // Interpret and default an options object function getOptions(opts) { var options = {} for (var opt in defaultOptions) options[opt] = opts && has(opts, opt) ? opts[opt] : defaultOptions[opt] if (options.allowReserved == null) options.allowReserved = options.ecmaVersion < 5 if (isArray(options.onToken)) { var tokens = options.onToken options.onToken = function (token) { return tokens.push(token); } } if (isArray(options.onComment)) options.onComment = pushComment(options, options.onComment) return options } function pushComment(options, array) { return function (block, text, start, end, startLoc, endLoc) { var comment = { type: block ? 'Block' : 'Line', value: text, start: start, end: end } if (options.locations) comment.loc = new SourceLocation(this, startLoc, endLoc) if (options.ranges) comment.range = [start, end] array.push(comment) } } // Registered plugins var plugins = {} function keywordRegexp(words) { return new RegExp("^(" + words.replace(/ /g, "|") + ")$") } var Parser = function Parser(options, input, startPos) { this.options = options = getOptions(options) this.sourceFile = options.sourceFile this.keywords = keywordRegexp(keywords[options.ecmaVersion >= 6 ? 6 : 5]) var reserved = options.allowReserved ? "" : reservedWords[options.ecmaVersion] + (options.sourceType == "module" ? " await" : "") this.reservedWords = keywordRegexp(reserved) var reservedStrict = (reserved ? reserved + " " : "") + reservedWords.strict this.reservedWordsStrict = keywordRegexp(reservedStrict) this.reservedWordsStrictBind = keywordRegexp(reservedStrict + " " + reservedWords.strictBind) this.input = String(input) // Used to signal to callers of `readWord1` whether the word // contained any escape sequences. This is needed because words with // escape sequences must not be interpreted as keywords. this.containsEsc = false // Load plugins this.loadPlugins(options.plugins) // Set up token state // The current position of the tokenizer in the input. if (startPos) { this.pos = startPos this.lineStart = Math.max(0, this.input.lastIndexOf("\n", startPos)) this.curLine = this.input.slice(0, this.lineStart).split(lineBreak).length } else { this.pos = this.lineStart = 0 this.curLine = 1 } // Properties of the current token: // Its type this.type = tt.eof // For tokens that include more information than their type, the value this.value = null // Its start and end offset this.start = this.end = this.pos // And, if locations are used, the {line, column} object // corresponding to those offsets this.startLoc = this.endLoc = this.curPosition() // Position information for the previous token this.lastTokEndLoc = this.lastTokStartLoc = null this.lastTokStart = this.lastTokEnd = this.pos // The context stack is used to superficially track syntactic // context to predict whether a regular expression is allowed in a // given position. this.context = this.initialContext() this.exprAllowed = true // Figure out if it's a module code. this.strict = this.inModule = options.sourceType === "module" // Used to signify the start of a potential arrow function this.potentialArrowAt = -1 // Flags to track whether we are in a function, a generator. this.inFunction = this.inGenerator = false // Labels in scope. this.labels = [] // If enabled, skip leading hashbang line. if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === '#!') this.skipLineComment(2) }; // DEPRECATED Kept for backwards compatibility until 3.0 in case a plugin uses them Parser.prototype.isKeyword = function isKeyword (word) { return this.keywords.test(word) }; Parser.prototype.isReservedWord = function isReservedWord (word) { return this.reservedWords.test(word) }; Parser.prototype.extend = function extend (name, f) { this[name] = f(this[name]) }; Parser.prototype.loadPlugins = function loadPlugins (pluginConfigs) { var this$1 = this; for (var name in pluginConfigs) { var plugin = plugins[name] if (!plugin) throw new Error("Plugin '" + name + "' not found") plugin(this$1, pluginConfigs[name]) } }; Parser.prototype.parse = function parse () { var node = this.options.program || this.startNode() this.nextToken() return this.parseTopLevel(node) }; var pp = Parser.prototype // ## Parser utilities // Test whether a statement node is the string literal `"use strict"`. pp.isUseStrict = function(stmt) { return this.options.ecmaVersion >= 5 && stmt.type === "ExpressionStatement" && stmt.expression.type === "Literal" && stmt.expression.raw.slice(1, -1) === "use strict" } // Predicate that tests whether the next token is of the given // type, and if yes, consumes it as a side effect. pp.eat = function(type) { if (this.type === type) { this.next() return true } else { return false } } // Tests whether parsed token is a contextual keyword. pp.isContextual = function(name) { return this.type === tt.name && this.value === name } // Consumes contextual keyword if possible. pp.eatContextual = function(name) { return this.value === name && this.eat(tt.name) } // Asserts that following token is given contextual keyword. pp.expectContextual = function(name) { if (!this.eatContextual(name)) this.unexpected() } // Test whether a semicolon can be inserted at the current position. pp.canInsertSemicolon = function() { return this.type === tt.eof || this.type === tt.braceR || lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) } pp.insertSemicolon = function() { if (this.canInsertSemicolon()) { if (this.options.onInsertedSemicolon) this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc) return true } } // Consume a semicolon, or, failing that, see if we are allowed to // pretend that there is a semicolon at this position. pp.semicolon = function() { if (!this.eat(tt.semi) && !this.insertSemicolon()) this.unexpected() } pp.afterTrailingComma = function(tokType) { if (this.type == tokType) { if (this.options.onTrailingComma) this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc) this.next() return true } } // Expect a token of a given type. If found, consume it, otherwise, // raise an unexpected token error. pp.expect = function(type) { this.eat(type) || this.unexpected() } // Raise an unexpected token error. pp.unexpected = function(pos) { this.raise(pos != null ? pos : this.start, "Unexpected token") } var DestructuringErrors = function DestructuringErrors() { this.shorthandAssign = 0 this.trailingComma = 0 }; pp.checkPatternErrors = function(refDestructuringErrors, andThrow) { var trailing = refDestructuringErrors && refDestructuringErrors.trailingComma if (!andThrow) return !!trailing if (trailing) this.raise(trailing, "Comma is not permitted after the rest element") } pp.checkExpressionErrors = function(refDestructuringErrors, andThrow) { var pos = refDestructuringErrors && refDestructuringErrors.shorthandAssign if (!andThrow) return !!pos if (pos) this.raise(pos, "Shorthand property assignments are valid only in destructuring patterns") } var pp$1 = Parser.prototype // ### Statement parsing // Parse a program. Initializes the parser, reads any number of // statements, and wraps them in a Program node. Optionally takes a // `program` argument. If present, the statements will be appended // to its body instead of creating a new node. pp$1.parseTopLevel = function(node) { var this$1 = this; var first = true if (!node.body) node.body = [] while (this.type !== tt.eof) { var stmt = this$1.parseStatement(true, true) node.body.push(stmt) if (first) { if (this$1.isUseStrict(stmt)) this$1.setStrict(true) first = false } } this.next() if (this.options.ecmaVersion >= 6) { node.sourceType = this.options.sourceType } return this.finishNode(node, "Program") } var loopLabel = {kind: "loop"}; var switchLabel = {kind: "switch"}; pp$1.isLet = function() { if (this.type !== tt.name || this.options.ecmaVersion < 6 || this.value != "let") return false skipWhiteSpace.lastIndex = this.pos var skip = skipWhiteSpace.exec(this.input) var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next) if (nextCh === 91 || nextCh == 123) return true // '{' and '[' if (isIdentifierStart(nextCh, true)) { for (var pos = next + 1; isIdentifierChar(this.input.charCodeAt(pos), true); ++pos) {} var ident = this.input.slice(next, pos) if (!this.isKeyword(ident)) return true } return false } // Parse a single statement. // // If expecting a statement and finding a slash operator, parse a // regular expression literal. This is to handle cases like // `if (foo) /blah/.exec(foo)`, where looking at the previous token // does not help. pp$1.parseStatement = function(declaration, topLevel) { var starttype = this.type, node = this.startNode(), kind if (this.isLet()) { starttype = tt._var kind = "let" } // Most types of statements are recognized by the keyword they // start with. Many are trivial to parse, some require a bit of // complexity. switch (starttype) { case tt._break: case tt._continue: return this.parseBreakContinueStatement(node, starttype.keyword) case tt._debugger: return this.parseDebuggerStatement(node) case tt._do: return this.parseDoStatement(node) case tt._for: return this.parseForStatement(node) case tt._function: if (!declaration && this.options.ecmaVersion >= 6) this.unexpected() return this.parseFunctionStatement(node) case tt._class: if (!declaration) this.unexpected() return this.parseClass(node, true) case tt._if: return this.parseIfStatement(node) case tt._return: return this.parseReturnStatement(node) case tt._switch: return this.parseSwitchStatement(node) case tt._throw: return this.parseThrowStatement(node) case tt._try: return this.parseTryStatement(node) case tt._const: case tt._var: kind = kind || this.value if (!declaration && kind != "var") this.unexpected() return this.parseVarStatement(node, kind) case tt._while: return this.parseWhileStatement(node) case tt._with: return this.parseWithStatement(node) case tt.braceL: return this.parseBlock() case tt.semi: return this.parseEmptyStatement(node) case tt._export: case tt._import: if (!this.options.allowImportExportEverywhere) { if (!topLevel) this.raise(this.start, "'import' and 'export' may only appear at the top level") if (!this.inModule) this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'") } return starttype === tt._import ? this.parseImport(node) : this.parseExport(node) // If the statement does not start with a statement keyword or a // brace, it's an ExpressionStatement or LabeledStatement. We // simply start parsing an expression, and afterwards, if the // next token is a colon and the expression was a simple // Identifier node, we switch to interpreting it as a label. default: var maybeName = this.value, expr = this.parseExpression() if (starttype === tt.name && expr.type === "Identifier" && this.eat(tt.colon)) return this.parseLabeledStatement(node, maybeName, expr) else return this.parseExpressionStatement(node, expr) } } pp$1.parseBreakContinueStatement = function(node, keyword) { var this$1 = this; var isBreak = keyword == "break" this.next() if (this.eat(tt.semi) || this.insertSemicolon()) node.label = null else if (this.type !== tt.name) this.unexpected() else { node.label = this.parseIdent() this.semicolon() } // Verify that there is an actual destination to break or // continue to. for (var i = 0; i < this.labels.length; ++i) { var lab = this$1.labels[i] if (node.label == null || lab.name === node.label.name) { if (lab.kind != null && (isBreak || lab.kind === "loop")) break if (node.label && isBreak) break } } if (i === this.labels.length) this.raise(node.start, "Unsyntactic " + keyword) return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement") } pp$1.parseDebuggerStatement = function(node) { this.next() this.semicolon() return this.finishNode(node, "DebuggerStatement") } pp$1.parseDoStatement = function(node) { this.next() this.labels.push(loopLabel) node.body = this.parseStatement(false) this.labels.pop() this.expect(tt._while) node.test = this.parseParenExpression() if (this.options.ecmaVersion >= 6) this.eat(tt.semi) else this.semicolon() return this.finishNode(node, "DoWhileStatement") } // Disambiguating between a `for` and a `for`/`in` or `for`/`of` // loop is non-trivial. Basically, we have to parse the init `var` // statement or expression, disallowing the `in` operator (see // the second parameter to `parseExpression`), and then check // whether the next token is `in` or `of`. When there is no init // part (semicolon immediately after the opening parenthesis), it // is a regular `for` loop. pp$1.parseForStatement = function(node) { this.next() this.labels.push(loopLabel) this.expect(tt.parenL) if (this.type === tt.semi) return this.parseFor(node, null) var isLet = this.isLet() if (this.type === tt._var || this.type === tt._const || isLet) { var init$1 = this.startNode(), kind = isLet ? "let" : this.value this.next() this.parseVar(init$1, true, kind) this.finishNode(init$1, "VariableDeclaration") if ((this.type === tt._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) && init$1.declarations.length === 1 && !(kind !== "var" && init$1.declarations[0].init)) return this.parseForIn(node, init$1) return this.parseFor(node, init$1) } var refDestructuringErrors = new DestructuringErrors var init = this.parseExpression(true, refDestructuringErrors) if (this.type === tt._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) { this.checkPatternErrors(refDestructuringErrors, true) this.toAssignable(init) this.checkLVal(init) return this.parseForIn(node, init) } else { this.checkExpressionErrors(refDestructuringErrors, true) } return this.parseFor(node, init) } pp$1.parseFunctionStatement = function(node) { this.next() return this.parseFunction(node, true) } pp$1.parseIfStatement = function(node) { this.next() node.test = this.parseParenExpression() node.consequent = this.parseStatement(false) node.alternate = this.eat(tt._else) ? this.parseStatement(false) : null return this.finishNode(node, "IfStatement") } pp$1.parseReturnStatement = function(node) { if (!this.inFunction && !this.options.allowReturnOutsideFunction) this.raise(this.start, "'return' outside of function") this.next() // In `return` (and `break`/`continue`), the keywords with // optional arguments, we eagerly look for a semicolon or the // possibility to insert one. if (this.eat(tt.semi) || this.insertSemicolon()) node.argument = null else { node.argument = this.parseExpression(); this.semicolon() } return this.finishNode(node, "ReturnStatement") } pp$1.parseSwitchStatement = function(node) { var this$1 = this; this.next() node.discriminant = this.parseParenExpression() node.cases = [] this.expect(tt.braceL) this.labels.push(switchLabel) // Statements under must be grouped (by label) in SwitchCase // nodes. `cur` is used to keep the node that we are currently // adding statements to. for (var cur, sawDefault = false; this.type != tt.braceR;) { if (this$1.type === tt._case || this$1.type === tt._default) { var isCase = this$1.type === tt._case if (cur) this$1.finishNode(cur, "SwitchCase") node.cases.push(cur = this$1.startNode()) cur.consequent = [] this$1.next() if (isCase) { cur.test = this$1.parseExpression() } else { if (sawDefault) this$1.raiseRecoverable(this$1.lastTokStart, "Multiple default clauses") sawDefault = true cur.test = null } this$1.expect(tt.colon) } else { if (!cur) this$1.unexpected() cur.consequent.push(this$1.parseStatement(true)) } } if (cur) this.finishNode(cur, "SwitchCase") this.next() // Closing brace this.labels.pop() return this.finishNode(node, "SwitchStatement") } pp$1.parseThrowStatement = function(node) { this.next() if (lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) this.raise(this.lastTokEnd, "Illegal newline after throw") node.argument = this.parseExpression() this.semicolon() return this.finishNode(node, "ThrowStatement") } // Reused empty array added for node fields that are always empty. var empty = [] pp$1.parseTryStatement = function(node) { this.next() node.block = this.parseBlock() node.handler = null if (this.type === tt._catch) { var clause = this.startNode() this.next() this.expect(tt.parenL) clause.param = this.parseBindingAtom() this.checkLVal(clause.param, true) this.expect(tt.parenR) clause.body = this.parseBlock() node.handler = this.finishNode(clause, "CatchClause") } node.finalizer = this.eat(tt._finally) ? this.parseBlock() : null if (!node.handler && !node.finalizer) this.raise(node.start, "Missing catch or finally clause") return this.finishNode(node, "TryStatement") } pp$1.parseVarStatement = function(node, kind) { this.next() this.parseVar(node, false, kind) this.semicolon() return this.finishNode(node, "VariableDeclaration") } pp$1.parseWhileStatement = function(node) { this.next() node.test = this.parseParenExpression() this.labels.push(loopLabel) node.body = this.parseStatement(false) this.labels.pop() return this.finishNode(node, "WhileStatement") } pp$1.parseWithStatement = function(node) { if (this.strict) this.raise(this.start, "'with' in strict mode") this.next() node.object = this.parseParenExpression() node.body = this.parseStatement(false) return this.finishNode(node, "WithStatement") } pp$1.parseEmptyStatement = function(node) { this.next() return this.finishNode(node, "EmptyStatement") } pp$1.parseLabeledStatement = function(node, maybeName, expr) { var this$1 = this; for (var i = 0; i < this.labels.length; ++i) if (this$1.labels[i].name === maybeName) this$1.raise(expr.start, "Label '" + maybeName + "' is already declared") var kind = this.type.isLoop ? "loop" : this.type === tt._switch ? "switch" : null for (var i$1 = this.labels.length - 1; i$1 >= 0; i$1--) { var label = this$1.labels[i$1] if (label.statementStart == node.start) { label.statementStart = this$1.start label.kind = kind } else break } this.labels.push({name: maybeName, kind: kind, statementStart: this.start}) node.body = this.parseStatement(true) this.labels.pop() node.label = expr return this.finishNode(node, "LabeledStatement") } pp$1.parseExpressionStatement = function(node, expr) { node.expression = expr this.semicolon() return this.finishNode(node, "ExpressionStatement") } // Parse a semicolon-enclosed block of statements, handling `"use // strict"` declarations when `allowStrict` is true (used for // function bodies). pp$1.parseBlock = function(allowStrict) { var this$1 = this; var node = this.startNode(), first = true, oldStrict node.body = [] this.expect(tt.braceL) while (!this.eat(tt.braceR)) { var stmt = this$1.parseStatement(true) node.body.push(stmt) if (first && allowStrict && this$1.isUseStrict(stmt)) { oldStrict = this$1.strict this$1.setStrict(this$1.strict = true) } first = false } if (oldStrict === false) this.setStrict(false) return this.finishNode(node, "BlockStatement") } // Parse a regular `for` loop. The disambiguation code in // `parseStatement` will already have parsed the init statement or // expression. pp$1.parseFor = function(node, init) { node.init = init this.expect(tt.semi) node.test = this.type === tt.semi ? null : this.parseExpression() this.expect(tt.semi) node.update = this.type === tt.parenR ? null : this.parseExpression() this.expect(tt.parenR) node.body = this.parseStatement(false) this.labels.pop() return this.finishNode(node, "ForStatement") } // Parse a `for`/`in` and `for`/`of` loop, which are almost // same from parser's perspective. pp$1.parseForIn = function(node, init) { var type = this.type === tt._in ? "ForInStatement" : "ForOfStatement" this.next() node.left = init node.right = this.parseExpression() this.expect(tt.parenR) node.body = this.parseStatement(false) this.labels.pop() return this.finishNode(node, type) } // Parse a list of variable declarations. pp$1.parseVar = function(node, isFor, kind) { var this$1 = this; node.declarations = [] node.kind = kind for (;;) { var decl = this$1.startNode() this$1.parseVarId(decl) if (this$1.eat(tt.eq)) { decl.init = this$1.parseMaybeAssign(isFor) } else if (kind === "const" && !(this$1.type === tt._in || (this$1.options.ecmaVersion >= 6 && this$1.isContextual("of")))) { this$1.unexpected() } else if (decl.id.type != "Identifier" && !(isFor && (this$1.type === tt._in || this$1.isContextual("of")))) { this$1.raise(this$1.lastTokEnd, "Complex binding patterns require an initialization value") } else { decl.init = null } node.declarations.push(this$1.finishNode(decl, "VariableDeclarator")) if (!this$1.eat(tt.comma)) break } return node } pp$1.parseVarId = function(decl) { decl.id = this.parseBindingAtom() this.checkLVal(decl.id, true) } // Parse a function declaration or literal (depending on the // `isStatement` parameter). pp$1.parseFunction = function(node, isStatement, allowExpressionBody) { this.initFunction(node) if (this.options.ecmaVersion >= 6) node.generator = this.eat(tt.star) var oldInGen = this.inGenerator this.inGenerator = node.generator if (isStatement || this.type === tt.name) node.id = this.parseIdent() this.parseFunctionParams(node) this.parseFunctionBody(node, allowExpressionBody) this.inGenerator = oldInGen return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression") } pp$1.parseFunctionParams = function(node) { this.expect(tt.parenL) node.params = this.parseBindingList(tt.parenR, false, false, true) } // Parse a class declaration or literal (depending on the // `isStatement` parameter). pp$1.parseClass = function(node, isStatement) { var this$1 = this; this.next() this.parseClassId(node, isStatement) this.parseClassSuper(node) var classBody = this.startNode() var hadConstructor = false classBody.body = [] this.expect(tt.braceL) while (!this.eat(tt.braceR)) { if (this$1.eat(tt.semi)) continue var method = this$1.startNode() var isGenerator = this$1.eat(tt.star) var isMaybeStatic = this$1.type === tt.name && this$1.value === "static" this$1.parsePropertyName(method) method.static = isMaybeStatic && this$1.type !== tt.parenL if (method.static) { if (isGenerator) this$1.unexpected() isGenerator = this$1.eat(tt.star) this$1.parsePropertyName(method) } method.kind = "method" var isGetSet = false if (!method.computed) { var key = method.key; if (!isGenerator && key.type === "Identifier" && this$1.type !== tt.parenL && (key.name === "get" || key.name === "set")) { isGetSet = true method.kind = key.name key = this$1.parsePropertyName(method) } if (!method.static && (key.type === "Identifier" && key.name === "constructor" || key.type === "Literal" && key.value === "constructor")) { if (hadConstructor) this$1.raise(key.start, "Duplicate constructor in the same class") if (isGetSet) this$1.raise(key.start, "Constructor can't have get/set modifier") if (isGenerator) this$1.raise(key.start, "Constructor can't be a generator") method.kind = "constructor" hadConstructor = true } } this$1.parseClassMethod(classBody, method, isGenerator) if (isGetSet) { var paramCount = method.kind === "get" ? 0 : 1 if (method.value.params.length !== paramCount) { var start = method.value.start if (method.kind === "get") this$1.raiseRecoverable(start, "getter should have no params") else this$1.raiseRecoverable(start, "setter should have exactly one param") } if (method.kind === "set" && method.value.params[0].type === "RestElement") this$1.raise(method.value.params[0].start, "Setter cannot use rest params") } } node.body = this.finishNode(classBody, "ClassBody") return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression") } pp$1.parseClassMethod = function(classBody, method, isGenerator) { method.value = this.parseMethod(isGenerator) classBody.body.push(this.finishNode(method, "MethodDefinition")) } pp$1.parseClassId = function(node, isStatement) { node.id = this.type === tt.name ? this.parseIdent() : isStatement ? this.unexpected() : null } pp$1.parseClassSuper = function(node) { node.superClass = this.eat(tt._extends) ? this.parseExprSubscripts() : null } // Parses module export declaration. pp$1.parseExport = function(node) { var this$1 = this; this.next() // export * from '...' if (this.eat(tt.star)) { this.expectContextual("from") node.source = this.type === tt.string ? this.parseExprAtom() : this.unexpected() this.semicolon() return this.finishNode(node, "ExportAllDeclaration") } if (this.eat(tt._default)) { // export default ... var parens = this.type == tt.parenL var expr = this.parseMaybeAssign() var needsSemi = true if (!parens && (expr.type == "FunctionExpression" || expr.type == "ClassExpression")) { needsSemi = false if (expr.id) { expr.type = expr.type == "FunctionExpression" ? "FunctionDeclaration" : "ClassDeclaration" } } node.declaration = expr if (needsSemi) this.semicolon() return this.finishNode(node, "ExportDefaultDeclaration") } // export var|const|let|function|class ... if (this.shouldParseExportStatement()) { node.declaration = this.parseStatement(true) node.specifiers = [] node.source = null } else { // export { x, y as z } [from '...'] node.declaration = null node.specifiers = this.parseExportSpecifiers() if (this.eatContextual("from")) { node.source = this.type === tt.string ? this.parseExprAtom() : this.unexpected() } else { // check for keywords used as local names for (var i = 0; i < node.specifiers.length; i++) { if (this$1.keywords.test(node.specifiers[i].local.name) || this$1.reservedWords.test(node.specifiers[i].local.name)) { this$1.unexpected(node.specifiers[i].local.start) } } node.source = null } this.semicolon() } return this.finishNode(node, "ExportNamedDeclaration") } pp$1.shouldParseExportStatement = function() { retu