1'use strict'; 2 3Object.defineProperty(exports, '__esModule', { value: true }); 4 5/* eslint max-len: 0 */ 6 7// This is a trick taken from Esprima. It turns out that, on 8// non-Chrome browsers, to check whether a string is in a set, a 9// predicate containing a big ugly `switch` statement is faster than 10// a regular expression, and on Chrome the two are about on par. 11// This function uses `eval` (non-lexical) to produce such a 12// predicate from a space-separated string of words. 13// 14// It starts by sorting the words by length. 15 16function makePredicate(words) { 17 words = words.split(" "); 18 return function (str) { 19 return words.indexOf(str) >= 0; 20 }; 21} 22 23// Reserved word lists for various dialects of the language 24 25var reservedWords = { 26 6: makePredicate("enum await"), 27 strict: makePredicate("implements interface let package private protected public static yield"), 28 strictBind: makePredicate("eval arguments") 29}; 30 31// And the keywords 32 33var 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"); 34 35// ## Character categories 36 37// Big ugly regular expressions that match characters in the 38// whitespace, identifier, and identifier-start categories. These 39// are only applied when a character is found to actually have a 40// code point above 128. 41// Generated by `bin/generate-identifier-regex.js`. 42 43var 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"; 44var 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"; 45 46var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]"); 47var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]"); 48 49nonASCIIidentifierStartChars = nonASCIIidentifierChars = null; 50 51// These are a run-length and offset encoded representation of the 52// >0xffff code points that are a valid part of identifiers. The 53// offset starts at 0x10000, and each pair of numbers represents an 54// offset to the next range, and then a size of the range. They were 55// generated by `bin/generate-identifier-regex.js`. 56// eslint-disable-next-line comma-spacing 57var 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]; 58// eslint-disable-next-line comma-spacing 59var 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]; 60 61// This has a complexity linear to the value of the code. The 62// assumption is that looking up astral identifier characters is 63// rare. 64function isInAstralSet(code, set) { 65 var pos = 0x10000; 66 for (var i = 0; i < set.length; i += 2) { 67 pos += set[i]; 68 if (pos > code) return false; 69 70 pos += set[i + 1]; 71 if (pos >= code) return true; 72 } 73} 74 75// Test whether a given character code starts an identifier. 76 77function isIdentifierStart(code) { 78 if (code < 65) return code === 36; 79 if (code < 91) return true; 80 if (code < 97) return code === 95; 81 if (code < 123) return true; 82 if (code <= 0xffff) return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)); 83 return isInAstralSet(code, astralIdentifierStartCodes); 84} 85 86// Test whether a given character is part of an identifier. 87 88function isIdentifierChar(code) { 89 if (code < 48) return code === 36; 90 if (code < 58) return true; 91 if (code < 65) return false; 92 if (code < 91) return true; 93 if (code < 97) return code === 95; 94 if (code < 123) return true; 95 if (code <= 0xffff) return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)); 96 return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes); 97} 98 99// A second optional argument can be given to further configure 100var defaultOptions = { 101 // Source type ("script" or "module") for different semantics 102 sourceType: "script", 103 // Source filename. 104 sourceFilename: undefined, 105 // Line from which to start counting source. Useful for 106 // integration with other tools. 107 startLine: 1, 108 // When enabled, a return at the top level is not considered an 109 // error. 110 allowReturnOutsideFunction: false, 111 // When enabled, import/export statements are not constrained to 112 // appearing at the top of the program. 113 allowImportExportEverywhere: false, 114 // TODO 115 allowSuperOutsideMethod: false, 116 // An array of plugins to enable 117 plugins: [], 118 // TODO 119 strictMode: null 120}; 121 122// Interpret and default an options object 123 124function getOptions(opts) { 125 var options = {}; 126 for (var key in defaultOptions) { 127 options[key] = opts && key in opts ? opts[key] : defaultOptions[key]; 128 } 129 return options; 130} 131 132var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { 133 return typeof obj; 134} : function (obj) { 135 return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; 136}; 137 138 139 140 141 142 143 144 145 146 147 148var classCallCheck = function (instance, Constructor) { 149 if (!(instance instanceof Constructor)) { 150 throw new TypeError("Cannot call a class as a function"); 151 } 152}; 153 154 155 156 157 158 159 160 161 162 163 164var inherits = function (subClass, superClass) { 165 if (typeof superClass !== "function" && superClass !== null) { 166 throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); 167 } 168 169 subClass.prototype = Object.create(superClass && superClass.prototype, { 170 constructor: { 171 value: subClass, 172 enumerable: false, 173 writable: true, 174 configurable: true 175 } 176 }); 177 if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; 178}; 179 180 181 182 183 184 185 186 187 188 189 190var possibleConstructorReturn = function (self, call) { 191 if (!self) { 192 throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); 193 } 194 195 return call && (typeof call === "object" || typeof call === "function") ? call : self; 196}; 197 198// ## Token types 199 200// The assignment of fine-grained, information-carrying type objects 201// allows the tokenizer to store the information it has about a 202// token in a way that is very cheap for the parser to look up. 203 204// All token type variables start with an underscore, to make them 205// easy to recognize. 206 207// The `beforeExpr` property is used to disambiguate between regular 208// expressions and divisions. It is set on all token types that can 209// be followed by an expression (thus, a slash after them would be a 210// regular expression). 211// 212// `isLoop` marks a keyword as starting a loop, which is important 213// to know when parsing a label, in order to allow or disallow 214// continue jumps to that label. 215 216var beforeExpr = true; 217var startsExpr = true; 218var isLoop = true; 219var isAssign = true; 220var prefix = true; 221var postfix = true; 222 223var TokenType = function TokenType(label) { 224 var conf = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 225 classCallCheck(this, TokenType); 226 227 this.label = label; 228 this.keyword = conf.keyword; 229 this.beforeExpr = !!conf.beforeExpr; 230 this.startsExpr = !!conf.startsExpr; 231 this.rightAssociative = !!conf.rightAssociative; 232 this.isLoop = !!conf.isLoop; 233 this.isAssign = !!conf.isAssign; 234 this.prefix = !!conf.prefix; 235 this.postfix = !!conf.postfix; 236 this.binop = conf.binop || null; 237 this.updateContext = null; 238}; 239 240var KeywordTokenType = function (_TokenType) { 241 inherits(KeywordTokenType, _TokenType); 242 243 function KeywordTokenType(name) { 244 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 245 classCallCheck(this, KeywordTokenType); 246 247 options.keyword = name; 248 249 return possibleConstructorReturn(this, _TokenType.call(this, name, options)); 250 } 251 252 return KeywordTokenType; 253}(TokenType); 254 255var BinopTokenType = function (_TokenType2) { 256 inherits(BinopTokenType, _TokenType2); 257 258 function BinopTokenType(name, prec) { 259 classCallCheck(this, BinopTokenType); 260 return possibleConstructorReturn(this, _TokenType2.call(this, name, { beforeExpr: beforeExpr, binop: prec })); 261 } 262 263 return BinopTokenType; 264}(TokenType); 265 266var types = { 267 num: new TokenType("num", { startsExpr: startsExpr }), 268 regexp: new TokenType("regexp", { startsExpr: startsExpr }), 269 string: new TokenType("string", { startsExpr: startsExpr }), 270 name: new TokenType("name", { startsExpr: startsExpr }), 271 eof: new TokenType("eof"), 272 273 // Punctuation token types. 274 bracketL: new TokenType("[", { beforeExpr: beforeExpr, startsExpr: startsExpr }), 275 bracketR: new TokenType("]"), 276 braceL: new TokenType("{", { beforeExpr: beforeExpr, startsExpr: startsExpr }), 277 braceBarL: new TokenType("{|", { beforeExpr: beforeExpr, startsExpr: startsExpr }), 278 braceR: new TokenType("}"), 279 braceBarR: new TokenType("|}"), 280 parenL: new TokenType("(", { beforeExpr: beforeExpr, startsExpr: startsExpr }), 281 parenR: new TokenType(")"), 282 comma: new TokenType(",", { beforeExpr: beforeExpr }), 283 semi: new TokenType(";", { beforeExpr: beforeExpr }), 284 colon: new TokenType(":", { beforeExpr: beforeExpr }), 285 doubleColon: new TokenType("::", { beforeExpr: beforeExpr }), 286 dot: new TokenType("."), 287 question: new TokenType("?", { beforeExpr: beforeExpr }), 288 arrow: new TokenType("=>", { beforeExpr: beforeExpr }), 289 template: new TokenType("template"), 290 ellipsis: new TokenType("...", { beforeExpr: beforeExpr }), 291 backQuote: new TokenType("`", { startsExpr: startsExpr }), 292 dollarBraceL: new TokenType("${", { beforeExpr: beforeExpr, startsExpr: startsExpr }), 293 at: new TokenType("@"), 294 295 // Operators. These carry several kinds of properties to help the 296 // parser use them properly (the presence of these properties is 297 // what categorizes them as operators). 298 // 299 // `binop`, when present, specifies that this operator is a binary 300 // operator, and will refer to its precedence. 301 // 302 // `prefix` and `postfix` mark the operator as a prefix or postfix 303 // unary operator. 304 // 305 // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as 306 // binary operators with a very low precedence, that should result 307 // in AssignmentExpression nodes. 308 309 eq: new TokenType("=", { beforeExpr: beforeExpr, isAssign: isAssign }), 310 assign: new TokenType("_=", { beforeExpr: beforeExpr, isAssign: isAssign }), 311 incDec: new TokenType("++/--", { prefix: prefix, postfix: postfix, startsExpr: startsExpr }), 312 prefix: new TokenType("prefix", { beforeExpr: beforeExpr, prefix: prefix, startsExpr: startsExpr }), 313 logicalOR: new BinopTokenType("||", 1), 314 logicalAND: new BinopTokenType("&&", 2), 315 bitwiseOR: new BinopTokenType("|", 3), 316 bitwiseXOR: new BinopTokenType("^", 4), 317 bitwiseAND: new BinopTokenType("&", 5), 318 equality: new BinopTokenType("==/!=", 6), 319 relational: new BinopTokenType("</>", 7), 320 bitShift: new BinopTokenType("<</>>", 8), 321 plusMin: new TokenType("+/-", { beforeExpr: beforeExpr, binop: 9, prefix: prefix, startsExpr: startsExpr }), 322 modulo: new BinopTokenType("%", 10), 323 star: new BinopTokenType("*", 10), 324 slash: new BinopTokenType("/", 10), 325 exponent: new TokenType("**", { beforeExpr: beforeExpr, binop: 11, rightAssociative: true }) 326}; 327 328var keywords = { 329 "break": new KeywordTokenType("break"), 330 "case": new KeywordTokenType("case", { beforeExpr: beforeExpr }), 331 "catch": new KeywordTokenType("catch"), 332 "continue": new KeywordTokenType("continue"), 333 "debugger": new KeywordTokenType("debugger"), 334 "default": new KeywordTokenType("default", { beforeExpr: beforeExpr }), 335 "do": new KeywordTokenType("do", { isLoop: isLoop, beforeExpr: beforeExpr }), 336 "else": new KeywordTokenType("else", { beforeExpr: beforeExpr }), 337 "finally": new KeywordTokenType("finally"), 338 "for": new KeywordTokenType("for", { isLoop: isLoop }), 339 "function": new KeywordTokenType("function", { startsExpr: startsExpr }), 340 "if": new KeywordTokenType("if"), 341 "return": new KeywordTokenType("return", { beforeExpr: beforeExpr }), 342 "switch": new KeywordTokenType("switch"), 343 "throw": new KeywordTokenType("throw", { beforeExpr: beforeExpr }), 344 "try": new KeywordTokenType("try"), 345 "var": new KeywordTokenType("var"), 346 "let": new KeywordTokenType("let"), 347 "const": new KeywordTokenType("const"), 348 "while": new KeywordTokenType("while", { isLoop: isLoop }), 349 "with": new KeywordTokenType("with"), 350 "new": new KeywordTokenType("new", { beforeExpr: beforeExpr, startsExpr: startsExpr }), 351 "this": new KeywordTokenType("this", { startsExpr: startsExpr }), 352 "super": new KeywordTokenType("super", { startsExpr: startsExpr }), 353 "class": new KeywordTokenType("class"), 354 "extends": new KeywordTokenType("extends", { beforeExpr: beforeExpr }), 355 "export": new KeywordTokenType("export"), 356 "import": new KeywordTokenType("import", { startsExpr: startsExpr }), 357 "yield": new KeywordTokenType("yield", { beforeExpr: beforeExpr, startsExpr: startsExpr }), 358 "null": new KeywordTokenType("null", { startsExpr: startsExpr }), 359 "true": new KeywordTokenType("true", { startsExpr: startsExpr }), 360 "false": new KeywordTokenType("false", { startsExpr: startsExpr }), 361 "in": new KeywordTokenType("in", { beforeExpr: beforeExpr, binop: 7 }), 362 "instanceof": new KeywordTokenType("instanceof", { beforeExpr: beforeExpr, binop: 7 }), 363 "typeof": new KeywordTokenType("typeof", { beforeExpr: beforeExpr, prefix: prefix, startsExpr: startsExpr }), 364 "void": new KeywordTokenType("void", { beforeExpr: beforeExpr, prefix: prefix, startsExpr: startsExpr }), 365 "delete": new KeywordTokenType("delete", { beforeExpr: beforeExpr, prefix: prefix, startsExpr: startsExpr }) 366}; 367 368// Map keyword names to token types. 369Object.keys(keywords).forEach(function (name) { 370 types["_" + name] = keywords[name]; 371}); 372 373// Matches a whole line break (where CRLF is considered a single 374// line break). Used to count lines. 375 376var lineBreak = /\r\n?|\n|\u2028|\u2029/; 377var lineBreakG = new RegExp(lineBreak.source, "g"); 378 379function isNewLine(code) { 380 return code === 10 || code === 13 || code === 0x2028 || code === 0x2029; 381} 382 383var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/; 384 385// The algorithm used to determine whether a regexp can appear at a 386// given point in the program is loosely based on sweet.js' approach. 387// See https://github.com/mozilla/sweet.js/wiki/design 388 389var TokContext = function TokContext(token, isExpr, preserveSpace, override) { 390 classCallCheck(this, TokContext); 391 392 this.token = token; 393 this.isExpr = !!isExpr; 394 this.preserveSpace = !!preserveSpace; 395 this.override = override; 396}; 397 398var types$1 = { 399 braceStatement: new TokContext("{", false), 400 braceExpression: new TokContext("{", true), 401 templateQuasi: new TokContext("${", true), 402 parenStatement: new TokContext("(", false), 403 parenExpression: new TokContext("(", true), 404 template: new TokContext("`", true, true, function (p) { 405 return p.readTmplToken(); 406 }), 407 functionExpression: new TokContext("function", true) 408}; 409 410// Token-specific context update code 411 412types.parenR.updateContext = types.braceR.updateContext = function () { 413 if (this.state.context.length === 1) { 414 this.state.exprAllowed = true; 415 return; 416 } 417 418 var out = this.state.context.pop(); 419 if (out === types$1.braceStatement && this.curContext() === types$1.functionExpression) { 420 this.state.context.pop(); 421 this.state.exprAllowed = false; 422 } else if (out === types$1.templateQuasi) { 423 this.state.exprAllowed = true; 424 } else { 425 this.state.exprAllowed = !out.isExpr; 426 } 427}; 428 429types.name.updateContext = function (prevType) { 430 this.state.exprAllowed = false; 431 432 if (prevType === types._let || prevType === types._const || prevType === types._var) { 433 if (lineBreak.test(this.input.slice(this.state.end))) { 434 this.state.exprAllowed = true; 435 } 436 } 437}; 438 439types.braceL.updateContext = function (prevType) { 440 this.state.context.push(this.braceIsBlock(prevType) ? types$1.braceStatement : types$1.braceExpression); 441 this.state.exprAllowed = true; 442}; 443 444types.dollarBraceL.updateContext = function () { 445 this.state.context.push(types$1.templateQuasi); 446 this.state.exprAllowed = true; 447}; 448 449types.parenL.updateContext = function (prevType) { 450 var statementParens = prevType === types._if || prevType === types._for || prevType === types._with || prevType === types._while; 451 this.state.context.push(statementParens ? types$1.parenStatement : types$1.parenExpression); 452 this.state.exprAllowed = true; 453}; 454 455types.incDec.updateContext = function () { 456 // tokExprAllowed stays unchanged 457}; 458 459types._function.updateContext = function () { 460 if (this.curContext() !== types$1.braceStatement) { 461 this.state.context.push(types$1.functionExpression); 462 } 463 464 this.state.exprAllowed = false; 465}; 466 467types.backQuote.updateContext = function () { 468 if (this.curContext() === types$1.template) { 469 this.state.context.pop(); 470 } else { 471 this.state.context.push(types$1.template); 472 } 473 this.state.exprAllowed = false; 474}; 475 476// These are used when `options.locations` is on, for the 477// `startLoc` and `endLoc` properties. 478 479var Position = function Position(line, col) { 480 classCallCheck(this, Position); 481 482 this.line = line; 483 this.column = col; 484}; 485 486var SourceLocation = function SourceLocation(start, end) { 487 classCallCheck(this, SourceLocation); 488 489 this.start = start; 490 this.end = end; 491}; 492 493// The `getLineInfo` function is mostly useful when the 494// `locations` option is off (for performance reasons) and you 495// want to find the line/column position for a given character 496// offset. `input` should be the code string that the offset refers 497// into. 498 499function getLineInfo(input, offset) { 500 for (var line = 1, cur = 0;;) { 501 lineBreakG.lastIndex = cur; 502 var match = lineBreakG.exec(input); 503 if (match && match.index < offset) { 504 ++line; 505 cur = match.index + match[0].length; 506 } else { 507 return new Position(line, offset - cur); 508 } 509 } 510} 511 512var State = function () { 513 function State() { 514 classCallCheck(this, State); 515 } 516 517 State.prototype.init = function init(options, input) { 518 this.strict = options.strictMode === false ? false : options.sourceType === "module"; 519 520 this.input = input; 521 522 this.potentialArrowAt = -1; 523 524 this.inMethod = this.inFunction = this.inGenerator = this.inAsync = this.inPropertyName = this.inType = this.inClassProperty = this.noAnonFunctionType = false; 525 526 this.labels = []; 527 528 this.decorators = []; 529 530 this.tokens = []; 531 532 this.comments = []; 533 534 this.trailingComments = []; 535 this.leadingComments = []; 536 this.commentStack = []; 537 538 this.pos = this.lineStart = 0; 539 this.curLine = options.startLine; 540 541 this.type = types.eof; 542 this.value = null; 543 this.start = this.end = this.pos; 544 this.startLoc = this.endLoc = this.curPosition(); 545 546 this.lastTokEndLoc = this.lastTokStartLoc = null; 547 this.lastTokStart = this.lastTokEnd = this.pos; 548 549 this.context = [types$1.braceStatement]; 550 this.exprAllowed = true; 551 552 this.containsEsc = this.containsOctal = false; 553 this.octalPosition = null; 554 555 this.invalidTemplateEscapePosition = null; 556 557 this.exportedIdentifiers = []; 558 559 return this; 560 }; 561 562 // TODO 563 564 565 // TODO 566 567 568 // Used to signify the start of a potential arrow function 569 570 571 // Flags to track whether we are in a function, a generator. 572 573 574 // Labels in scope. 575 576 577 // Leading decorators. 578 579 580 // Token store. 581 582 583 // Comment store. 584 585 586 // Comment attachment store 587 588 589 // The current position of the tokenizer in the input. 590 591 592 // Properties of the current token: 593 // Its type 594 595 596 // For tokens that include more information than their type, the value 597 598 599 // Its start and end offset 600 601 602 // And, if locations are used, the {line, column} object 603 // corresponding to those offsets 604 605 606 // Position information for the previous token 607 608 609 // The context stack is used to superficially track syntactic 610 // context to predict whether a regular expression is allowed in a 611 // given position. 612 613 614 // Used to signal to callers of `readWord1` whether the word 615 // contained any escape sequences. This is needed because words with 616 // escape sequences must not be interpreted as keywords. 617 618 619 // TODO 620 621 622 // Names of exports store. `default` is stored as a name for both 623 // `export default foo;` and `export { foo as default };`. 624 625 626 State.prototype.curPosition = function curPosition() { 627 return new Position(this.curLine, this.pos - this.lineStart); 628 }; 629 630 State.prototype.clone = function clone(skipArrays) { 631 var state = new State(); 632 for (var key in this) { 633 var val = this[key]; 634 635 if ((!skipArrays || key === "context") && Array.isArray(val)) { 636 val = val.slice(); 637 } 638 639 state[key] = val; 640 } 641 return state; 642 }; 643 644 return State; 645}(); 646 647// Object type used to represent tokens. Note that normally, tokens 648// simply exist as properties on the parser object. This is only 649// used for the onToken callback and the external tokenizer. 650 651var Token = function Token(state) { 652 classCallCheck(this, Token); 653 654 this.type = state.type; 655 this.value = state.value; 656 this.start = state.start; 657 this.end = state.end; 658 this.loc = new SourceLocation(state.startLoc, state.endLoc); 659}; 660 661// ## Tokenizer 662 663function codePointToString(code) { 664 // UTF-16 Decoding 665 if (code <= 0xFFFF) { 666 return String.fromCharCode(code); 667 } else { 668 return String.fromCharCode((code - 0x10000 >> 10) + 0xD800, (code - 0x10000 & 1023) + 0xDC00); 669 } 670} 671 672var Tokenizer = function () { 673 function Tokenizer(options, input) { 674 classCallCheck(this, Tokenizer); 675 676 this.state = new State(); 677 this.state.init(options, input); 678 } 679 680 // Move to the next token 681 682 Tokenizer.prototype.next = function next() { 683 if (!this.isLookahead) { 684 this.state.tokens.push(new Token(this.state)); 685 } 686 687 this.state.lastTokEnd = this.state.end; 688 this.state.lastTokStart = this.state.start; 689 this.state.lastTokEndLoc = this.state.endLoc; 690 this.state.lastTokStartLoc = this.state.startLoc; 691 this.nextToken(); 692 }; 693 694 // TODO 695 696 Tokenizer.prototype.eat = function eat(type) { 697 if (this.match(type)) { 698 this.next(); 699 return true; 700 } else { 701 return false; 702 } 703 }; 704 705 // TODO 706 707 Tokenizer.prototype.match = function match(type) { 708 return this.state.type === type; 709 }; 710 711 // TODO 712 713 Tokenizer.prototype.isKeyword = function isKeyword$$1(word) { 714 return isKeyword(word); 715 }; 716 717 // TODO 718 719 Tokenizer.prototype.lookahead = function lookahead() { 720 var old = this.state; 721 this.state = old.clone(true); 722 723 this.isLookahead = true; 724 this.next(); 725 this.isLookahead = false; 726 727 var curr = this.state.clone(true); 728 this.state = old; 729 return curr; 730 }; 731 732 // Toggle strict mode. Re-reads the next number or string to please 733 // pedantic tests (`"use strict"; 010;` should fail). 734 735 Tokenizer.prototype.setStrict = function setStrict(strict) { 736 this.state.strict = strict; 737 if (!this.match(types.num) && !this.match(types.string)) return; 738 this.state.pos = this.state.start; 739 while (this.state.pos < this.state.lineStart) { 740 this.state.lineStart = this.input.lastIndexOf("\n", this.state.lineStart - 2) + 1; 741 --this.state.curLine; 742 } 743 this.nextToken(); 744 }; 745 746 Tokenizer.prototype.curContext = function curContext() { 747 return this.state.context[this.state.context.length - 1]; 748 }; 749 750 // Read a single token, updating the parser object's token-related 751 // properties. 752 753 Tokenizer.prototype.nextToken = function nextToken() { 754 var curContext = this.curContext(); 755 if (!curContext || !curContext.preserveSpace) this.skipSpace(); 756 757 this.state.containsOctal = false; 758 this.state.octalPosition = null; 759 this.state.start = this.state.pos; 760 this.state.startLoc = this.state.curPosition(); 761 if (this.state.pos >= this.input.length) return this.finishToken(types.eof); 762 763 if (curContext.override) { 764 return curContext.override(this); 765 } else { 766 return this.readToken(this.fullCharCodeAtPos()); 767 } 768 }; 769 770 Tokenizer.prototype.readToken = function readToken(code) { 771 // Identifier or keyword. '\uXXXX' sequences are allowed in 772 // identifiers, so '\' also dispatches to that. 773 if (isIdentifierStart(code) || code === 92 /* '\' */) { 774 return this.readWord(); 775 } else { 776 return this.getTokenFromCode(code); 777 } 778 }; 779 780 Tokenizer.prototype.fullCharCodeAtPos = function fullCharCodeAtPos() { 781 var code = this.input.charCodeAt(this.state.pos); 782 if (code <= 0xd7ff || code >= 0xe000) return code; 783 784 var next = this.input.charCodeAt(this.state.pos + 1); 785 return (code << 10) + next - 0x35fdc00; 786 }; 787 788 Tokenizer.prototype.pushComment = function pushComment(block, text, start, end, startLoc, endLoc) { 789 var comment = { 790 type: block ? "CommentBlock" : "CommentLine", 791 value: text, 792 start: start, 793 end: end, 794 loc: new SourceLocation(startLoc, endLoc) 795 }; 796 797 if (!this.isLookahead) { 798 this.state.tokens.push(comment); 799 this.state.comments.push(comment); 800 this.addComment(comment); 801 } 802 }; 803 804 Tokenizer.prototype.skipBlockComment = function skipBlockComment() { 805 var startLoc = this.state.curPosition(); 806 var start = this.state.pos; 807 var end = this.input.indexOf("*/", this.state.pos += 2); 808 if (end === -1) this.raise(this.state.pos - 2, "Unterminated comment"); 809 810 this.state.pos = end + 2; 811 lineBreakG.lastIndex = start; 812 var match = void 0; 813 while ((match = lineBreakG.exec(this.input)) && match.index < this.state.pos) { 814 ++this.state.curLine; 815 this.state.lineStart = match.index + match[0].length; 816 } 817 818 this.pushComment(true, this.input.slice(start + 2, end), start, this.state.pos, startLoc, this.state.curPosition()); 819 }; 820 821 Tokenizer.prototype.skipLineComment = function skipLineComment(startSkip) { 822 var start = this.state.pos; 823 var startLoc = this.state.curPosition(); 824 var ch = this.input.charCodeAt(this.state.pos += startSkip); 825 while (this.state.pos < this.input.length && ch !== 10 && ch !== 13 && ch !== 8232 && ch !== 8233) { 826 ++this.state.pos; 827 ch = this.input.charCodeAt(this.state.pos); 828 } 829 830 this.pushComment(false, this.input.slice(start + startSkip, this.state.pos), start, this.state.pos, startLoc, this.state.curPosition()); 831 }; 832 833 // Called at the start of the parse and after every token. Skips 834 // whitespace and comments, and. 835 836 Tokenizer.prototype.skipSpace = function skipSpace() { 837 loop: while (this.state.pos < this.input.length) { 838 var ch = this.input.charCodeAt(this.state.pos); 839 switch (ch) { 840 case 32:case 160: 841 // ' ' 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 // '/' 858 switch (this.input.charCodeAt(this.state.pos + 1)) { 859 case 42: 860 // '*' 861 this.skipBlockComment(); 862 break; 863 864 case 47: 865 this.skipLineComment(2); 866 break; 867 868 default: 869 break loop; 870 } 871 break; 872 873 default: 874 if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) { 875 ++this.state.pos; 876 } else { 877 break loop; 878 } 879 } 880 } 881 }; 882 883 // Called at the end of every token. Sets `end`, `val`, and 884 // maintains `context` and `exprAllowed`, and skips the space after 885 // the token, so that the next one's `start` will point at the 886 // right position. 887 888 Tokenizer.prototype.finishToken = function finishToken(type, val) { 889 this.state.end = this.state.pos; 890 this.state.endLoc = this.state.curPosition(); 891 var prevType = this.state.type; 892 this.state.type = type; 893 this.state.value = val; 894 895 this.updateContext(prevType); 896 }; 897 898 // ### Token reading 899 900 // This is the function that is called to fetch the next token. It 901 // is somewhat obscure, because it works in character codes rather 902 // than characters, and because operator parsing has been inlined 903 // into it. 904 // 905 // All in the name of speed. 906 // 907 908 909 Tokenizer.prototype.readToken_dot = function readToken_dot() { 910 var next = this.input.charCodeAt(this.state.pos + 1); 911 if (next >= 48 && next <= 57) { 912 return this.readNumber(true); 913 } 914 915 var next2 = this.input.charCodeAt(this.state.pos + 2); 916 if (next === 46 && next2 === 46) { 917 // 46 = dot '.' 918 this.state.pos += 3; 919 return this.finishToken(types.ellipsis); 920 } else { 921 ++this.state.pos; 922 return this.finishToken(types.dot); 923 } 924 }; 925 926 Tokenizer.prototype.readToken_slash = function readToken_slash() { 927 // '/' 928 if (this.state.exprAllowed) { 929 ++this.state.pos; 930 return this.readRegexp(); 931 } 932 933 var next = this.input.charCodeAt(this.state.pos + 1); 934 if (next === 61) { 935 return this.finishOp(types.assign, 2); 936 } else { 937 return this.finishOp(types.slash, 1); 938 } 939 }; 940 941 Tokenizer.prototype.readToken_mult_modulo = function readToken_mult_modulo(code) { 942 // '%*' 943 var type = code === 42 ? types.star : types.modulo; 944 var width = 1; 945 var next = this.input.charCodeAt(this.state.pos + 1); 946 947 if (next === 42) { 948 // '*' 949 width++; 950 next = this.input.charCodeAt(this.state.pos + 2); 951 type = types.exponent; 952 } 953 954 if (next === 61) { 955 width++; 956 type = types.assign; 957 } 958 959 return this.finishOp(type, width); 960 }; 961 962 Tokenizer.prototype.readToken_pipe_amp = function readToken_pipe_amp(code) { 963 // '|&' 964 var next = this.input.charCodeAt(this.state.pos + 1); 965 if (next === code) return this.finishOp(code === 124 ? types.logicalOR : types.logicalAND, 2); 966 if (next === 61) return this.finishOp(types.assign, 2); 967 if (code === 124 && next === 125 && this.hasPlugin("flow")) return this.finishOp(types.braceBarR, 2); 968 return this.finishOp(code === 124 ? types.bitwiseOR : types.bitwiseAND, 1); 969 }; 970 971 Tokenizer.prototype.readToken_caret = function readToken_caret() { 972 // '^' 973 var next = this.input.charCodeAt(this.state.pos + 1); 974 if (next === 61) { 975 return this.finishOp(types.assign, 2); 976 } else { 977 return this.finishOp(types.bitwiseXOR, 1); 978 } 979 }; 980 981 Tokenizer.prototype.readToken_plus_min = function readToken_plus_min(code) { 982 // '+-' 983 var next = this.input.charCodeAt(this.state.pos + 1); 984 985 if (next === code) { 986 if (next === 45 && this.input.charCodeAt(this.state.pos + 2) === 62 && lineBreak.test(this.input.slice(this.state.lastTokEnd, this.state.pos))) { 987 // A `-->` line comment 988 this.skipLineComment(3); 989 this.skipSpace(); 990 return this.nextToken(); 991 } 992 return this.finishOp(types.incDec, 2); 993 } 994 995 if (next === 61) { 996 return this.finishOp(types.assign, 2); 997 } else { 998 return this.finishOp(types.plusMin, 1); 999 } 1000 }; 1001 1002 Tokenizer.prototype.readToken_lt_gt = function readToken_lt_gt(code) { 1003 // '<>' 1004 var next = this.input.charCodeAt(this.state.pos + 1); 1005 var size = 1; 1006 1007 if (next === code) { 1008 size = code === 62 && this.input.charCodeAt(this.state.pos + 2) === 62 ? 3 : 2; 1009 if (this.input.charCodeAt(this.state.pos + size) === 61) return this.finishOp(types.assign, size + 1); 1010 return this.finishOp(types.bitShift, size); 1011 } 1012 1013 if (next === 33 && code === 60 && this.input.charCodeAt(this.state.pos + 2) === 45 && this.input.charCodeAt(this.state.pos + 3) === 45) { 1014 if (this.inModule) this.unexpected(); 1015 // `<!--`, an XML-style comment that should be interpreted as a line comment 1016 this.skipLineComment(4); 1017 this.skipSpace(); 1018 return this.nextToken(); 1019 } 1020 1021 if (next === 61) { 1022 // <= | >= 1023 size = 2; 1024 } 1025 1026 return this.finishOp(types.relational, size); 1027 }; 1028 1029 Tokenizer.prototype.readToken_eq_excl = function readToken_eq_excl(code) { 1030 // '=!' 1031 var next = this.input.charCodeAt(this.state.pos + 1); 1032 if (next === 61) return this.finishOp(types.equality, this.input.charCodeAt(this.state.pos + 2) === 61 ? 3 : 2); 1033 if (code === 61 && next === 62) { 1034 // '=>' 1035 this.state.pos += 2; 1036 return this.finishToken(types.arrow); 1037 } 1038 return this.finishOp(code === 61 ? types.eq : types.prefix, 1); 1039 }; 1040 1041 Tokenizer.prototype.getTokenFromCode = function getTokenFromCode(code) { 1042 switch (code) { 1043 // The interpretation of a dot depends on whether it is followed 1044 // by a digit or another two dots. 1045 case 46: 1046 // '.' 1047 return this.readToken_dot(); 1048 1049 // Punctuation tokens. 1050 case 40: 1051 ++this.state.pos;return this.finishToken(types.parenL); 1052 case 41: 1053 ++this.state.pos;return this.finishToken(types.parenR); 1054 case 59: 1055 ++this.state.pos;return this.finishToken(types.semi); 1056 case 44: 1057 ++this.state.pos;return this.finishToken(types.comma); 1058 case 91: 1059 ++this.state.pos;return this.finishToken(types.bracketL); 1060 case 93: 1061 ++this.state.pos;return this.finishToken(types.bracketR); 1062 1063 case 123: 1064 if (this.hasPlugin("flow") && this.input.charCodeAt(this.state.pos + 1) === 124) { 1065 return this.finishOp(types.braceBarL, 2); 1066 } else { 1067 ++this.state.pos; 1068 return this.finishToken(types.braceL); 1069 } 1070 1071 case 125: 1072 ++this.state.pos;return this.finishToken(types.braceR); 1073 1074 case 58: 1075 if (this.hasPlugin("functionBind") && this.input.charCodeAt(this.state.pos + 1) === 58) { 1076 return this.finishOp(types.doubleColon, 2); 1077 } else { 1078 ++this.state.pos; 1079 return this.finishToken(types.colon); 1080 } 1081 1082 case 63: 1083 ++this.state.pos;return this.finishToken(types.question); 1084 case 64: 1085 ++this.state.pos;return this.finishToken(types.at); 1086 1087 case 96: 1088 // '`' 1089 ++this.state.pos; 1090 return this.finishToken(types.backQuote); 1091 1092 case 48: 1093 // '0' 1094 var next = this.input.charCodeAt(this.state.pos + 1); 1095 if (next === 120 || next === 88) return this.readRadixNumber(16); // '0x', '0X' - hex number 1096 if (next === 111 || next === 79) return this.readRadixNumber(8); // '0o', '0O' - octal number 1097 if (next === 98 || next === 66) return this.readRadixNumber(2); // '0b', '0B' - binary number 1098 // Anything else beginning with a digit is an integer, octal 1099 // number, or float. 1100 case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57: 1101 // 1-9 1102 return this.readNumber(false); 1103 1104 // Quotes produce strings. 1105 case 34:case 39: 1106 // '"', "'" 1107 return this.readString(code); 1108 1109 // Operators are parsed inline in tiny state machines. '=' (61) is 1110 // often referred to. `finishOp` simply skips the amount of 1111 // characters it is given as second argument, and returns a token 1112 // of the type given by its first argument. 1113 1114 case 47: 1115 // '/' 1116 return this.readToken_slash(); 1117 1118 case 37:case 42: 1119 // '%*' 1120 return this.readToken_mult_modulo(code); 1121 1122 case 124:case 38: 1123 // '|&' 1124 return this.readToken_pipe_amp(code); 1125 1126 case 94: 1127 // '^' 1128 return this.readToken_caret(); 1129 1130 case 43:case 45: 1131 // '+-' 1132 return this.readToken_plus_min(code); 1133 1134 case 60:case 62: 1135 // '<>' 1136 return this.readToken_lt_gt(code); 1137 1138 case 61:case 33: 1139 // '=!' 1140 return this.readToken_eq_excl(code); 1141 1142 case 126: 1143 // '~' 1144 return this.finishOp(types.prefix, 1); 1145 } 1146 1147 this.raise(this.state.pos, "Unexpected character '" + codePointToString(code) + "'"); 1148 }; 1149 1150 Tokenizer.prototype.finishOp = function finishOp(type, size) { 1151 var str = this.input.slice(this.state.pos, this.state.pos + size); 1152 this.state.pos += size; 1153 return this.finishToken(type, str); 1154 }; 1155 1156 Tokenizer.prototype.readRegexp = function readRegexp() { 1157 var start = this.state.pos; 1158 var escaped = void 0, 1159 inClass = void 0; 1160 for (;;) { 1161 if (this.state.pos >= this.input.length) this.raise(start, "Unterminated regular expression"); 1162 var ch = this.input.charAt(this.state.pos); 1163 if (lineBreak.test(ch)) { 1164 this.raise(start, "Unterminated regular expression"); 1165 } 1166 if (escaped) { 1167 escaped = false; 1168 } else { 1169 if (ch === "[") { 1170 inClass = true; 1171 } else if (ch === "]" && inClass) { 1172 inClass = false; 1173 } else if (ch === "/" && !inClass) { 1174 break; 1175 } 1176 escaped = ch === "\\"; 1177 } 1178 ++this.state.pos; 1179 } 1180 var content = this.input.slice(start, this.state.pos); 1181 ++this.state.pos; 1182 // Need to use `readWord1` because '\uXXXX' sequences are allowed 1183 // here (don't ask). 1184 var mods = this.readWord1(); 1185 if (mods) { 1186 var validFlags = /^[gmsiyu]*$/; 1187 if (!validFlags.test(mods)) this.raise(start, "Invalid regular expression flag"); 1188 } 1189 return this.finishToken(types.regexp, { 1190 pattern: content, 1191 flags: mods 1192 }); 1193 }; 1194 1195 // Read an integer in the given radix. Return null if zero digits 1196 // were read, the integer value otherwise. When `len` is given, this 1197 // will return `null` unless the integer has exactly `len` digits. 1198 1199 Tokenizer.prototype.readInt = function readInt(radix, len) { 1200 var start = this.state.pos; 1201 var total = 0; 1202 1203 for (var i = 0, e = len == null ? Infinity : len; i < e; ++i) { 1204 var code = this.input.charCodeAt(this.state.pos); 1205 var val = void 0; 1206 if (code >= 97) { 1207 val = code - 97 + 10; // a 1208 } else if (code >= 65) { 1209 val = code - 65 + 10; // A 1210 } else if (code >= 48 && code <= 57) { 1211 val = code - 48; // 0-9 1212 } else { 1213 val = Infinity; 1214 } 1215 if (val >= radix) break; 1216 ++this.state.pos; 1217 total = total * radix + val; 1218 } 1219 if (this.state.pos === start || len != null && this.state.pos - start !== len) return null; 1220 1221 return total; 1222 }; 1223 1224 Tokenizer.prototype.readRadixNumber = function readRadixNumber(radix) { 1225 this.state.pos += 2; // 0x 1226 var val = this.readInt(radix); 1227 if (val == null) this.raise(this.state.start + 2, "Expected number in radix " + radix); 1228 if (isIdentifierStart(this.fullCharCodeAtPos())) this.raise(this.state.pos, "Identifier directly after number"); 1229 return this.finishToken(types.num, val); 1230 }; 1231 1232 // Read an integer, octal integer, or floating-point number. 1233 1234 Tokenizer.prototype.readNumber = function readNumber(startsWithDot) { 1235 var start = this.state.pos; 1236 var octal = this.input.charCodeAt(start) === 48; // '0' 1237 var isFloat = false; 1238 1239 if (!startsWithDot && this.readInt(10) === null) this.raise(start, "Invalid number"); 1240 if (octal && this.state.pos == start + 1) octal = false; // number === 0 1241 1242 var next = this.input.charCodeAt(this.state.pos); 1243 if (next === 46 && !octal) { 1244 // '.' 1245 ++this.state.pos; 1246 this.readInt(10); 1247 isFloat = true; 1248 next = this.input.charCodeAt(this.state.pos); 1249 } 1250 1251 if ((next === 69 || next === 101) && !octal) { 1252 // 'eE' 1253 next = this.input.charCodeAt(++this.state.pos); 1254 if (next === 43 || next === 45) ++this.state.pos; // '+-' 1255 if (this.readInt(10) === null) this.raise(start, "Invalid number"); 1256 isFloat = true; 1257 } 1258 1259 if (isIdentifierStart(this.fullCharCodeAtPos())) this.raise(this.state.pos, "Identifier directly after number"); 1260 1261 var str = this.input.slice(start, this.state.pos); 1262 var val = void 0; 1263 if (isFloat) { 1264 val = parseFloat(str); 1265 } else if (!octal || str.length === 1) { 1266 val = parseInt(str, 10); 1267 } else if (this.state.strict) { 1268 this.raise(start, "Invalid number"); 1269 } else if (/[89]/.test(str)) { 1270 val = parseInt(str, 10); 1271 } else { 1272 val = parseInt(str, 8); 1273 } 1274 return this.finishToken(types.num, val); 1275 }; 1276 1277 // Read a string value, interpreting backslash-escapes. 1278 1279 Tokenizer.prototype.readCodePoint = function readCodePoint(throwOnInvalid) { 1280 var ch = this.input.charCodeAt(this.state.pos); 1281 var code = void 0; 1282 1283 if (ch === 123) { 1284 // '{' 1285 var codePos = ++this.state.pos; 1286 code = this.readHexChar(this.input.indexOf("}", this.state.pos) - this.state.pos, throwOnInvalid); 1287 ++this.state.pos; 1288 if (code === null) { 1289 --this.state.invalidTemplateEscapePosition; // to point to the '\'' instead of the 'u' 1290 } else if (code > 0x10FFFF) { 1291 if (throwOnInvalid) { 1292 this.raise(codePos, "Code point out of bounds"); 1293 } else { 1294 this.state.invalidTemplateEscapePosition = codePos - 2; 1295 return null; 1296 } 1297 } 1298 } else { 1299 code = this.readHexChar(4, throwOnInvalid); 1300 } 1301 return code; 1302 }; 1303 1304 Tokenizer.prototype.readString = function readString(quote) { 1305 var out = "", 1306 chunkStart = ++this.state.pos; 1307 for (;;) { 1308 if (this.state.pos >= this.input.length) this.raise(this.state.start, "Unterminated string constant"); 1309 var ch = this.input.charCodeAt(this.state.pos); 1310 if (ch === quote) break; 1311 if (ch === 92) { 1312 // '\' 1313 out += this.input.slice(chunkStart, this.state.pos); 1314 out += this.readEscapedChar(false); 1315 chunkStart = this.state.pos; 1316 } else { 1317 if (isNewLine(ch)) this.raise(this.state.start, "Unterminated string constant"); 1318 ++this.state.pos; 1319 } 1320 } 1321 out += this.input.slice(chunkStart, this.state.pos++); 1322 return this.finishToken(types.string, out); 1323 }; 1324 1325 // Reads template string tokens. 1326 1327 Tokenizer.prototype.readTmplToken = function readTmplToken() { 1328 var out = "", 1329 chunkStart = this.state.pos, 1330 containsInvalid = false; 1331 for (;;) { 1332 if (this.state.pos >= this.input.length) this.raise(this.state.start, "Unterminated template"); 1333 var ch = this.input.charCodeAt(this.state.pos); 1334 if (ch === 96 || ch === 36 && this.input.charCodeAt(this.state.pos + 1) === 123) { 1335 // '`', '${' 1336 if (this.state.pos === this.state.start && this.match(types.template)) { 1337 if (ch === 36) { 1338 this.state.pos += 2; 1339 return this.finishToken(types.dollarBraceL); 1340 } else { 1341 ++this.state.pos; 1342 return this.finishToken(types.backQuote); 1343 } 1344 } 1345 out += this.input.slice(chunkStart, this.state.pos); 1346 return this.finishToken(types.template, containsInvalid ? null : out); 1347 } 1348 if (ch === 92) { 1349 // '\' 1350 out += this.input.slice(chunkStart, this.state.pos); 1351 var escaped = this.readEscapedChar(true); 1352 if (escaped === null) { 1353 containsInvalid = true; 1354 } else { 1355 out += escaped; 1356 } 1357 chunkStart = this.state.pos; 1358 } else if (isNewLine(ch)) { 1359 out += this.input.slice(chunkStart, this.state.pos); 1360 ++this.state.pos; 1361 switch (ch) { 1362 case 13: 1363 if (this.input.charCodeAt(this.state.pos) === 10) ++this.state.pos; 1364 case 10: 1365 out += "\n"; 1366 break; 1367 default: 1368 out += String.fromCharCode(ch); 1369 break; 1370 } 1371 ++this.state.curLine; 1372 this.state.lineStart = this.state.pos; 1373 chunkStart = this.state.pos; 1374 } else { 1375 ++this.state.pos; 1376 } 1377 } 1378 }; 1379 1380 // Used to read escaped characters 1381 1382 Tokenizer.prototype.readEscapedChar = function readEscapedChar(inTemplate) { 1383 var throwOnInvalid = !inTemplate; 1384 var ch = this.input.charCodeAt(++this.state.pos); 1385 ++this.state.pos; 1386 switch (ch) { 1387 case 110: 1388 return "\n"; // 'n' -> '\n' 1389 case 114: 1390 return "\r"; // 'r' -> '\r' 1391 case 120: 1392 { 1393 // 'x' 1394 var code = this.readHexChar(2, throwOnInvalid); 1395 return code === null ? null : String.fromCharCode(code); 1396 } 1397 case 117: 1398 { 1399 // 'u' 1400 var _code = this.readCodePoint(throwOnInvalid); 1401 return _code === null ? null : codePointToString(_code); 1402 } 1403 case 116: 1404 return "\t"; // 't' -> '\t' 1405 case 98: 1406 return "\b"; // 'b' -> '\b' 1407 case 118: 1408 return "\x0B"; // 'v' -> '\u000b' 1409 case 102: 1410 return "\f"; // 'f' -> '\f' 1411 case 13: 1412 if (this.input.charCodeAt(this.state.pos) === 10) ++this.state.pos; // '\r\n' 1413 case 10: 1414 // ' \n' 1415 this.state.lineStart = this.state.pos; 1416 ++this.state.curLine; 1417 return ""; 1418 default: 1419 if (ch >= 48 && ch <= 55) { 1420 var codePos = this.state.pos - 1; 1421 var octalStr = this.input.substr(this.state.pos - 1, 3).match(/^[0-7]+/)[0]; 1422 var octal = parseInt(octalStr, 8); 1423 if (octal > 255) { 1424 octalStr = octalStr.slice(0, -1); 1425 octal = parseInt(octalStr, 8); 1426 } 1427 if (octal > 0) { 1428 if (inTemplate) { 1429 this.state.invalidTemplateEscapePosition = codePos; 1430 return null; 1431 } else if (this.state.strict) { 1432 this.raise(codePos, "Octal literal in strict mode"); 1433 } else if (!this.state.containsOctal) { 1434 // These properties are only used to throw an error for an octal which occurs 1435 // in a directive which occurs prior to a "use strict" directive. 1436 this.state.containsOctal = true; 1437 this.state.octalPosition = codePos; 1438 } 1439 } 1440 this.state.pos += octalStr.length - 1; 1441 return String.fromCharCode(octal); 1442 } 1443 return String.fromCharCode(ch); 1444 } 1445 }; 1446 1447 // Used to read character escape sequences ('\x', '\u'). 1448 1449 Tokenizer.prototype.readHexChar = function readHexChar(len, throwOnInvalid) { 1450 var codePos = this.state.pos; 1451 var n = this.readInt(16, len); 1452 if (n === null) { 1453 if (throwOnInvalid) { 1454 this.raise(codePos, "Bad character escape sequence"); 1455 } else { 1456 this.state.pos = codePos - 1; 1457 this.state.invalidTemplateEscapePosition = codePos - 1; 1458 } 1459 } 1460 return n; 1461 }; 1462 1463 // Read an identifier, and return it as a string. Sets `this.state.containsEsc` 1464 // to whether the word contained a '\u' escape. 1465 // 1466 // Incrementally adds only escaped chars, adding other chunks as-is 1467 // as a micro-optimization. 1468 1469 Tokenizer.prototype.readWord1 = function readWord1() { 1470 this.state.containsEsc = false; 1471 var word = "", 1472 first = true, 1473 chunkStart = this.state.pos; 1474 while (this.state.pos < this.input.length) { 1475 var ch = this.fullCharCodeAtPos(); 1476 if (isIdentifierChar(ch)) { 1477 this.state.pos += ch <= 0xffff ? 1 : 2; 1478 } else if (ch === 92) { 1479 // "\" 1480 this.state.containsEsc = true; 1481 1482 word += this.input.slice(chunkStart, this.state.pos); 1483 var escStart = this.state.pos; 1484 1485 if (this.input.charCodeAt(++this.state.pos) !== 117) { 1486 // "u" 1487 this.raise(this.state.pos, "Expecting Unicode escape sequence \\uXXXX"); 1488 } 1489 1490 ++this.state.pos; 1491 var esc = this.readCodePoint(true); 1492 if (!(first ? isIdentifierStart : isIdentifierChar)(esc, true)) { 1493 this.raise(escStart, "Invalid Unicode escape"); 1494 } 1495 1496 word += codePointToString(esc); 1497 chunkStart = this.state.pos; 1498 } else { 1499 break; 1500 } 1501 first = false; 1502 } 1503 return word + this.input.slice(chunkStart, this.state.pos); 1504 }; 1505 1506 // Read an identifier or keyword token. Will check for reserved 1507 // words when necessary. 1508 1509 Tokenizer.prototype.readWord = function readWord() { 1510 var word = this.readWord1(); 1511 var type = types.name; 1512 if (!this.state.containsEsc && this.isKeyword(word)) { 1513 type = keywords[word]; 1514 } 1515 return this.finishToken(type, word); 1516 }; 1517 1518 Tokenizer.prototype.braceIsBlock = function braceIsBlock(prevType) { 1519 if (prevType === types.colon) { 1520 var parent = this.curContext(); 1521 if (parent === types$1.braceStatement || parent === types$1.braceExpression) { 1522 return !parent.isExpr; 1523 } 1524 } 1525 1526 if (prevType === types._return) { 1527 return lineBreak.test(this.input.slice(this.state.lastTokEnd, this.state.start)); 1528 } 1529 1530 if (prevType === types._else || prevType === types.semi || prevType === types.eof || prevType === types.parenR) { 1531 return true; 1532 } 1533 1534 if (prevType === types.braceL) { 1535 return this.curContext() === types$1.braceStatement; 1536 } 1537 1538 return !this.state.exprAllowed; 1539 }; 1540 1541 Tokenizer.prototype.updateContext = function updateContext(prevType) { 1542 var type = this.state.type; 1543 var update = void 0; 1544 1545 if (type.keyword && prevType === types.dot) { 1546 this.state.exprAllowed = false; 1547 } else if (update = type.updateContext) { 1548 update.call(this, prevType); 1549 } else { 1550 this.state.exprAllowed = type.beforeExpr; 1551 } 1552 }; 1553 1554 return Tokenizer; 1555}(); 1556 1557var plugins = {}; 1558var frozenDeprecatedWildcardPluginList = ["jsx", "doExpressions", "objectRestSpread", "decorators", "classProperties", "exportExtensions", "asyncGenerators", "functionBind", "functionSent", "dynamicImport", "flow"]; 1559 1560var Parser = function (_Tokenizer) { 1561 inherits(Parser, _Tokenizer); 1562 1563 function Parser(options, input) { 1564 classCallCheck(this, Parser); 1565 1566 options = getOptions(options); 1567 1568 var _this = possibleConstructorReturn(this, _Tokenizer.call(this, options, input)); 1569 1570 _this.options = options; 1571 _this.inModule = _this.options.sourceType === "module"; 1572 _this.input = input; 1573 _this.plugins = _this.loadPlugins(_this.options.plugins); 1574 _this.filename = options.sourceFilename; 1575 1576 // If enabled, skip leading hashbang line. 1577 if (_this.state.pos === 0 && _this.input[0] === "#" && _this.input[1] === "!") { 1578 _this.skipLineComment(2); 1579 } 1580 return _this; 1581 } 1582 1583 Parser.prototype.isReservedWord = function isReservedWord(word) { 1584 if (word === "await") { 1585 return this.inModule; 1586 } else { 1587 return reservedWords[6](word); 1588 } 1589 }; 1590 1591 Parser.prototype.hasPlugin = function hasPlugin(name) { 1592 if (this.plugins["*"] && frozenDeprecatedWildcardPluginList.indexOf(name) > -1) { 1593 return true; 1594 } 1595 1596 return !!this.plugins[name]; 1597 }; 1598 1599 Parser.prototype.extend = function extend(name, f) { 1600 this[name] = f(this[name]); 1601 }; 1602 1603 Parser.prototype.loadAllPlugins = function loadAllPlugins() { 1604 var _this2 = this; 1605 1606 // ensure flow plugin loads last, also ensure estree is not loaded with * 1607 var pluginNames = Object.keys(plugins).filter(function (name) { 1608 return name !== "flow" && name !== "estree"; 1609 }); 1610 pluginNames.push("flow"); 1611 1612 pluginNames.forEach(function (name) { 1613 var plugin = plugins[name]; 1614 if (plugin) plugin(_this2); 1615 }); 1616 }; 1617 1618 Parser.prototype.loadPlugins = function loadPlugins(pluginList) { 1619 // TODO: Deprecate "*" option in next major version of Babylon 1620 if (pluginList.indexOf("*") >= 0) { 1621 this.loadAllPlugins(); 1622 1623 return { "*": true }; 1624 } 1625 1626 var pluginMap = {}; 1627 1628 if (pluginList.indexOf("flow") >= 0) { 1629 // ensure flow plugin loads last 1630 pluginList = pluginList.filter(function (plugin) { 1631 return plugin !== "flow"; 1632 }); 1633 pluginList.push("flow"); 1634 } 1635 1636 if (pluginList.indexOf("estree") >= 0) { 1637 // ensure estree plugin loads first 1638 pluginList = pluginList.filter(function (plugin) { 1639 return plugin !== "estree"; 1640 }); 1641 pluginList.unshift("estree"); 1642 } 1643 1644 for (var _iterator = pluginList, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { 1645 var _ref; 1646 1647 if (_isArray) { 1648 if (_i >= _iterator.length) break; 1649 _ref = _iterator[_i++]; 1650 } else { 1651 _i = _iterator.next(); 1652 if (_i.done) break; 1653 _ref = _i.value; 1654 } 1655 1656 var name = _ref; 1657 1658 if (!pluginMap[name]) { 1659 pluginMap[name] = true; 1660 1661 var plugin = plugins[name]; 1662 if (plugin) plugin(this); 1663 } 1664 } 1665 1666 return pluginMap; 1667 }; 1668 1669 Parser.prototype.parse = function parse() { 1670 var file = this.startNode(); 1671 var program = this.startNode(); 1672 this.nextToken(); 1673 return this.parseTopLevel(file, program); 1674 }; 1675 1676 return Parser; 1677}(Tokenizer); 1678 1679var pp = Parser.prototype; 1680 1681// ## Parser utilities 1682 1683// TODO 1684 1685pp.addExtra = function (node, key, val) { 1686 if (!node) return; 1687 1688 var extra = node.extra = node.extra || {}; 1689 extra[key] = val; 1690}; 1691 1692// TODO 1693 1694pp.isRelational = function (op) { 1695 return this.match(types.relational) && this.state.value === op; 1696}; 1697 1698// TODO 1699 1700pp.expectRelational = function (op) { 1701 if (this.isRelational(op)) { 1702 this.next(); 1703 } else { 1704 this.unexpected(null, types.relational); 1705 } 1706}; 1707 1708// Tests whether parsed token is a contextual keyword. 1709 1710pp.isContextual = function (name) { 1711 return this.match(types.name) && this.state.value === name; 1712}; 1713 1714// Consumes contextual keyword if possible. 1715 1716pp.eatContextual = function (name) { 1717 return this.state.value === name && this.eat(types.name); 1718}; 1719 1720// Asserts that following token is given contextual keyword. 1721 1722pp.expectContextual = function (name, message) { 1723 if (!this.eatContextual(name)) this.unexpected(null, message); 1724}; 1725 1726// Test whether a semicolon can be inserted at the current position. 1727 1728pp.canInsertSemicolon = function () { 1729 return this.match(types.eof) || this.match(types.braceR) || lineBreak.test(this.input.slice(this.state.lastTokEnd, this.state.start)); 1730}; 1731 1732// TODO 1733 1734pp.isLineTerminator = function () { 1735 return this.eat(types.semi) || this.canInsertSemicolon(); 1736}; 1737 1738// Consume a semicolon, or, failing that, see if we are allowed to 1739// pretend that there is a semicolon at this position. 1740 1741pp.semicolon = function () { 1742 if (!this.isLineTerminator()) this.unexpected(null, types.semi); 1743}; 1744 1745// Expect a token of a given type. If found, consume it, otherwise, 1746// raise an unexpected token error at given pos. 1747 1748pp.expect = function (type, pos) { 1749 return this.eat(type) || this.unexpected(pos, type); 1750}; 1751 1752// Raise an unexpected token error. Can take the expected token type 1753// instead of a message string. 1754 1755pp.unexpected = function (pos) { 1756 var messageOrType = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "Unexpected token"; 1757 1758 if (messageOrType && (typeof messageOrType === "undefined" ? "undefined" : _typeof(messageOrType)) === "object" && messageOrType.label) { 1759 messageOrType = "Unexpected token, expected " + messageOrType.label; 1760 } 1761 this.raise(pos != null ? pos : this.state.start, messageOrType); 1762}; 1763 1764/* eslint max-len: 0 */ 1765 1766var pp$1 = Parser.prototype; 1767 1768// ### Statement parsing 1769 1770// Parse a program. Initializes the parser, reads any number of 1771// statements, and wraps them in a Program node. Optionally takes a 1772// `program` argument. If present, the statements will be appended 1773// to its body instead of creating a new node. 1774 1775pp$1.parseTopLevel = function (file, program) { 1776 program.sourceType = this.options.sourceType; 1777 1778 this.parseBlockBody(program, true, true, types.eof); 1779 1780 file.program = this.finishNode(program, "Program"); 1781 file.comments = this.state.comments; 1782 file.tokens = this.state.tokens; 1783 1784 return this.finishNode(file, "File"); 1785}; 1786 1787var loopLabel = { kind: "loop" }; 1788var switchLabel = { kind: "switch" }; 1789 1790// TODO 1791 1792pp$1.stmtToDirective = function (stmt) { 1793 var expr = stmt.expression; 1794 1795 var directiveLiteral = this.startNodeAt(expr.start, expr.loc.start); 1796 var directive = this.startNodeAt(stmt.start, stmt.loc.start); 1797 1798 var raw = this.input.slice(expr.start, expr.end); 1799 var val = directiveLiteral.value = raw.slice(1, -1); // remove quotes 1800 1801 this.addExtra(directiveLiteral, "raw", raw); 1802 this.addExtra(directiveLiteral, "rawValue", val); 1803 1804 directive.value = this.finishNodeAt(directiveLiteral, "DirectiveLiteral", expr.end, expr.loc.end); 1805 1806 return this.finishNodeAt(directive, "Directive", stmt.end, stmt.loc.end); 1807}; 1808 1809// Parse a single statement. 1810// 1811// If expecting a statement and finding a slash operator, parse a 1812// regular expression literal. This is to handle cases like 1813// `if (foo) /blah/.exec(foo)`, where looking at the previous token 1814// does not help. 1815 1816pp$1.parseStatement = function (declaration, topLevel) { 1817 if (this.match(types.at)) { 1818 this.parseDecorators(true); 1819 } 1820 1821 var starttype = this.state.type; 1822 var node = this.startNode(); 1823 1824 // Most types of statements are recognized by the keyword they 1825 // start with. Many are trivial to parse, some require a bit of 1826 // complexity. 1827 1828 switch (starttype) { 1829 case types._break:case types._continue: 1830 return this.parseBreakContinueStatement(node, starttype.keyword); 1831 case types._debugger: 1832 return this.parseDebuggerStatement(node); 1833 case types._do: 1834 return this.parseDoStatement(node); 1835 case types._for: 1836 return this.parseForStatement(node); 1837 case types._function: 1838 if (!declaration) this.unexpected(); 1839 return this.parseFunctionStatement(node); 1840 1841 case types._class: 1842 if (!declaration) this.unexpected(); 1843 return this.parseClass(node, true); 1844 1845 case types._if: 1846 return this.parseIfStatement(node); 1847 case types._return: 1848 return this.parseReturnStatement(node); 1849 case types._switch: 1850 return this.parseSwitchStatement(node); 1851 case types._throw: 1852 return this.parseThrowStatement(node); 1853 case types._try: 1854 return this.parseTryStatement(node); 1855 1856 case types._let: 1857 case types._const: 1858 if (!declaration) this.unexpected(); // NOTE: falls through to _var 1859 1860 case types._var: 1861 return this.parseVarStatement(node, starttype); 1862 1863 case types._while: 1864 return this.parseWhileStatement(node); 1865 case types._with: 1866 return this.parseWithStatement(node); 1867 case types.braceL: 1868 return this.parseBlock(); 1869 case types.semi: 1870 return this.parseEmptyStatement(node); 1871 case types._export: 1872 case types._import: 1873 if (this.hasPlugin("dynamicImport") && this.lookahead().type === types.parenL) break; 1874 1875 if (!this.options.allowImportExportEverywhere) { 1876 if (!topLevel) { 1877 this.raise(this.state.start, "'import' and 'export' may only appear at the top level"); 1878 } 1879 1880 if (!this.inModule) { 1881 this.raise(this.state.start, "'import' and 'export' may appear only with 'sourceType: \"module\"'"); 1882 } 1883 } 1884 return starttype === types._import ? this.parseImport(node) : this.parseExport(node); 1885 1886 case types.name: 1887 if (this.state.value === "async") { 1888 // peek ahead and see if next token is a function 1889 var state = this.state.clone(); 1890 this.next(); 1891 if (this.match(types._function) && !this.canInsertSemicolon()) { 1892 this.expect(types._function); 1893 return this.parseFunction(node, true, false, true); 1894 } else { 1895 this.state = state; 1896 } 1897 } 1898 } 1899 1900 // If the statement does not start with a statement keyword or a 1901 // brace, it's an ExpressionStatement or LabeledStatement. We 1902 // simply start parsing an expression, and afterwards, if the 1903 // next token is a colon and the expression was a simple 1904 // Identifier node, we switch to interpreting it as a label. 1905 var maybeName = this.state.value; 1906 var expr = this.parseExpression(); 1907 1908 if (starttype === types.name && expr.type === "Identifier" && this.eat(types.colon)) { 1909 return this.parseLabeledStatement(node, maybeName, expr); 1910 } else { 1911 return this.parseExpressionStatement(node, expr); 1912 } 1913}; 1914 1915pp$1.takeDecorators = function (node) { 1916 if (this.state.decorators.length) { 1917 node.decorators = this.state.decorators; 1918 this.state.decorators = []; 1919 } 1920}; 1921 1922pp$1.parseDecorators = function (allowExport) { 1923 while (this.match(types.at)) { 1924 var decorator = this.parseDecorator(); 1925 this.state.decorators.push(decorator); 1926 } 1927 1928 if (allowExport && this.match(types._export)) { 1929 return; 1930 } 1931 1932 if (!this.match(types._class)) { 1933 this.raise(this.state.start, "Leading decorators must be attached to a class declaration"); 1934 } 1935}; 1936 1937pp$1.parseDecorator = function () { 1938 if (!this.hasPlugin("decorators")) { 1939 this.unexpected(); 1940 } 1941 var node = this.startNode(); 1942 this.next(); 1943 node.expression = this.parseMaybeAssign(); 1944 return this.finishNode(node, "Decorator"); 1945}; 1946 1947pp$1.parseBreakContinueStatement = function (node, keyword) { 1948 var isBreak = keyword === "break"; 1949 this.next(); 1950 1951 if (this.isLineTerminator()) { 1952 node.label = null; 1953 } else if (!this.match(types.name)) { 1954 this.unexpected(); 1955 } else { 1956 node.label = this.parseIdentifier(); 1957 this.semicolon(); 1958 } 1959 1960 // Verify that there is an actual destination to break or 1961 // continue to. 1962 var i = void 0; 1963 for (i = 0; i < this.state.labels.length; ++i) { 1964 var lab = this.state.labels[i]; 1965 if (node.label == null || lab.name === node.label.name) { 1966 if (lab.kind != null && (isBreak || lab.kind === "loop")) break; 1967 if (node.label && isBreak) break; 1968 } 1969 } 1970 if (i === this.state.labels.length) this.raise(node.start, "Unsyntactic " + keyword); 1971 return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement"); 1972}; 1973 1974pp$1.parseDebuggerStatement = function (node) { 1975 this.next(); 1976 this.semicolon(); 1977 return this.finishNode(node, "DebuggerStatement"); 1978}; 1979 1980pp$1.parseDoStatement = function (node) { 1981 this.next(); 1982 this.state.labels.push(loopLabel); 1983 node.body = this.parseStatement(false); 1984 this.state.labels.pop(); 1985 this.expect(types._while); 1986 node.test = this.parseParenExpression(); 1987 this.eat(types.semi); 1988 return this.finishNode(node, "DoWhileStatement"); 1989}; 1990 1991// Disambiguating between a `for` and a `for`/`in` or `for`/`of` 1992// loop is non-trivial. Basically, we have to parse the init `var` 1993// statement or expression, disallowing the `in` operator (see 1994// the second parameter to `parseExpression`), and then check 1995// whether the next token is `in` or `of`. When there is no init 1996// part (semicolon immediately after the opening parenthesis), it 1997// is a regular `for` loop. 1998 1999pp$1.parseForStatement = function (node) { 2000 this.next(); 2001 this.state.labels.push(loopLabel); 2002 2003 var forAwait = false; 2004 if (this.hasPlugin("asyncGenerators") && this.state.inAsync && this.isContextual("await")) { 2005 forAwait = true; 2006 this.next(); 2007 } 2008 this.expect(types.parenL); 2009 2010 if (this.match(types.semi)) { 2011 if (forAwait) { 2012 this.unexpected(); 2013 } 2014 return this.parseFor(node, null); 2015 } 2016 2017 if (this.match(types._var) || this.match(types._let) || this.match(types._const)) { 2018 var _init = this.startNode(); 2019 var varKind = this.state.type; 2020 this.next(); 2021 this.parseVar(_init, true, varKind); 2022 this.finishNode(_init, "VariableDeclaration"); 2023 2024 if (this.match(types._in) || this.isContextual("of")) { 2025 if (_init.declarations.length === 1 && !_init.declarations[0].init) { 2026 return this.parseForIn(node, _init, forAwait); 2027 } 2028 } 2029 if (forAwait) { 2030 this.unexpected(); 2031 } 2032 return this.parseFor(node, _init); 2033 } 2034 2035 var refShorthandDefaultPos = { start: 0 }; 2036 var init = this.parseExpression(true, refShorthandDefaultPos); 2037 if (this.match(types._in) || this.isContextual("of")) { 2038 var description = this.isContextual("of") ? "for-of statement" : "for-in statement"; 2039 this.toAssignable(init, undefined, description); 2040 this.checkLVal(init, undefined, undefined, description); 2041 return this.parseForIn(node, init, forAwait); 2042 } else if (refShorthandDefaultPos.start) { 2043 this.unexpected(refShorthandDefaultPos.start); 2044 } 2045 if (forAwait) { 2046 this.unexpected(); 2047 } 2048 return this.parseFor(node, init); 2049}; 2050 2051pp$1.parseFunctionStatement = function (node) { 2052 this.next(); 2053 return this.parseFunction(node, true); 2054}; 2055 2056pp$1.parseIfStatement = function (node) { 2057 this.next(); 2058 node.test = this.parseParenExpression(); 2059 node.consequent = this.parseStatement(false); 2060 node.alternate = this.eat(types._else) ? this.parseStatement(false) : null; 2061 return this.finishNode(node, "IfStatement"); 2062}; 2063 2064pp$1.parseReturnStatement = function (node) { 2065 if (!this.state.inFunction && !this.options.allowReturnOutsideFunction) { 2066 this.raise(this.state.start, "'return' outside of function"); 2067 } 2068 2069 this.next(); 2070 2071 // In `return` (and `break`/`continue`), the keywords with 2072 // optional arguments, we eagerly look for a semicolon or the 2073 // possibility to insert one. 2074 2075 if (this.isLineTerminator()) { 2076 node.argument = null; 2077 } else { 2078 node.argument = this.parseExpression(); 2079 this.semicolon(); 2080 } 2081 2082 return this.finishNode(node, "ReturnStatement"); 2083}; 2084 2085pp$1.parseSwitchStatement = function (node) { 2086 this.next(); 2087 node.discriminant = this.parseParenExpression(); 2088 node.cases = []; 2089 this.expect(types.braceL); 2090 this.state.labels.push(switchLabel); 2091 2092 // Statements under must be grouped (by label) in SwitchCase 2093 // nodes. `cur` is used to keep the node that we are currently 2094 // adding statements to. 2095 2096 var cur = void 0; 2097 for (var sawDefault; !this.match(types.braceR);) { 2098 if (this.match(types._case) || this.match(types._default)) { 2099 var isCase = this.match(types._case); 2100 if (cur) this.finishNode(cur, "SwitchCase"); 2101 node.cases.push(cur = this.startNode()); 2102 cur.consequent = []; 2103 this.next(); 2104 if (isCase) { 2105 cur.test = this.parseExpression(); 2106 } else { 2107 if (sawDefault) this.raise(this.state.lastTokStart, "Multiple default clauses"); 2108 sawDefault = true; 2109 cur.test = null; 2110 } 2111 this.expect(types.colon); 2112 } else { 2113 if (cur) { 2114 cur.consequent.push(this.parseStatement(true)); 2115 } else { 2116 this.unexpected(); 2117 } 2118 } 2119 } 2120 if (cur) this.finishNode(cur, "SwitchCase"); 2121 this.next(); // Closing brace 2122 this.state.labels.pop(); 2123 return this.finishNode(node, "SwitchStatement"); 2124}; 2125 2126pp$1.parseThrowStatement = function (node) { 2127 this.next(); 2128 if (lineBreak.test(this.input.slice(this.state.lastTokEnd, this.state.start))) this.raise(this.state.lastTokEnd, "Illegal newline after throw"); 2129 node.argument = this.parseExpression(); 2130 this.semicolon(); 2131 return this.finishNode(node, "ThrowStatement"); 2132}; 2133 2134// Reused empty array added for node fields that are always empty. 2135 2136var empty = []; 2137 2138pp$1.parseTryStatement = function (node) { 2139 this.next(); 2140 2141 node.block = this.parseBlock(); 2142 node.handler = null; 2143 2144 if (this.match(types._catch)) { 2145 var clause = this.startNode(); 2146 this.next(); 2147 2148 this.expect(types.parenL); 2149 clause.param = this.parseBindingAtom(); 2150 this.checkLVal(clause.param, true, Object.create(null), "catch clause"); 2151 this.expect(types.parenR); 2152 2153 clause.body = this.parseBlock(); 2154 node.handler = this.finishNode(clause, "CatchClause"); 2155 } 2156 2157 node.guardedHandlers = empty; 2158 node.finalizer = this.eat(types._finally) ? this.parseBlock() : null; 2159 2160 if (!node.handler && !node.finalizer) { 2161 this.raise(node.start, "Missing catch or finally clause"); 2162 } 2163 2164 return this.finishNode(node, "TryStatement"); 2165}; 2166 2167pp$1.parseVarStatement = function (node, kind) { 2168 this.next(); 2169 this.parseVar(node, false, kind); 2170 this.semicolon(); 2171 return this.finishNode(node, "VariableDeclaration"); 2172}; 2173 2174pp$1.parseWhileStatement = function (node) { 2175 this.next(); 2176 node.test = this.parseParenExpression(); 2177 this.state.labels.push(loopLabel); 2178 node.body = this.parseStatement(false); 2179 this.state.labels.pop(); 2180 return this.finishNode(node, "WhileStatement"); 2181}; 2182 2183pp$1.parseWithStatement = function (node) { 2184 if (this.state.strict) this.raise(this.state.start, "'with' in strict mode"); 2185 this.next(); 2186 node.object = this.parseParenExpression(); 2187 node.body = this.parseStatement(false); 2188 return this.finishNode(node, "WithStatement"); 2189}; 2190 2191pp$1.parseEmptyStatement = function (node) { 2192 this.next(); 2193 return this.finishNode(node, "EmptyStatement"); 2194}; 2195 2196pp$1.parseLabeledStatement = function (node, maybeName, expr) { 2197 for (var _iterator = this.state.labels, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { 2198 var _ref; 2199 2200 if (_isArray) { 2201 if (_i >= _iterator.length) break; 2202 _ref = _iterator[_i++]; 2203 } else { 2204 _i = _iterator.next(); 2205 if (_i.done) break; 2206 _ref = _i.value; 2207 } 2208 2209 var _label = _ref; 2210 2211 if (_label.name === maybeName) { 2212 this.raise(expr.start, "Label '" + maybeName + "' is already declared"); 2213 } 2214 } 2215 2216 var kind = this.state.type.isLoop ? "loop" : this.match(types._switch) ? "switch" : null; 2217 for (var i = this.state.labels.length - 1; i >= 0; i--) { 2218 var label = this.state.labels[i]; 2219 if (label.statementStart === node.start) { 2220 label.statementStart = this.state.start; 2221 label.kind = kind; 2222 } else { 2223 break; 2224 } 2225 } 2226 2227 this.state.labels.push({ name: maybeName, kind: kind, statementStart: this.state.start }); 2228 node.body = this.parseStatement(true); 2229 this.state.labels.pop(); 2230 node.label = expr; 2231 return this.finishNode(node, "LabeledStatement"); 2232}; 2233 2234pp$1.parseExpressionStatement = function (node, expr) { 2235 node.expression = expr; 2236 this.semicolon(); 2237 return this.finishNode(node, "ExpressionStatement"); 2238}; 2239 2240// Parse a semicolon-enclosed block of statements, handling `"use 2241// strict"` declarations when `allowStrict` is true (used for 2242// function bodies). 2243 2244pp$1.parseBlock = function (allowDirectives) { 2245 var node = this.startNode(); 2246 this.expect(types.braceL); 2247 this.parseBlockBody(node, allowDirectives, false, types.braceR); 2248 return this.finishNode(node, "BlockStatement"); 2249}; 2250 2251pp$1.isValidDirective = function (stmt) { 2252 return stmt.type === "ExpressionStatement" && stmt.expression.type === "StringLiteral" && !stmt.expression.extra.parenthesized; 2253}; 2254 2255pp$1.parseBlockBody = function (node, allowDirectives, topLevel, end) { 2256 node.body = []; 2257 node.directives = []; 2258 2259 var parsedNonDirective = false; 2260 var oldStrict = void 0; 2261 var octalPosition = void 0; 2262 2263 while (!this.eat(end)) { 2264 if (!parsedNonDirective && this.state.containsOctal && !octalPosition) { 2265 octalPosition = this.state.octalPosition; 2266 } 2267 2268 var stmt = this.parseStatement(true, topLevel); 2269 2270 if (allowDirectives && !parsedNonDirective && this.isValidDirective(stmt)) { 2271 var directive = this.stmtToDirective(stmt); 2272 node.directives.push(directive); 2273 2274 if (oldStrict === undefined && directive.value.value === "use strict") { 2275 oldStrict = this.state.strict; 2276 this.setStrict(true); 2277 2278 if (octalPosition) { 2279 this.raise(octalPosition, "Octal literal in strict mode"); 2280 } 2281 } 2282 2283 continue; 2284 } 2285 2286 parsedNonDirective = true; 2287 node.body.push(stmt); 2288 } 2289 2290 if (oldStrict === false) { 2291 this.setStrict(false); 2292 } 2293}; 2294 2295// Parse a regular `for` loop. The disambiguation code in 2296// `parseStatement` will already have parsed the init statement or 2297// expression. 2298 2299pp$1.parseFor = function (node, init) { 2300 node.init = init; 2301 this.expect(types.semi); 2302 node.test = this.match(types.semi) ? null : this.parseExpression(); 2303 this.expect(types.semi); 2304 node.update = this.match(types.parenR) ? null : this.parseExpression(); 2305 this.expect(types.parenR); 2306 node.body = this.parseStatement(false); 2307 this.state.labels.pop(); 2308 return this.finishNode(node, "ForStatement"); 2309}; 2310 2311// Parse a `for`/`in` and `for`/`of` loop, which are almost 2312// same from parser's perspective. 2313 2314pp$1.parseForIn = function (node, init, forAwait) { 2315 var type = void 0; 2316 if (forAwait) { 2317 this.eatContextual("of"); 2318 type = "ForAwaitStatement"; 2319 } else { 2320 type = this.match(types._in) ? "ForInStatement" : "ForOfStatement"; 2321 this.next(); 2322 } 2323 node.left = init; 2324 node.right = this.parseExpression(); 2325 this.expect(types.parenR); 2326 node.body = this.parseStatement(false); 2327 this.state.labels.pop(); 2328 return this.finishNode(node, type); 2329}; 2330 2331// Parse a list of variable declarations. 2332 2333pp$1.parseVar = function (node, isFor, kind) { 2334 node.declarations = []; 2335 node.kind = kind.keyword; 2336 for (;;) { 2337 var decl = this.startNode(); 2338 this.parseVarHead(decl); 2339 if (this.eat(types.eq)) { 2340 decl.init = this.parseMaybeAssign(isFor); 2341 } else if (kind === types._const && !(this.match(types._in) || this.isContextual("of"))) { 2342 this.unexpected(); 2343 } else if (decl.id.type !== "Identifier" && !(isFor && (this.match(types._in) || this.isContextual("of")))) { 2344 this.raise(this.state.lastTokEnd, "Complex binding patterns require an initialization value"); 2345 } else { 2346 decl.init = null; 2347 } 2348 node.declarations.push(this.finishNode(decl, "VariableDeclarator")); 2349 if (!this.eat(types.comma)) break; 2350 } 2351 return node; 2352}; 2353 2354pp$1.parseVarHead = function (decl) { 2355 decl.id = this.parseBindingAtom(); 2356 this.checkLVal(decl.id, true, undefined, "variable declaration"); 2357}; 2358 2359// Parse a function declaration or literal (depending on the 2360// `isStatement` parameter). 2361 2362pp$1.parseFunction = function (node, isStatement, allowExpressionBody, isAsync, optionalId) { 2363 var oldInMethod = this.state.inMethod; 2364 this.state.inMethod = false; 2365 2366 this.initFunction(node, isAsync); 2367 2368 if (this.match(types.star)) { 2369 if (node.async && !this.hasPlugin("asyncGenerators")) { 2370 this.unexpected(); 2371 } else { 2372 node.generator = true; 2373 this.next(); 2374 } 2375 } 2376 2377 if (isStatement && !optionalId && !this.match(types.name) && !this.match(types._yield)) { 2378 this.unexpected(); 2379 } 2380 2381 if (this.match(types.name) || this.match(types._yield)) { 2382 node.id = this.parseBindingIdentifier(); 2383 } 2384 2385 this.parseFunctionParams(node); 2386 this.parseFunctionBody(node, allowExpressionBody); 2387 2388 this.state.inMethod = oldInMethod; 2389 2390 return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression"); 2391}; 2392 2393pp$1.parseFunctionParams = function (node) { 2394 this.expect(types.parenL); 2395 node.params = this.parseBindingList(types.parenR); 2396}; 2397 2398// Parse a class declaration or literal (depending on the 2399// `isStatement` parameter). 2400 2401pp$1.parseClass = function (node, isStatement, optionalId) { 2402 this.next(); 2403 this.takeDecorators(node); 2404 this.parseClassId(node, isStatement, optionalId); 2405 this.parseClassSuper(node); 2406 this.parseClassBody(node); 2407 return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression"); 2408}; 2409 2410pp$1.isClassProperty = function () { 2411 return this.match(types.eq) || this.match(types.semi) || this.match(types.braceR); 2412}; 2413 2414pp$1.isClassMethod = function () { 2415 return this.match(types.parenL); 2416}; 2417 2418pp$1.isNonstaticConstructor = function (method) { 2419 return !method.computed && !method.static && (method.key.name === "constructor" || // Identifier 2420 method.key.value === "constructor" // Literal 2421 ); 2422}; 2423 2424pp$1.parseClassBody = function (node) { 2425 // class bodies are implicitly strict 2426 var oldStrict = this.state.strict; 2427 this.state.strict = true; 2428 2429 var hadConstructorCall = false; 2430 var hadConstructor = false; 2431 var decorators = []; 2432 var classBody = this.startNode(); 2433 2434 classBody.body = []; 2435 2436 this.expect(types.braceL); 2437 2438 while (!this.eat(types.braceR)) { 2439 if (this.eat(types.semi)) { 2440 if (decorators.length > 0) { 2441 this.raise(this.state.lastTokEnd, "Decorators must not be followed by a semicolon"); 2442 } 2443 continue; 2444 } 2445 2446 if (this.match(types.at)) { 2447 decorators.push(this.parseDecorator()); 2448 continue; 2449 } 2450 2451 var method = this.startNode(); 2452 2453 // steal the decorators if there are any 2454 if (decorators.length) { 2455 method.decorators = decorators; 2456 decorators = []; 2457 } 2458 2459 method.static = false; 2460 if (this.match(types.name) && this.state.value === "static") { 2461 var key = this.parseIdentifier(true); // eats 'static' 2462 if (this.isClassMethod()) { 2463 // a method named 'static' 2464 method.kind = "method"; 2465 method.computed = false; 2466 method.key = key; 2467 this.parseClassMethod(classBody, method, false, false); 2468 continue; 2469 } else if (this.isClassProperty()) { 2470 // a property named 'static' 2471 method.computed = false; 2472 method.key = key; 2473 classBody.body.push(this.parseClassProperty(method)); 2474 continue; 2475 } 2476 // otherwise something static 2477 method.static = true; 2478 } 2479 2480 if (this.eat(types.star)) { 2481 // a generator 2482 method.kind = "method"; 2483 this.parsePropertyName(method); 2484 if (this.isNonstaticConstructor(method)) { 2485 this.raise(method.key.start, "Constructor can't be a generator"); 2486 } 2487 if (!method.computed && method.static && (method.key.name === "prototype" || method.key.value === "prototype")) { 2488 this.raise(method.key.start, "Classes may not have static property named prototype"); 2489 } 2490 this.parseClassMethod(classBody, method, true, false); 2491 } else { 2492 var isSimple = this.match(types.name); 2493 var _key = this.parsePropertyName(method); 2494 if (!method.computed && method.static && (method.key.name === "prototype" || method.key.value === "prototype")) { 2495 this.raise(method.key.start, "Classes may not have static property named prototype"); 2496 } 2497 if (this.isClassMethod()) { 2498 // a normal method 2499 if (this.isNonstaticConstructor(method)) { 2500 if (hadConstructor) { 2501 this.raise(_key.start, "Duplicate constructor in the same class"); 2502 } else if (method.decorators) { 2503 this.raise(method.start, "You can't attach decorators to a class constructor"); 2504 } 2505 hadConstructor = true; 2506 method.kind = "constructor"; 2507 } else { 2508 method.kind = "method"; 2509 } 2510 this.parseClassMethod(classBody, method, false, false); 2511 } else if (this.isClassProperty()) { 2512 // a normal property 2513 if (this.isNonstaticConstructor(method)) { 2514 this.raise(method.key.start, "Classes may not have a non-static field named 'constructor'"); 2515 } 2516 classBody.body.push(this.parseClassProperty(method)); 2517 } else if (isSimple && _key.name === "async" && !this.isLineTerminator()) { 2518 // an async method 2519 var isGenerator = this.hasPlugin("asyncGenerators") && this.eat(types.star); 2520 method.kind = "method"; 2521 this.parsePropertyName(method); 2522 if (this.isNonstaticConstructor(method)) { 2523 this.raise(method.key.start, "Constructor can't be an async function"); 2524 } 2525 this.parseClassMethod(classBody, method, isGenerator, true); 2526 } else if (isSimple && (_key.name === "get" || _key.name === "set") && !(this.isLineTerminator() && this.match(types.star))) { 2527 // `get\n*` is an uninitialized property named 'get' followed by a generator. 2528 // a getter or setter 2529 method.kind = _key.name; 2530 this.parsePropertyName(method); 2531 if (this.isNonstaticConstructor(method)) { 2532 this.raise(method.key.start, "Constructor can't have get/set modifier"); 2533 } 2534 this.parseClassMethod(classBody, method, false, false); 2535 this.checkGetterSetterParamCount(method); 2536 } else if (this.hasPlugin("classConstructorCall") && isSimple && _key.name === "call" && this.match(types.name) && this.state.value === "constructor") { 2537 // a (deprecated) call constructor 2538 if (hadConstructorCall) { 2539 this.raise(method.start, "Duplicate constructor call in the same class"); 2540 } else if (method.decorators) { 2541 this.raise(method.start, "You can't attach decorators to a class constructor"); 2542 } 2543 hadConstructorCall = true; 2544 method.kind = "constructorCall"; 2545 this.parsePropertyName(method); // consume "constructor" and make it the method's name 2546 this.parseClassMethod(classBody, method, false, false); 2547 } else if (this.isLineTerminator()) { 2548 // an uninitialized class property (due to ASI, since we don't otherwise recognize the next token) 2549 if (this.isNonstaticConstructor(method)) { 2550 this.raise(method.key.start, "Classes may not have a non-static field named 'constructor'"); 2551 } 2552 classBody.body.push(this.parseClassProperty(method)); 2553 } else { 2554 this.unexpected(); 2555 } 2556 } 2557 } 2558 2559 if (decorators.length) { 2560 this.raise(this.state.start, "You have trailing decorators with no method"); 2561 } 2562 2563 node.body = this.finishNode(classBody, "ClassBody"); 2564 2565 this.state.strict = oldStrict; 2566}; 2567 2568pp$1.parseClassProperty = function (node) { 2569 this.state.inClassProperty = true; 2570 if (this.match(types.eq)) { 2571 if (!this.hasPlugin("classProperties")) this.unexpected(); 2572 this.next(); 2573 node.value = this.parseMaybeAssign(); 2574 } else { 2575 node.value = null; 2576 } 2577 this.semicolon(); 2578 this.state.inClassProperty = false; 2579 return this.finishNode(node, "ClassProperty"); 2580}; 2581 2582pp$1.parseClassMethod = function (classBody, method, isGenerator, isAsync) { 2583 this.parseMethod(method, isGenerator, isAsync); 2584 classBody.body.push(this.finishNode(method, "ClassMethod")); 2585}; 2586 2587pp$1.parseClassId = function (node, isStatement, optionalId) { 2588 if (this.match(types.name)) { 2589 node.id = this.parseIdentifier(); 2590 } else { 2591 if (optionalId || !isStatement) { 2592 node.id = null; 2593 } else { 2594 this.unexpected(); 2595 } 2596 } 2597}; 2598 2599pp$1.parseClassSuper = function (node) { 2600 node.superClass = this.eat(types._extends) ? this.parseExprSubscripts() : null; 2601}; 2602 2603// Parses module export declaration. 2604 2605pp$1.parseExport = function (node) { 2606 this.next(); 2607 // export * from '...' 2608 if (this.match(types.star)) { 2609 var specifier = this.startNode(); 2610 this.next(); 2611 if (this.hasPlugin("exportExtensions") && this.eatContextual("as")) { 2612 specifier.exported = this.parseIdentifier(); 2613 node.specifiers = [this.finishNode(specifier, "ExportNamespaceSpecifier")]; 2614 this.parseExportSpecifiersMaybe(node); 2615 this.parseExportFrom(node, true); 2616 } else { 2617 this.parseExportFrom(node, true); 2618 return this.finishNode(node, "ExportAllDeclaration"); 2619 } 2620 } else if (this.hasPlugin("exportExtensions") && this.isExportDefaultSpecifier()) { 2621 var _specifier = this.startNode(); 2622 _specifier.exported = this.parseIdentifier(true); 2623 node.specifiers = [this.finishNode(_specifier, "ExportDefaultSpecifier")]; 2624 if (this.match(types.comma) && this.lookahead().type === types.star) { 2625 this.expect(types.comma); 2626 var _specifier2 = this.startNode(); 2627 this.expect(types.star); 2628 this.expectContextual("as"); 2629 _specifier2.exported = this.parseIdentifier(); 2630 node.specifiers.push(this.finishNode(_specifier2, "ExportNamespaceSpecifier")); 2631 } else { 2632 this.parseExportSpecifiersMaybe(node); 2633 } 2634 this.parseExportFrom(node, true); 2635 } else if (this.eat(types._default)) { 2636 // export default ... 2637 var expr = this.startNode(); 2638 var needsSemi = false; 2639 if (this.eat(types._function)) { 2640 expr = this.parseFunction(expr, true, false, false, true); 2641 } else if (this.match(types._class)) { 2642 expr = this.parseClass(expr, true, true); 2643 } else { 2644 needsSemi = true; 2645 expr = this.parseMaybeAssign(); 2646 } 2647 node.declaration = expr; 2648 if (needsSemi) this.semicolon(); 2649 this.checkExport(node, true, true); 2650 return this.finishNode(node, "ExportDefaultDeclaration"); 2651 } else if (this.shouldParseExportDeclaration()) { 2652 node.specifiers = []; 2653 node.source = null; 2654 node.declaration = this.parseExportDeclaration(node); 2655 } else { 2656 // export { x, y as z } [from '...'] 2657 node.declaration = null; 2658 node.specifiers = this.parseExportSpecifiers(); 2659 this.parseExportFrom(node); 2660 } 2661 this.checkExport(node, true); 2662 return this.finishNode(node, "ExportNamedDeclaration"); 2663}; 2664 2665pp$1.parseExportDeclaration = function () { 2666 return this.parseStatement(true); 2667}; 2668 2669pp$1.isExportDefaultSpecifier = function () { 2670 if (this.match(types.name)) { 2671 return this.state.value !== "async"; 2672 } 2673 2674 if (!this.match(types._default)) { 2675 return false; 2676 } 2677 2678 var lookahead = this.lookahead(); 2679 return lookahead.type === types.comma || lookahead.type === types.name && lookahead.value === "from"; 2680}; 2681 2682pp$1.parseExportSpecifiersMaybe = function (node) { 2683 if (this.eat(types.comma)) { 2684 node.specifiers = node.specifiers.concat(this.parseExportSpecifiers()); 2685 } 2686}; 2687 2688pp$1.parseExportFrom = function (node, expect) { 2689 if (this.eatContextual("from")) { 2690 node.source = this.match(types.string) ? this.parseExprAtom() : this.unexpected(); 2691 this.checkExport(node); 2692 } else { 2693 if (expect) { 2694 this.unexpected(); 2695 } else { 2696 node.source = null; 2697 } 2698 } 2699 2700 this.semicolon(); 2701}; 2702 2703pp$1.shouldParseExportDeclaration = function () { 2704 return this.state.type.keyword === "var" || this.state.type.keyword === "const" || this.state.type.keyword === "let" || this.state.type.keyword === "function" || this.state.type.keyword === "class" || this.isContextual("async"); 2705}; 2706 2707pp$1.checkExport = function (node, checkNames, isDefault) { 2708 if (checkNames) { 2709 // Check for duplicate exports 2710 if (isDefault) { 2711 // Default exports 2712 this.checkDuplicateExports(node, "default"); 2713 } else if (node.specifiers && node.specifiers.length) { 2714 // Named exports 2715 for (var _iterator2 = node.specifiers, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) { 2716 var _ref2; 2717 2718 if (_isArray2) { 2719 if (_i2 >= _iterator2.length) break; 2720 _ref2 = _iterator2[_i2++]; 2721 } else { 2722 _i2 = _iterator2.next(); 2723 if (_i2.done) break; 2724 _ref2 = _i2.value; 2725 } 2726 2727 var specifier = _ref2; 2728 2729 this.checkDuplicateExports(specifier, specifier.exported.name); 2730 } 2731 } else if (node.declaration) { 2732 // Exported declarations 2733 if (node.declaration.type === "FunctionDeclaration" || node.declaration.type === "ClassDeclaration") { 2734 this.checkDuplicateExports(node, node.declaration.id.name); 2735 } else if (node.declaration.type === "VariableDeclaration") { 2736 for (var _iterator3 = node.declaration.declarations, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) { 2737 var _ref3; 2738 2739 if (_isArray3) { 2740 if (_i3 >= _iterator3.length) break; 2741 _ref3 = _iterator3[_i3++]; 2742 } else { 2743 _i3 = _iterator3.next(); 2744 if (_i3.done) break; 2745 _ref3 = _i3.value; 2746 } 2747 2748 var declaration = _ref3; 2749 2750 this.checkDeclaration(declaration.id); 2751 } 2752 } 2753 } 2754 } 2755 2756 if (this.state.decorators.length) { 2757 var isClass = node.declaration && (node.declaration.type === "ClassDeclaration" || node.declaration.type === "ClassExpression"); 2758 if (!node.declaration || !isClass) { 2759 this.raise(node.start, "You can only use decorators on an export when exporting a class"); 2760 } 2761 this.takeDecorators(node.declaration); 2762 } 2763}; 2764 2765pp$1.checkDeclaration = function (node) { 2766 if (node.type === "ObjectPattern") { 2767 for (var _iterator4 = node.properties, _isArray4 = Array.isArray(_iterator4), _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : _iterator4[Symbol.iterator]();;) { 2768 var _ref4; 2769 2770 if (_isArray4) { 2771 if (_i4 >= _iterator4.length) break; 2772 _ref4 = _iterator4[_i4++]; 2773 } else { 2774 _i4 = _iterator4.next(); 2775 if (_i4.done) break; 2776 _ref4 = _i4.value; 2777 } 2778 2779 var prop = _ref4; 2780 2781 this.checkDeclaration(prop); 2782 } 2783 } else if (node.type === "ArrayPattern") { 2784 for (var _iterator5 = node.elements, _isArray5 = Array.isArray(_iterator5), _i5 = 0, _iterator5 = _isArray5 ? _iterator5 : _iterator5[Symbol.iterator]();;) { 2785 var _ref5; 2786 2787 if (_isArray5) { 2788 if (_i5 >= _iterator5.length) break; 2789 _ref5 = _iterator5[_i5++]; 2790 } else { 2791 _i5 = _iterator5.next(); 2792 if (_i5.done) break; 2793 _ref5 = _i5.value; 2794 } 2795 2796 var elem = _ref5; 2797 2798 if (elem) { 2799 this.checkDeclaration(elem); 2800 } 2801 } 2802 } else if (node.type === "ObjectProperty") { 2803 this.checkDeclaration(node.value); 2804 } else if (node.type === "RestElement" || node.type === "RestProperty") { 2805 this.checkDeclaration(node.argument); 2806 } else if (node.type === "Identifier") { 2807 this.checkDuplicateExports(node, node.name); 2808 } 2809}; 2810 2811pp$1.checkDuplicateExports = function (node, name) { 2812 if (this.state.exportedIdentifiers.indexOf(name) > -1) { 2813 this.raiseDuplicateExportError(node, name); 2814 } 2815 this.state.exportedIdentifiers.push(name); 2816}; 2817 2818pp$1.raiseDuplicateExportError = function (node, name) { 2819 this.raise(node.start, name === "default" ? "Only one default export allowed per module." : "`" + name + "` has already been exported. Exported identifiers must be unique."); 2820}; 2821 2822// Parses a comma-separated list of module exports. 2823 2824pp$1.parseExportSpecifiers = function () { 2825 var nodes = []; 2826 var first = true; 2827 var needsFrom = void 0; 2828 2829 // export { x, y as z } [from '...'] 2830 this.expect(types.braceL); 2831 2832 while (!this.eat(types.braceR)) { 2833 if (first) { 2834 first = false; 2835 } else { 2836 this.expect(types.comma); 2837 if (this.eat(types.braceR)) break; 2838 } 2839 2840 var isDefault = this.match(types._default); 2841 if (isDefault && !needsFrom) needsFrom = true; 2842 2843 var node = this.startNode(); 2844 node.local = this.parseIdentifier(isDefault); 2845 node.exported = this.eatContextual("as") ? this.parseIdentifier(true) : node.local.__clone(); 2846 nodes.push(this.finishNode(node, "ExportSpecifier")); 2847 } 2848 2849 // https://github.com/ember-cli/ember-cli/pull/3739 2850 if (needsFrom && !this.isContextual("from")) { 2851 this.unexpected(); 2852 } 2853 2854 return nodes; 2855}; 2856 2857// Parses import declaration. 2858 2859pp$1.parseImport = function (node) { 2860 this.eat(types._import); 2861 2862 // import '...' 2863 if (this.match(types.string)) { 2864 node.specifiers = []; 2865 node.source = this.parseExprAtom(); 2866 } else { 2867 node.specifiers = []; 2868 this.parseImportSpecifiers(node); 2869 this.expectContextual("from"); 2870 node.source = this.match(types.string) ? this.parseExprAtom() : this.unexpected(); 2871 } 2872 this.semicolon(); 2873 return this.finishNode(node, "ImportDeclaration"); 2874}; 2875 2876// Parses a comma-separated list of module imports. 2877 2878pp$1.parseImportSpecifiers = function (node) { 2879 var first = true; 2880 if (this.match(types.name)) { 2881 // import defaultObj, { x, y as z } from '...' 2882 var startPos = this.state.start; 2883 var startLoc = this.state.startLoc; 2884 node.specifiers.push(this.parseImportSpecifierDefault(this.parseIdentifier(), startPos, startLoc)); 2885 if (!this.eat(types.comma)) return; 2886 } 2887 2888 if (this.match(types.star)) { 2889 var specifier = this.startNode(); 2890 this.next(); 2891 this.expectContextual("as"); 2892 specifier.local = this.parseIdentifier(); 2893 this.checkLVal(specifier.local, true, undefined, "import namespace specifier"); 2894 node.specifiers.push(this.finishNode(specifier, "ImportNamespaceSpecifier")); 2895 return; 2896 } 2897 2898 this.expect(types.braceL); 2899 while (!this.eat(types.braceR)) { 2900 if (first) { 2901 first = false; 2902 } else { 2903 // Detect an attempt to deep destructure 2904 if (this.eat(types.colon)) { 2905 this.unexpected(null, "ES2015 named imports do not destructure. Use another statement for destructuring after the import."); 2906 } 2907 2908 this.expect(types.comma); 2909 if (this.eat(types.braceR)) break; 2910 } 2911 2912 this.parseImportSpecifier(node); 2913 } 2914}; 2915 2916pp$1.parseImportSpecifier = function (node) { 2917 var specifier = this.startNode(); 2918 specifier.imported = this.parseIdentifier(true); 2919 if (this.eatContextual("as")) { 2920 specifier.local = this.parseIdentifier(); 2921 } else { 2922 this.checkReservedWord(specifier.imported.name, specifier.start, true, true); 2923 specifier.local = specifier.imported.__clone(); 2924 } 2925 this.checkLVal(specifier.local, true, undefined, "import specifier"); 2926 node.specifiers.push(this.finishNode(specifier, "ImportSpecifier")); 2927}; 2928 2929pp$1.parseImportSpecifierDefault = function (id, startPos, startLoc) { 2930 var node = this.startNodeAt(startPos, startLoc); 2931 node.local = id; 2932 this.checkLVal(node.local, true, undefined, "default import specifier"); 2933 return this.finishNode(node, "ImportDefaultSpecifier"); 2934}; 2935 2936var pp$2 = Parser.prototype; 2937 2938// Convert existing expression atom to assignable pattern 2939// if possible. 2940 2941pp$2.toAssignable = function (node, isBinding, contextDescription) { 2942 if (node) { 2943 switch (node.type) { 2944 case "Identifier": 2945 case "ObjectPattern": 2946 case "ArrayPattern": 2947 case "AssignmentPattern": 2948 break; 2949 2950 case "ObjectExpression": 2951 node.type = "ObjectPattern"; 2952 for (var _iterator = node.properties, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { 2953 var _ref; 2954 2955 if (_isArray) { 2956 if (_i >= _iterator.length) break; 2957 _ref = _iterator[_i++]; 2958 } else { 2959 _i = _iterator.next(); 2960 if (_i.done) break; 2961 _ref = _i.value; 2962 } 2963 2964 var prop = _ref; 2965 2966 if (prop.type === "ObjectMethod") { 2967 if (prop.kind === "get" || prop.kind === "set") { 2968 this.raise(prop.key.start, "Object pattern can't contain getter or setter"); 2969 } else { 2970 this.raise(prop.key.start, "Object pattern can't contain methods"); 2971 } 2972 } else { 2973 this.toAssignable(prop, isBinding, "object destructuring pattern"); 2974 } 2975 } 2976 break; 2977 2978 case "ObjectProperty": 2979 this.toAssignable(node.value, isBinding, contextDescription); 2980 break; 2981 2982 case "SpreadProperty": 2983 node.type = "RestProperty"; 2984 var arg = node.argument; 2985 this.toAssignable(arg, isBinding, contextDescription); 2986 break; 2987 2988 case "ArrayExpression": 2989 node.type = "ArrayPattern"; 2990 this.toAssignableList(node.elements, isBinding, contextDescription); 2991 break; 2992 2993 case "AssignmentExpression": 2994 if (node.operator === "=") { 2995 node.type = "AssignmentPattern"; 2996 delete node.operator; 2997 } else { 2998 this.raise(node.left.end, "Only '=' operator can be used for specifying default value."); 2999 } 3000 break; 3001 3002 case "MemberExpression": 3003 if (!isBinding) break; 3004 3005 default: 3006 { 3007 var message = "Invalid left-hand side" + (contextDescription ? " in " + contextDescription : /* istanbul ignore next */"expression"); 3008 this.raise(node.start, message); 3009 } 3010 } 3011 } 3012 return node; 3013}; 3014 3015// Convert list of expression atoms to binding list. 3016 3017pp$2.toAssignableList = function (exprList, isBinding, contextDescription) { 3018 var end = exprList.length; 3019 if (end) { 3020 var last = exprList[end - 1]; 3021 if (last && last.type === "RestElement") { 3022 --end; 3023 } else if (last && last.type === "SpreadElement") { 3024 last.type = "RestElement"; 3025 var arg = last.argument; 3026 this.toAssignable(arg, isBinding, contextDescription); 3027 if (arg.type !== "Identifier" && arg.type !== "MemberExpression" && arg.type !== "ArrayPattern") { 3028 this.unexpected(arg.start); 3029 } 3030 --end; 3031 } 3032 } 3033 for (var i = 0; i < end; i++) { 3034 var elt = exprList[i]; 3035 if (elt) this.toAssignable(elt, isBinding, contextDescription); 3036 } 3037 return exprList; 3038}; 3039 3040// Convert list of expression atoms to a list of 3041 3042pp$2.toReferencedList = function (exprList) { 3043 return exprList; 3044}; 3045 3046// Parses spread element. 3047 3048pp$2.parseSpread = function (refShorthandDefaultPos) { 3049 var node = this.startNode(); 3050 this.next(); 3051 node.argument = this.parseMaybeAssign(false, refShorthandDefaultPos); 3052 return this.finishNode(node, "SpreadElement"); 3053}; 3054 3055pp$2.parseRest = function () { 3056 var node = this.startNode(); 3057 this.next(); 3058 node.argument = this.parseBindingIdentifier(); 3059 return this.finishNode(node, "RestElement"); 3060}; 3061 3062pp$2.shouldAllowYieldIdentifier = function () { 3063 return this.match(types._yield) && !this.state.strict && !this.state.inGenerator; 3064}; 3065 3066pp$2.parseBindingIdentifier = function () { 3067 return this.parseIdentifier(this.shouldAllowYieldIdentifier()); 3068}; 3069 3070// Parses lvalue (assignable) atom. 3071 3072pp$2.parseBindingAtom = function () { 3073 switch (this.state.type) { 3074 case types._yield: 3075 if (this.state.strict || this.state.inGenerator) this.unexpected(); 3076 // fall-through 3077 case types.name: 3078 return this.parseIdentifier(true); 3079 3080 case types.bracketL: 3081 var node = this.startNode(); 3082 this.next(); 3083 node.elements = this.parseBindingList(types.bracketR, true); 3084 return this.finishNode(node, "ArrayPattern"); 3085 3086 case types.braceL: 3087 return this.parseObj(true); 3088 3089 default: 3090 this.unexpected(); 3091 } 3092}; 3093 3094pp$2.parseBindingList = function (close, allowEmpty) { 3095 var elts = []; 3096 var first = true; 3097 while (!this.eat(close)) { 3098 if (first) { 3099 first = false; 3100 } else { 3101 this.expect(types.comma); 3102 } 3103 if (allowEmpty && this.match(types.comma)) { 3104 elts.push(null); 3105 } else if (this.eat(close)) { 3106 break; 3107 } else if (this.match(types.ellipsis)) { 3108 elts.push(this.parseAssignableListItemTypes(this.parseRest())); 3109 this.expect(close); 3110 break; 3111 } else { 3112 var decorators = []; 3113 while (this.match(types.at)) { 3114 decorators.push(this.parseDecorator()); 3115 } 3116 var left = this.parseMaybeDefault(); 3117 if (decorators.length) { 3118 left.decorators = decorators; 3119 } 3120 this.parseAssignableListItemTypes(left); 3121 elts.push(this.parseMaybeDefault(left.start, left.loc.start, left)); 3122 } 3123 } 3124 return elts; 3125}; 3126 3127pp$2.parseAssignableListItemTypes = function (param) { 3128 return param; 3129}; 3130 3131// Parses assignment pattern around given atom if possible. 3132 3133pp$2.parseMaybeDefault = function (startPos, startLoc, left) { 3134 startLoc = startLoc || this.state.startLoc; 3135 startPos = startPos || this.state.start; 3136 left = left || this.parseBindingAtom(); 3137 if (!this.eat(types.eq)) return left; 3138 3139 var node = this.startNodeAt(startPos, startLoc); 3140 node.left = left; 3141 node.right = this.parseMaybeAssign(); 3142 return this.finishNode(node, "AssignmentPattern"); 3143}; 3144 3145// Verify that a node is an lval — something that can be assigned 3146// to. 3147 3148pp$2.checkLVal = function (expr, isBinding, checkClashes, contextDescription) { 3149 switch (expr.type) { 3150 case "Identifier": 3151 this.checkReservedWord(expr.name, expr.start, false, true); 3152 3153 if (checkClashes) { 3154 // we need to prefix this with an underscore for the cases where we have a key of 3155 // `__proto__`. there's a bug in old V8 where the following wouldn't work: 3156 // 3157 // > var obj = Object.create(null); 3158 // undefined 3159 // > obj.__proto__ 3160 // null 3161 // > obj.__proto__ = true; 3162 // true 3163 // > obj.__proto__ 3164 // null 3165 var key = "_" + expr.name; 3166 3167 if (checkClashes[key]) { 3168 this.raise(expr.start, "Argument name clash in strict mode"); 3169 } else { 3170 checkClashes[key] = true; 3171 } 3172 } 3173 break; 3174 3175 case "MemberExpression": 3176 if (isBinding) this.raise(expr.start, (isBinding ? "Binding" : "Assigning to") + " member expression"); 3177 break; 3178 3179 case "ObjectPattern": 3180 for (var _iterator2 = expr.properties, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) { 3181 var _ref2; 3182 3183 if (_isArray2) { 3184 if (_i2 >= _iterator2.length) break; 3185 _ref2 = _iterator2[_i2++]; 3186 } else { 3187 _i2 = _iterator2.next(); 3188 if (_i2.done) break; 3189 _ref2 = _i2.value; 3190 } 3191 3192 var prop = _ref2; 3193 3194 if (prop.type === "ObjectProperty") prop = prop.value; 3195 this.checkLVal(prop, isBinding, checkClashes, "object destructuring pattern"); 3196 } 3197 break; 3198 3199 case "ArrayPattern": 3200 for (var _iterator3 = expr.elements, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) { 3201 var _ref3; 3202 3203 if (_isArray3) { 3204 if (_i3 >= _iterator3.length) break; 3205 _ref3 = _iterator3[_i3++]; 3206 } else { 3207 _i3 = _iterator3.next(); 3208 if (_i3.done) break; 3209 _ref3 = _i3.value; 3210 } 3211 3212 var elem = _ref3; 3213 3214 if (elem) this.checkLVal(elem, isBinding, checkClashes, "array destructuring pattern"); 3215 } 3216 break; 3217 3218 case "AssignmentPattern": 3219 this.checkLVal(expr.left, isBinding, checkClashes, "assignment pattern"); 3220 break; 3221 3222 case "RestProperty": 3223 this.checkLVal(expr.argument, isBinding, checkClashes, "rest property"); 3224 break; 3225 3226 case "RestElement": 3227 this.checkLVal(expr.argument, isBinding, checkClashes, "rest element"); 3228 break; 3229 3230 default: 3231 { 3232 var message = (isBinding ? /* istanbul ignore next */"Binding invalid" : "Invalid") + " left-hand side" + (contextDescription ? " in " + contextDescription : /* istanbul ignore next */"expression"); 3233 this.raise(expr.start, message); 3234 } 3235 } 3236}; 3237 3238/* eslint max-len: 0 */ 3239 3240// A recursive descent parser operates by defining functions for all 3241// syntactic elements, and recursively calling those, each function 3242// advancing the input stream and returning an AST node. Precedence 3243// of constructs (for example, the fact that `!x[1]` means `!(x[1])` 3244// instead of `(!x)[1]` is handled by the fact that the parser 3245// function that parses unary prefix operators is called first, and 3246// in turn calls the function that parses `[]` subscripts — that 3247// way, it'll receive the node for `x[1]` already parsed, and wraps 3248// *that* in the unary operator node. 3249// 3250// Acorn uses an [operator precedence parser][opp] to handle binary 3251// operator precedence, because it is much more compact than using 3252// the technique outlined above, which uses different, nesting 3253// functions to specify precedence, for all of the ten binary 3254// precedence levels that JavaScript defines. 3255// 3256// [opp]: http://en.wikipedia.org/wiki/Operator-precedence_parser 3257 3258var pp$3 = Parser.prototype; 3259 3260// Check if property name clashes with already added. 3261// Object/class getters and setters are not allowed to clash — 3262// either with each other or with an init property — and in 3263// strict mode, init properties are also not allowed to be repeated. 3264 3265pp$3.checkPropClash = function (prop, propHash) { 3266 if (prop.computed || prop.kind) return; 3267 3268 var key = prop.key; 3269 // It is either an Identifier or a String/NumericLiteral 3270 var name = key.type === "Identifier" ? key.name : String(key.value); 3271 3272 if (name === "__proto__") { 3273 if (propHash.proto) this.raise(key.start, "Redefinition of __proto__ property"); 3274 propHash.proto = true; 3275 } 3276}; 3277 3278// Convenience method to parse an Expression only 3279pp$3.getExpression = function () { 3280 this.nextToken(); 3281 var expr = this.parseExpression(); 3282 if (!this.match(types.eof)) { 3283 this.unexpected(); 3284 } 3285 return expr; 3286}; 3287 3288// ### Expression parsing 3289 3290// These nest, from the most general expression type at the top to 3291// 'atomic', nondivisible expression types at the bottom. Most of 3292// the functions will simply let the function (s) below them parse, 3293// and, *if* the syntactic construct they handle is present, wrap 3294// the AST node that the inner parser gave them in another node. 3295 3296// Parse a full expression. The optional arguments are used to 3297// forbid the `in` operator (in for loops initialization expressions) 3298// and provide reference for storing '=' operator inside shorthand 3299// property assignment in contexts where both object expression 3300// and object pattern might appear (so it's possible to raise 3301// delayed syntax error at correct position). 3302 3303pp$3.parseExpression = function (noIn, refShorthandDefaultPos) { 3304 var startPos = this.state.start; 3305 var startLoc = this.state.startLoc; 3306 var expr = this.parseMaybeAssign(noIn, refShorthandDefaultPos); 3307 if (this.match(types.comma)) { 3308 var node = this.startNodeAt(startPos, startLoc); 3309 node.expressions = [expr]; 3310 while (this.eat(types.comma)) { 3311 node.expressions.push(this.parseMaybeAssign(noIn, refShorthandDefaultPos)); 3312 } 3313 this.toReferencedList(node.expressions); 3314 return this.finishNode(node, "SequenceExpression"); 3315 } 3316 return expr; 3317}; 3318 3319// Parse an assignment expression. This includes applications of 3320// operators like `+=`. 3321 3322pp$3.parseMaybeAssign = function (noIn, refShorthandDefaultPos, afterLeftParse, refNeedsArrowPos) { 3323 var startPos = this.state.start; 3324 var startLoc = this.state.startLoc; 3325 3326 if (this.match(types._yield) && this.state.inGenerator) { 3327 var _left = this.parseYield(); 3328 if (afterLeftParse) _left = afterLeftParse.call(this, _left, startPos, startLoc); 3329 return _left; 3330 } 3331 3332 var failOnShorthandAssign = void 0; 3333 if (refShorthandDefaultPos) { 3334 failOnShorthandAssign = false; 3335 } else { 3336 refShorthandDefaultPos = { start: 0 }; 3337 failOnShorthandAssign = true; 3338 } 3339 3340 if (this.match(types.parenL) || this.match(types.name)) { 3341 this.state.potentialArrowAt = this.state.start; 3342 } 3343 3344 var left = this.parseMaybeConditional(noIn, refShorthandDefaultPos, refNeedsArrowPos); 3345 if (afterLeftParse) left = afterLeftParse.call(this, left, startPos, startLoc); 3346 if (this.state.type.isAssign) { 3347 var node = this.startNodeAt(startPos, startLoc); 3348 node.operator = this.state.value; 3349 node.left = this.match(types.eq) ? this.toAssignable(left, undefined, "assignment expression") : left; 3350 refShorthandDefaultPos.start = 0; // reset because shorthand default was used correctly 3351 3352 this.checkLVal(left, undefined, undefined, "assignment expression"); 3353 3354 if (left.extra && left.extra.parenthesized) { 3355 var errorMsg = void 0; 3356 if (left.type === "ObjectPattern") { 3357 errorMsg = "`({a}) = 0` use `({a} = 0)`"; 3358 } else if (left.type === "ArrayPattern") { 3359 errorMsg = "`([a]) = 0` use `([a] = 0)`"; 3360 } 3361 if (errorMsg) { 3362 this.raise(left.start, "You're trying to assign to a parenthesized expression, eg. instead of " + errorMsg); 3363 } 3364 } 3365 3366 this.next(); 3367 node.right = this.parseMaybeAssign(noIn); 3368 return this.finishNode(node, "AssignmentExpression"); 3369 } else if (failOnShorthandAssign && refShorthandDefaultPos.start) { 3370 this.unexpected(refShorthandDefaultPos.start); 3371 } 3372 3373 return left; 3374}; 3375 3376// Parse a ternary conditional (`?:`) operator. 3377 3378pp$3.parseMaybeConditional = function (noIn, refShorthandDefaultPos, refNeedsArrowPos) { 3379 var startPos = this.state.start; 3380 var startLoc = this.state.startLoc; 3381 var expr = this.parseExprOps(noIn, refShorthandDefaultPos); 3382 if (refShorthandDefaultPos && refShorthandDefaultPos.start) return expr; 3383 3384 return this.parseConditional(expr, noIn, startPos, startLoc, refNeedsArrowPos); 3385}; 3386 3387pp$3.parseConditional = function (expr, noIn, startPos, startLoc) { 3388 if (this.eat(types.question)) { 3389 var node = this.startNodeAt(startPos, startLoc); 3390 node.test = expr; 3391 node.consequent = this.parseMaybeAssign(); 3392 this.expect(types.colon); 3393 node.alternate = this.parseMaybeAssign(noIn); 3394 return this.finishNode(node, "ConditionalExpression"); 3395 } 3396 return expr; 3397}; 3398 3399// Start the precedence parser. 3400 3401pp$3.parseExprOps = function (noIn, refShorthandDefaultPos) { 3402 var startPos = this.state.start; 3403 var startLoc = this.state.startLoc; 3404 var expr = this.parseMaybeUnary(refShorthandDefaultPos); 3405 if (refShorthandDefaultPos && refShorthandDefaultPos.start) { 3406 return expr; 3407 } else { 3408 return this.parseExprOp(expr, startPos, startLoc, -1, noIn); 3409 } 3410}; 3411 3412// Parse binary operators with the operator precedence parsing 3413// algorithm. `left` is the left-hand side of the operator. 3414// `minPrec` provides context that allows the function to stop and 3415// defer further parser to one of its callers when it encounters an 3416// operator that has a lower precedence than the set it is parsing. 3417 3418pp$3.parseExprOp = function (left, leftStartPos, leftStartLoc, minPrec, noIn) { 3419 var prec = this.state.type.binop; 3420 if (prec != null && (!noIn || !this.match(types._in))) { 3421 if (prec > minPrec) { 3422 var node = this.startNodeAt(leftStartPos, leftStartLoc); 3423 node.left = left; 3424 node.operator = this.state.value; 3425 3426 if (node.operator === "**" && left.type === "UnaryExpression" && left.extra && !left.extra.parenthesizedArgument && !left.extra.parenthesized) { 3427 this.raise(left.argument.start, "Illegal expression. Wrap left hand side or entire exponentiation in parentheses."); 3428 } 3429 3430 var op = this.state.type; 3431 this.next(); 3432 3433 var startPos = this.state.start; 3434 var startLoc = this.state.startLoc; 3435 node.right = this.parseExprOp(this.parseMaybeUnary(), startPos, startLoc, op.rightAssociative ? prec - 1 : prec, noIn); 3436 3437 this.finishNode(node, op === types.logicalOR || op === types.logicalAND ? "LogicalExpression" : "BinaryExpression"); 3438 return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, noIn); 3439 } 3440 } 3441 return left; 3442}; 3443 3444// Parse unary operators, both prefix and postfix. 3445 3446pp$3.parseMaybeUnary = function (refShorthandDefaultPos) { 3447 if (this.state.type.prefix) { 3448 var node = this.startNode(); 3449 var update = this.match(types.incDec); 3450 node.operator = this.state.value; 3451 node.prefix = true; 3452 this.next(); 3453 3454 var argType = this.state.type; 3455 node.argument = this.parseMaybeUnary(); 3456 3457 this.addExtra(node, "parenthesizedArgument", argType === types.parenL && (!node.argument.extra || !node.argument.extra.parenthesized)); 3458 3459 if (refShorthandDefaultPos && refShorthandDefaultPos.start) { 3460 this.unexpected(refShorthandDefaultPos.start); 3461 } 3462 3463 if (update) { 3464 this.checkLVal(node.argument, undefined, undefined, "prefix operation"); 3465 } else if (this.state.strict && node.operator === "delete" && node.argument.type === "Identifier") { 3466 this.raise(node.start, "Deleting local variable in strict mode"); 3467 } 3468 3469 return this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression"); 3470 } 3471 3472 var startPos = this.state.start; 3473 var startLoc = this.state.startLoc; 3474 var expr = this.parseExprSubscripts(refShorthandDefaultPos); 3475 if (refShorthandDefaultPos && refShorthandDefaultPos.start) return expr; 3476 while (this.state.type.postfix && !this.canInsertSemicolon()) { 3477 var _node = this.startNodeAt(startPos, startLoc); 3478 _node.operator = this.state.value; 3479 _node.prefix = false; 3480 _node.argument = expr; 3481 this.checkLVal(expr, undefined, undefined, "postfix operation"); 3482 this.next(); 3483 expr = this.finishNode(_node, "UpdateExpression"); 3484 } 3485 return expr; 3486}; 3487 3488// Parse call, dot, and `[]`-subscript expressions. 3489 3490pp$3.parseExprSubscripts = function (refShorthandDefaultPos) { 3491 var startPos = this.state.start; 3492 var startLoc = this.state.startLoc; 3493 var potentialArrowAt = this.state.potentialArrowAt; 3494 var expr = this.parseExprAtom(refShorthandDefaultPos); 3495 3496 if (expr.type === "ArrowFunctionExpression" && expr.start === potentialArrowAt) { 3497 return expr; 3498 } 3499 3500 if (refShorthandDefaultPos && refShorthandDefaultPos.start) { 3501 return expr; 3502 } 3503 3504 return this.parseSubscripts(expr, startPos, startLoc); 3505}; 3506 3507pp$3.parseSubscripts = function (base, startPos, startLoc, noCalls) { 3508 for (;;) { 3509 if (!noCalls && this.eat(types.doubleColon)) { 3510 var node = this.startNodeAt(startPos, startLoc); 3511 node.object = base; 3512 node.callee = this.parseNoCallExpr(); 3513 return this.parseSubscripts(this.finishNode(node, "BindExpression"), startPos, startLoc, noCalls); 3514 } else if (this.eat(types.dot)) { 3515 var _node2 = this.startNodeAt(startPos, startLoc); 3516 _node2.object = base; 3517 _node2.property = this.parseIdentifier(true); 3518 _node2.computed = false; 3519 base = this.finishNode(_node2, "MemberExpression"); 3520 } else if (this.eat(types.bracketL)) { 3521 var _node3 = this.startNodeAt(startPos, startLoc); 3522 _node3.object = base; 3523 _node3.property = this.parseExpression(); 3524 _node3.computed = true; 3525 this.expect(types.bracketR); 3526 base = this.finishNode(_node3, "MemberExpression"); 3527 } else if (!noCalls && this.match(types.parenL)) { 3528 var possibleAsync = this.state.potentialArrowAt === base.start && base.type === "Identifier" && base.name === "async" && !this.canInsertSemicolon(); 3529 this.next(); 3530 3531 var _node4 = this.startNodeAt(startPos, startLoc); 3532 _node4.callee = base; 3533 _node4.arguments = this.parseCallExpressionArguments(types.parenR, possibleAsync); 3534 if (_node4.callee.type === "Import" && _node4.arguments.length !== 1) { 3535 this.raise(_node4.start, "import() requires exactly one argument"); 3536 } 3537 base = this.finishNode(_node4, "CallExpression"); 3538 3539 if (possibleAsync && this.shouldParseAsyncArrow()) { 3540 return this.parseAsyncArrowFromCallExpression(this.startNodeAt(startPos, startLoc), _node4); 3541 } else { 3542 this.toReferencedList(_node4.arguments); 3543 } 3544 } else if (this.match(types.backQuote)) { 3545 var _node5 = this.startNodeAt(startPos, startLoc); 3546 _node5.tag = base; 3547 _node5.quasi = this.parseTemplate(true); 3548 base = this.finishNode(_node5, "TaggedTemplateExpression"); 3549 } else { 3550 return base; 3551 } 3552 } 3553}; 3554 3555pp$3.parseCallExpressionArguments = function (close, possibleAsyncArrow) { 3556 var elts = []; 3557 var innerParenStart = void 0; 3558 var first = true; 3559 3560 while (!this.eat(close)) { 3561 if (first) { 3562 first = false; 3563 } else { 3564 this.expect(types.comma); 3565 if (this.eat(close)) break; 3566 } 3567 3568 // we need to make sure that if this is an async arrow functions, that we don't allow inner parens inside the params 3569 if (this.match(types.parenL) && !innerParenStart) { 3570 innerParenStart = this.state.start; 3571 } 3572 3573 elts.push(this.parseExprListItem(false, possibleAsyncArrow ? { start: 0 } : undefined, possibleAsyncArrow ? { start: 0 } : undefined)); 3574 } 3575 3576 // we found an async arrow function so let's not allow any inner parens 3577 if (possibleAsyncArrow && innerParenStart && this.shouldParseAsyncArrow()) { 3578 this.unexpected(); 3579 } 3580 3581 return elts; 3582}; 3583 3584pp$3.shouldParseAsyncArrow = function () { 3585 return this.match(types.arrow); 3586}; 3587 3588pp$3.parseAsyncArrowFromCallExpression = function (node, call) { 3589 this.expect(types.arrow); 3590 return this.parseArrowExpression(node, call.arguments, true); 3591}; 3592 3593// Parse a no-call expression (like argument of `new` or `::` operators). 3594 3595pp$3.parseNoCallExpr = function () { 3596 var startPos = this.state.start; 3597 var startLoc = this.state.startLoc; 3598 return this.parseSubscripts(this.parseExprAtom(), startPos, startLoc, true); 3599}; 3600 3601// Parse an atomic expression — either a single token that is an 3602// expression, an expression started by a keyword like `function` or 3603// `new`, or an expression wrapped in punctuation like `()`, `[]`, 3604// or `{}`. 3605 3606pp$3.parseExprAtom = function (refShorthandDefaultPos) { 3607 var canBeArrow = this.state.potentialArrowAt === this.state.start; 3608 var node = void 0; 3609 3610 switch (this.state.type) { 3611 case types._super: 3612 if (!this.state.inMethod && !this.state.inClassProperty && !this.options.allowSuperOutsideMethod) { 3613 this.raise(this.state.start, "'super' outside of function or class"); 3614 } 3615 3616 node = this.startNode(); 3617 this.next(); 3618 if (!this.match(types.parenL) && !this.match(types.bracketL) && !this.match(types.dot)) { 3619 this.unexpected(); 3620 } 3621 if (this.match(types.parenL) && this.state.inMethod !== "constructor" && !this.options.allowSuperOutsideMethod) { 3622 this.raise(node.start, "super() outside of class constructor"); 3623 } 3624 return this.finishNode(node, "Super"); 3625 3626 case types._import: 3627 if (!this.hasPlugin("dynamicImport")) this.unexpected(); 3628 3629 node = this.startNode(); 3630 this.next(); 3631 if (!this.match(types.parenL)) { 3632 this.unexpected(null, types.parenL); 3633 } 3634 return this.finishNode(node, "Import"); 3635 3636 case types._this: 3637 node = this.startNode(); 3638 this.next(); 3639 return this.finishNode(node, "ThisExpression"); 3640 3641 case types._yield: 3642 if (this.state.inGenerator) this.unexpected(); 3643 3644 case types.name: 3645 node = this.startNode(); 3646 var allowAwait = this.state.value === "await" && this.state.inAsync; 3647 var allowYield = this.shouldAllowYieldIdentifier(); 3648 var id = this.parseIdentifier(allowAwait || allowYield); 3649 3650 if (id.name === "await") { 3651 if (this.state.inAsync || this.inModule) { 3652 return this.parseAwait(node); 3653 } 3654 } else if (id.name === "async" && this.match(types._function) && !this.canInsertSemicolon()) { 3655 this.next(); 3656 return this.parseFunction(node, false, false, true); 3657 } else if (canBeArrow && id.name === "async" && this.match(types.name)) { 3658 var params = [this.parseIdentifier()]; 3659 this.expect(types.arrow); 3660 // let foo = bar => {}; 3661 return this.parseArrowExpression(node, params, true); 3662 } 3663 3664 if (canBeArrow && !this.canInsertSemicolon() && this.eat(types.arrow)) { 3665 return this.parseArrowExpression(node, [id]); 3666 } 3667 3668 return id; 3669 3670 case types._do: 3671 if (this.hasPlugin("doExpressions")) { 3672 var _node6 = this.startNode(); 3673 this.next(); 3674 var oldInFunction = this.state.inFunction; 3675 var oldLabels = this.state.labels; 3676 this.state.labels = []; 3677 this.state.inFunction = false; 3678 _node6.body = this.parseBlock(false, true); 3679 this.state.inFunction = oldInFunction; 3680 this.state.labels = oldLabels; 3681 return this.finishNode(_node6, "DoExpression"); 3682 } 3683 3684 case types.regexp: 3685 var value = this.state.value; 3686 node = this.parseLiteral(value.value, "RegExpLiteral"); 3687 node.pattern = value.pattern; 3688 node.flags = value.flags; 3689 return node; 3690 3691 case types.num: 3692 return this.parseLiteral(this.state.value, "NumericLiteral"); 3693 3694 case types.string: 3695 return this.parseLiteral(this.state.value, "StringLiteral"); 3696 3697 case types._null: 3698 node = this.startNode(); 3699 this.next(); 3700 return this.finishNode(node, "NullLiteral"); 3701 3702 case types._true:case types._false: 3703 node = this.startNode(); 3704 node.value = this.match(types._true); 3705 this.next(); 3706 return this.finishNode(node, "BooleanLiteral"); 3707 3708 case types.parenL: 3709 return this.parseParenAndDistinguishExpression(null, null, canBeArrow); 3710 3711 case types.bracketL: 3712 node = this.startNode(); 3713 this.next(); 3714 node.elements = this.parseExprList(types.bracketR, true, refShorthandDefaultPos); 3715 this.toReferencedList(node.elements); 3716 return this.finishNode(node, "ArrayExpression"); 3717 3718 case types.braceL: 3719 return this.parseObj(false, refShorthandDefaultPos); 3720 3721 case types._function: 3722 return this.parseFunctionExpression(); 3723 3724 case types.at: 3725 this.parseDecorators(); 3726 3727 case types._class: 3728 node = this.startNode(); 3729 this.takeDecorators(node); 3730 return this.parseClass(node, false); 3731 3732 case types._new: 3733 return this.parseNew(); 3734 3735 case types.backQuote: 3736 return this.parseTemplate(false); 3737 3738 case types.doubleColon: 3739 node = this.startNode(); 3740 this.next(); 3741 node.object = null; 3742 var callee = node.callee = this.parseNoCallExpr(); 3743 if (callee.type === "MemberExpression") { 3744 return this.finishNode(node, "BindExpression"); 3745 } else { 3746 this.raise(callee.start, "Binding should be performed on object property."); 3747 } 3748 3749 default: 3750 this.unexpected(); 3751 } 3752}; 3753 3754pp$3.parseFunctionExpression = function () { 3755 var node = this.startNode(); 3756 var meta = this.parseIdentifier(true); 3757 if (this.state.inGenerator && this.eat(types.dot) && this.hasPlugin("functionSent")) { 3758 return this.parseMetaProperty(node, meta, "sent"); 3759 } else { 3760 return this.parseFunction(node, false); 3761 } 3762}; 3763 3764pp$3.parseMetaProperty = function (node, meta, propertyName) { 3765 node.meta = meta; 3766 node.property = this.parseIdentifier(true); 3767 3768 if (node.property.name !== propertyName) { 3769 this.raise(node.property.start, "The only valid meta property for new is " + meta.name + "." + propertyName); 3770 } 3771 3772 return this.finishNode(node, "MetaProperty"); 3773}; 3774 3775pp$3.parseLiteral = function (value, type, startPos, startLoc) { 3776 startPos = startPos || this.state.start; 3777 startLoc = startLoc || this.state.startLoc; 3778 3779 var node = this.startNodeAt(startPos, startLoc); 3780 this.addExtra(node, "rawValue", value); 3781 this.addExtra(node, "raw", this.input.slice(startPos, this.state.end)); 3782 node.value = value; 3783 this.next(); 3784 return this.finishNode(node, type); 3785}; 3786 3787pp$3.parseParenExpression = function () { 3788 this.expect(types.parenL); 3789 var val = this.parseExpression(); 3790 this.expect(types.parenR); 3791 return val; 3792}; 3793 3794pp$3.parseParenAndDistinguishExpression = function (startPos, startLoc, canBeArrow) { 3795 startPos = startPos || this.state.start; 3796 startLoc = startLoc || this.state.startLoc; 3797 3798 var val = void 0; 3799 this.expect(types.parenL); 3800 3801 var innerStartPos = this.state.start; 3802 var innerStartLoc = this.state.startLoc; 3803 var exprList = []; 3804 var refShorthandDefaultPos = { start: 0 }; 3805 var refNeedsArrowPos = { start: 0 }; 3806 var first = true; 3807 var spreadStart = void 0; 3808 var optionalCommaStart = void 0; 3809 3810 while (!this.match(types.parenR)) { 3811 if (first) { 3812 first = false; 3813 } else { 3814 this.expect(types.comma, refNeedsArrowPos.start || null); 3815 if (this.match(types.parenR)) { 3816 optionalCommaStart = this.state.start; 3817 break; 3818 } 3819 } 3820 3821 if (this.match(types.ellipsis)) { 3822 var spreadNodeStartPos = this.state.start; 3823 var spreadNodeStartLoc = this.state.startLoc; 3824 spreadStart = this.state.start; 3825 exprList.push(this.parseParenItem(this.parseRest(), spreadNodeStartPos, spreadNodeStartLoc)); 3826 break; 3827 } else { 3828 exprList.push(this.parseMaybeAssign(false, refShorthandDefaultPos, this.parseParenItem, refNeedsArrowPos)); 3829 } 3830 } 3831 3832 var innerEndPos = this.state.start; 3833 var innerEndLoc = this.state.startLoc; 3834 this.expect(types.parenR); 3835 3836 var arrowNode = this.startNodeAt(startPos, startLoc); 3837 if (canBeArrow && this.shouldParseArrow() && (arrowNode = this.parseArrow(arrowNode))) { 3838 for (var _iterator = exprList, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { 3839 var _ref; 3840 3841 if (_isArray) { 3842 if (_i >= _iterator.length) break; 3843 _ref = _iterator[_i++]; 3844 } else { 3845 _i = _iterator.next(); 3846 if (_i.done) break; 3847 _ref = _i.value; 3848 } 3849 3850 var param = _ref; 3851 3852 if (param.extra && param.extra.parenthesized) this.unexpected(param.extra.parenStart); 3853 } 3854 3855 return this.parseArrowExpression(arrowNode, exprList); 3856 } 3857 3858 if (!exprList.length) { 3859 this.unexpected(this.state.lastTokStart); 3860 } 3861 if (optionalCommaStart) this.unexpected(optionalCommaStart); 3862 if (spreadStart) this.unexpected(spreadStart); 3863 if (refShorthandDefaultPos.start) this.unexpected(refShorthandDefaultPos.start); 3864 if (refNeedsArrowPos.start) this.unexpected(refNeedsArrowPos.start); 3865 3866 if (exprList.length > 1) { 3867 val = this.startNodeAt(innerStartPos, innerStartLoc); 3868 val.expressions = exprList; 3869 this.toReferencedList(val.expressions); 3870 this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc); 3871 } else { 3872 val = exprList[0]; 3873 } 3874 3875 this.addExtra(val, "parenthesized", true); 3876 this.addExtra(val, "parenStart", startPos); 3877 3878 return val; 3879}; 3880 3881pp$3.shouldParseArrow = function () { 3882 return !this.canInsertSemicolon(); 3883}; 3884 3885pp$3.parseArrow = function (node) { 3886 if (this.eat(types.arrow)) { 3887 return node; 3888 } 3889}; 3890 3891pp$3.parseParenItem = function (node) { 3892 return node; 3893}; 3894 3895// New's precedence is slightly tricky. It must allow its argument 3896// to be a `[]` or dot subscript expression, but not a call — at 3897// least, not without wrapping it in parentheses. Thus, it uses the 3898 3899pp$3.parseNew = function () { 3900 var node = this.startNode(); 3901 var meta = this.parseIdentifier(true); 3902 3903 if (this.eat(types.dot)) { 3904 var metaProp = this.parseMetaProperty(node, meta, "target"); 3905 3906 if (!this.state.inFunction) { 3907 this.raise(metaProp.property.start, "new.target can only be used in functions"); 3908 } 3909 3910 return metaProp; 3911 } 3912 3913 node.callee = this.parseNoCallExpr(); 3914 3915 if (this.eat(types.parenL)) { 3916 node.arguments = this.parseExprList(types.parenR); 3917 this.toReferencedList(node.arguments); 3918 } else { 3919 node.arguments = []; 3920 } 3921 3922 return this.finishNode(node, "NewExpression"); 3923}; 3924 3925// Parse template expression. 3926 3927pp$3.parseTemplateElement = function (isTagged) { 3928 var elem = this.startNode(); 3929 if (this.state.value === null) { 3930 if (!isTagged || !this.hasPlugin("templateInvalidEscapes")) { 3931 this.raise(this.state.invalidTemplateEscapePosition, "Invalid escape sequence in template"); 3932 } else { 3933 this.state.invalidTemplateEscapePosition = null; 3934 } 3935 } 3936 elem.value = { 3937 raw: this.input.slice(this.state.start, this.state.end).replace(/\r\n?/g, "\n"), 3938 cooked: this.state.value 3939 }; 3940 this.next(); 3941 elem.tail = this.match(types.backQuote); 3942 return this.finishNode(elem, "TemplateElement"); 3943}; 3944 3945pp$3.parseTemplate = function (isTagged) { 3946 var node = this.startNode(); 3947 this.next(); 3948 node.expressions = []; 3949 var curElt = this.parseTemplateElement(isTagged); 3950 node.quasis = [curElt]; 3951 while (!curElt.tail) { 3952 this.expect(types.dollarBraceL); 3953 node.expressions.push(this.parseExpression()); 3954 this.expect(types.braceR); 3955 node.quasis.push(curElt = this.parseTemplateElement(isTagged)); 3956 } 3957 this.next(); 3958 return this.finishNode(node, "TemplateLiteral"); 3959}; 3960 3961// Parse an object literal or binding pattern. 3962 3963pp$3.parseObj = function (isPattern, refShorthandDefaultPos) { 3964 var decorators = []; 3965 var propHash = Object.create(null); 3966 var first = true; 3967 var node = this.startNode(); 3968 3969 node.properties = []; 3970 this.next(); 3971 3972 var firstRestLocation = null; 3973 3974 while (!this.eat(types.braceR)) { 3975 if (first) { 3976 first = false; 3977 } else { 3978 this.expect(types.comma); 3979 if (this.eat(types.braceR)) break; 3980 } 3981 3982 while (this.match(types.at)) { 3983 decorators.push(this.parseDecorator()); 3984 } 3985 3986 var prop = this.startNode(), 3987 isGenerator = false, 3988 isAsync = false, 3989 startPos = void 0, 3990 startLoc = void 0; 3991 if (decorators.length) { 3992 prop.decorators = decorators; 3993 decorators = []; 3994 } 3995 3996 if (this.hasPlugin("objectRestSpread") && this.match(types.ellipsis)) { 3997 prop = this.parseSpread(isPattern ? { start: 0 } : undefined); 3998 prop.type = isPattern ? "RestProperty" : "SpreadProperty"; 3999 if (isPattern) this.toAssignable(prop.argument, true, "object pattern"); 4000 node.properties.push(prop); 4001 if (isPattern) { 4002 var position = this.state.start; 4003 if (firstRestLocation !== null) { 4004 this.unexpected(firstRestLocation, "Cannot have multiple rest elements when destructuring"); 4005 } else if (this.eat(types.braceR)) { 4006 break; 4007 } else if (this.match(types.comma) && this.lookahead().type === types.braceR) { 4008 // TODO: temporary rollback 4009 // this.unexpected(position, "A trailing comma is not permitted after the rest element"); 4010 continue; 4011 } else { 4012 firstRestLocation = position; 4013 continue; 4014 } 4015 } else { 4016 continue; 4017 } 4018 } 4019 4020 prop.method = false; 4021 prop.shorthand = false; 4022 4023 if (isPattern || refShorthandDefaultPos) { 4024 startPos = this.state.start; 4025 startLoc = this.state.startLoc; 4026 } 4027 4028 if (!isPattern) { 4029 isGenerator = this.eat(types.star); 4030 } 4031 4032 if (!isPattern && this.isContextual("async")) { 4033 if (isGenerator) this.unexpected(); 4034 4035 var asyncId = this.parseIdentifier(); 4036 if (this.match(types.colon) || this.match(types.parenL) || this.match(types.braceR) || this.match(types.eq) || this.match(types.comma)) { 4037 prop.key = asyncId; 4038 prop.computed = false; 4039 } else { 4040 isAsync = true; 4041 if (this.hasPlugin("asyncGenerators")) isGenerator = this.eat(types.star); 4042 this.parsePropertyName(prop); 4043 } 4044 } else { 4045 this.parsePropertyName(prop); 4046 } 4047 4048 this.parseObjPropValue(prop, startPos, startLoc, isGenerator, isAsync, isPattern, refShorthandDefaultPos); 4049 this.checkPropClash(prop, propHash); 4050 4051 if (prop.shorthand) { 4052 this.addExtra(prop, "shorthand", true); 4053 } 4054 4055 node.properties.push(prop); 4056 } 4057 4058 if (firstRestLocation !== null) { 4059 this.unexpected(firstRestLocation, "The rest element has to be the last element when destructuring"); 4060 } 4061 4062 if (decorators.length) { 4063 this.raise(this.state.start, "You have trailing decorators with no property"); 4064 } 4065 4066 return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression"); 4067}; 4068 4069pp$3.isGetterOrSetterMethod = function (prop, isPattern) { 4070 return !isPattern && !prop.computed && prop.key.type === "Identifier" && (prop.key.name === "get" || prop.key.name === "set") && (this.match(types.string) || // get "string"() {} 4071 this.match(types.num) || // get 1() {} 4072 this.match(types.bracketL) || // get ["string"]() {} 4073 this.match(types.name) || // get foo() {} 4074 this.state.type.keyword // get debugger() {} 4075 ); 4076}; 4077 4078// get methods aren't allowed to have any parameters 4079// set methods must have exactly 1 parameter 4080pp$3.checkGetterSetterParamCount = function (method) { 4081 var paramCount = method.kind === "get" ? 0 : 1; 4082 if (method.params.length !== paramCount) { 4083 var start = method.start; 4084 if (method.kind === "get") { 4085 this.raise(start, "getter should have no params"); 4086 } else { 4087 this.raise(start, "setter should have exactly one param"); 4088 } 4089 } 4090}; 4091 4092pp$3.parseObjectMethod = function (prop, isGenerator, isAsync, isPattern) { 4093 if (isAsync || isGenerator || this.match(types.parenL)) { 4094 if (isPattern) this.unexpected(); 4095 prop.kind = "method"; 4096 prop.method = true; 4097 this.parseMethod(prop, isGenerator, isAsync); 4098 4099 return this.finishNode(prop, "ObjectMethod"); 4100 } 4101 4102 if (this.isGetterOrSetterMethod(prop, isPattern)) { 4103 if (isGenerator || isAsync) this.unexpected(); 4104 prop.kind = prop.key.name; 4105 this.parsePropertyName(prop); 4106 this.parseMethod(prop); 4107 this.checkGetterSetterParamCount(prop); 4108 4109 return this.finishNode(prop, "ObjectMethod"); 4110 } 4111}; 4112 4113pp$3.parseObjectProperty = function (prop, startPos, startLoc, isPattern, refShorthandDefaultPos) { 4114 if (this.eat(types.colon)) { 4115 prop.value = isPattern ? this.parseMaybeDefault(this.state.start, this.state.startLoc) : this.parseMaybeAssign(false, refShorthandDefaultPos); 4116 4117 return this.finishNode(prop, "ObjectProperty"); 4118 } 4119 4120 if (!prop.computed && prop.key.type === "Identifier") { 4121 this.checkReservedWord(prop.key.name, prop.key.start, true, true); 4122 4123 if (isPattern) { 4124 prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key.__clone()); 4125 } else if (this.match(types.eq) && refShorthandDefaultPos) { 4126 if (!refShorthandDefaultPos.start) { 4127 refShorthandDefaultPos.start = this.state.start; 4128 } 4129 prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key.__clone()); 4130 } else { 4131 prop.value = prop.key.__clone(); 4132 } 4133 prop.shorthand = true; 4134 4135 return this.finishNode(prop, "ObjectProperty"); 4136 } 4137}; 4138 4139pp$3.parseObjPropValue = function (prop, startPos, startLoc, isGenerator, isAsync, isPattern, refShorthandDefaultPos) { 4140 var node = this.parseObjectMethod(prop, isGenerator, isAsync, isPattern) || this.parseObjectProperty(prop, startPos, startLoc, isPattern, refShorthandDefaultPos); 4141 4142 if (!node) this.unexpected(); 4143 4144 return node; 4145}; 4146 4147pp$3.parsePropertyName = function (prop) { 4148 if (this.eat(types.bracketL)) { 4149 prop.computed = true; 4150 prop.key = this.parseMaybeAssign(); 4151 this.expect(types.bracketR); 4152 } else { 4153 prop.computed = false; 4154 var oldInPropertyName = this.state.inPropertyName; 4155 this.state.inPropertyName = true; 4156 prop.key = this.match(types.num) || this.match(types.string) ? this.parseExprAtom() : this.parseIdentifier(true); 4157 this.state.inPropertyName = oldInPropertyName; 4158 } 4159 return prop.key; 4160}; 4161 4162// Initialize empty function node. 4163 4164pp$3.initFunction = function (node, isAsync) { 4165 node.id = null; 4166 node.generator = false; 4167 node.expression = false; 4168 node.async = !!isAsync; 4169}; 4170 4171// Parse object or class method. 4172 4173pp$3.parseMethod = function (node, isGenerator, isAsync) { 4174 var oldInMethod = this.state.inMethod; 4175 this.state.inMethod = node.kind || true; 4176 this.initFunction(node, isAsync); 4177 this.expect(types.parenL); 4178 node.params = this.parseBindingList(types.parenR); 4179 node.generator = !!isGenerator; 4180 this.parseFunctionBody(node); 4181 this.state.inMethod = oldInMethod; 4182 return node; 4183}; 4184 4185// Parse arrow function expression with given parameters. 4186 4187pp$3.parseArrowExpression = function (node, params, isAsync) { 4188 this.initFunction(node, isAsync); 4189 node.params = this.toAssignableList(params, true, "arrow function parameters"); 4190 this.parseFunctionBody(node, true); 4191 return this.finishNode(node, "ArrowFunctionExpression"); 4192}; 4193 4194pp$3.isStrictBody = function (node, isExpression) { 4195 if (!isExpression && node.body.directives.length) { 4196 for (var _iterator2 = node.body.directives, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) { 4197 var _ref2; 4198 4199 if (_isArray2) { 4200 if (_i2 >= _iterator2.length) break; 4201 _ref2 = _iterator2[_i2++]; 4202 } else { 4203 _i2 = _iterator2.next(); 4204 if (_i2.done) break; 4205 _ref2 = _i2.value; 4206 } 4207 4208 var directive = _ref2; 4209 4210 if (directive.value.value === "use strict") { 4211 return true; 4212 } 4213 } 4214 } 4215 4216 return false; 4217}; 4218 4219// Parse function body and check parameters. 4220pp$3.parseFunctionBody = function (node, allowExpression) { 4221 var isExpression = allowExpression && !this.match(types.braceL); 4222 4223 var oldInAsync = this.state.inAsync; 4224 this.state.inAsync = node.async; 4225 if (isExpression) { 4226 node.body = this.parseMaybeAssign(); 4227 node.expression = true; 4228 } else { 4229 // Start a new scope with regard to labels and the `inFunction` 4230 // flag (restore them to their old value afterwards). 4231 var oldInFunc = this.state.inFunction; 4232 var oldInGen = this.state.inGenerator; 4233 var oldLabels = this.state.labels; 4234 this.state.inFunction = true;this.state.inGenerator = node.generator;this.state.labels = []; 4235 node.body = this.parseBlock(true); 4236 node.expression = false; 4237 this.state.inFunction = oldInFunc;this.state.inGenerator = oldInGen;this.state.labels = oldLabels; 4238 } 4239 this.state.inAsync = oldInAsync; 4240 4241 // If this is a strict mode function, verify that argument names 4242 // are not repeated, and it does not try to bind the words `eval` 4243 // or `arguments`. 4244 var isStrict = this.isStrictBody(node, isExpression); 4245 // Also check when allowExpression === true for arrow functions 4246 var checkLVal = this.state.strict || allowExpression || isStrict; 4247 4248 if (isStrict && node.id && node.id.type === "Identifier" && node.id.name === "yield") { 4249 this.raise(node.id.start, "Binding yield in strict mode"); 4250 } 4251 4252 if (checkLVal) { 4253 var nameHash = Object.create(null); 4254 var oldStrict = this.state.strict; 4255 if (isStrict) this.state.strict = true; 4256 if (node.id) { 4257 this.checkLVal(node.id, true, undefined, "function name"); 4258 } 4259 for (var _iterator3 = node.params, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) { 4260 var _ref3; 4261 4262 if (_isArray3) { 4263 if (_i3 >= _iterator3.length) break; 4264 _ref3 = _iterator3[_i3++]; 4265 } else { 4266 _i3 = _iterator3.next(); 4267 if (_i3.done) break; 4268 _ref3 = _i3.value; 4269 } 4270 4271 var param = _ref3; 4272 4273 if (isStrict && param.type !== "Identifier") { 4274 this.raise(param.start, "Non-simple parameter in strict mode"); 4275 } 4276 this.checkLVal(param, true, nameHash, "function parameter list"); 4277 } 4278 this.state.strict = oldStrict; 4279 } 4280}; 4281 4282// Parses a comma-separated list of expressions, and returns them as 4283// an array. `close` is the token type that ends the list, and 4284// `allowEmpty` can be turned on to allow subsequent commas with 4285// nothing in between them to be parsed as `null` (which is needed 4286// for array literals). 4287 4288pp$3.parseExprList = function (close, allowEmpty, refShorthandDefaultPos) { 4289 var elts = []; 4290 var first = true; 4291 4292 while (!this.eat(close)) { 4293 if (first) { 4294 first = false; 4295 } else { 4296 this.expect(types.comma); 4297 if (this.eat(close)) break; 4298 } 4299 4300 elts.push(this.parseExprListItem(allowEmpty, refShorthandDefaultPos)); 4301 } 4302 return elts; 4303}; 4304 4305pp$3.parseExprListItem = function (allowEmpty, refShorthandDefaultPos, refNeedsArrowPos) { 4306 var elt = void 0; 4307 if (allowEmpty && this.match(types.comma)) { 4308 elt = null; 4309 } else if (this.match(types.ellipsis)) { 4310 elt = this.parseSpread(refShorthandDefaultPos); 4311 } else { 4312 elt = this.parseMaybeAssign(false, refShorthandDefaultPos, this.parseParenItem, refNeedsArrowPos); 4313 } 4314 return elt; 4315}; 4316 4317// Parse the next token as an identifier. If `liberal` is true (used 4318// when parsing properties), it will also convert keywords into 4319// identifiers. 4320 4321pp$3.parseIdentifier = function (liberal) { 4322 var node = this.startNode(); 4323 if (!liberal) { 4324 this.checkReservedWord(this.state.value, this.state.start, !!this.state.type.keyword, false); 4325 } 4326 4327 if (this.match(types.name)) { 4328 node.name = this.state.value; 4329 } else if (this.state.type.keyword) { 4330 node.name = this.state.type.keyword; 4331 } else { 4332 this.unexpected(); 4333 } 4334 4335 if (!liberal && node.name === "await" && this.state.inAsync) { 4336 this.raise(node.start, "invalid use of await inside of an async function"); 4337 } 4338 4339 node.loc.identifierName = node.name; 4340 4341 this.next(); 4342 return this.finishNode(node, "Identifier"); 4343}; 4344 4345pp$3.checkReservedWord = function (word, startLoc, checkKeywords, isBinding) { 4346 if (this.isReservedWord(word) || checkKeywords && this.isKeyword(word)) { 4347 this.raise(startLoc, word + " is a reserved word"); 4348 } 4349 4350 if (this.state.strict && (reservedWords.strict(word) || isBinding && reservedWords.strictBind(word))) { 4351 this.raise(startLoc, word + " is a reserved word in strict mode"); 4352 } 4353}; 4354 4355// Parses await expression inside async function. 4356 4357pp$3.parseAwait = function (node) { 4358 // istanbul ignore next: this condition is checked at the call site so won't be hit here 4359 if (!this.state.inAsync) { 4360 this.unexpected(); 4361 } 4362 if (this.match(types.star)) { 4363 this.raise(node.start, "await* has been removed from the async functions proposal. Use Promise.all() instead."); 4364 } 4365 node.argument = this.parseMaybeUnary(); 4366 return this.finishNode(node, "AwaitExpression"); 4367}; 4368 4369// Parses yield expression inside generator. 4370 4371pp$3.parseYield = function () { 4372 var node = this.startNode(); 4373 this.next(); 4374 if (this.match(types.semi) || this.canInsertSemicolon() || !this.match(types.star) && !this.state.type.startsExpr) { 4375 node.delegate = false; 4376 node.argument = null; 4377 } else { 4378 node.delegate = this.eat(types.star); 4379 node.argument = this.parseMaybeAssign(); 4380 } 4381 return this.finishNode(node, "YieldExpression"); 4382}; 4383 4384// Start an AST node, attaching a start offset. 4385 4386var pp$4 = Parser.prototype; 4387var commentKeys = ["leadingComments", "trailingComments", "innerComments"]; 4388 4389var Node = function () { 4390 function Node(pos, loc, filename) { 4391 classCallCheck(this, Node); 4392 4393 this.type = ""; 4394 this.start = pos; 4395 this.end = 0; 4396 this.loc = new SourceLocation(loc); 4397 if (filename) this.loc.filename = filename; 4398 } 4399 4400 Node.prototype.__clone = function __clone() { 4401 var node2 = new Node(); 4402 for (var key in this) { 4403 // Do not clone comments that are already attached to the node 4404 if (commentKeys.indexOf(key) < 0) { 4405 node2[key] = this[key]; 4406 } 4407 } 4408 4409 return node2; 4410 }; 4411 4412 return Node; 4413}(); 4414 4415pp$4.startNode = function () { 4416 return new Node(this.state.start, this.state.startLoc, this.filename); 4417}; 4418 4419pp$4.startNodeAt = function (pos, loc) { 4420 return new Node(pos, loc, this.filename); 4421}; 4422 4423function finishNodeAt(node, type, pos, loc) { 4424 node.type = type; 4425 node.end = pos; 4426 node.loc.end = loc; 4427 this.processComment(node); 4428 return node; 4429} 4430 4431// Finish an AST node, adding `type` and `end` properties. 4432 4433pp$4.finishNode = function (node, type) { 4434 return finishNodeAt.call(this, node, type, this.state.lastTokEnd, this.state.lastTokEndLoc); 4435}; 4436 4437// Finish node at given position 4438 4439pp$4.finishNodeAt = function (node, type, pos, loc) { 4440 return finishNodeAt.call(this, node, type, pos, loc); 4441}; 4442 4443var pp$5 = Parser.prototype; 4444 4445// This function is used to raise exceptions on parse errors. It 4446// takes an offset integer (into the current `input`) to indicate 4447// the location of the error, attaches the position to the end 4448// of the error message, and then raises a `SyntaxError` with that 4449// message. 4450 4451pp$5.raise = function (pos, message) { 4452 var loc = getLineInfo(this.input, pos); 4453 message += " (" + loc.line + ":" + loc.column + ")"; 4454 var err = new SyntaxError(message); 4455 err.pos = pos; 4456 err.loc = loc; 4457 throw err; 4458}; 4459 4460/* eslint max-len: 0 */ 4461 4462/** 4463 * Based on the comment attachment algorithm used in espree and estraverse. 4464 * 4465 * Redistribution and use in source and binary forms, with or without 4466 * modification, are permitted provided that the following conditions are met: 4467 * 4468 * * Redistributions of source code must retain the above copyright 4469 * notice, this list of conditions and the following disclaimer. 4470 * * Redistributions in binary form must reproduce the above copyright 4471 * notice, this list of conditions and the following disclaimer in the 4472 * documentation and/or other materials provided with the distribution. 4473 * 4474 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 4475 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4476 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4477 * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY 4478 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 4479 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 4480 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 4481 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 4482 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 4483 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 4484 */ 4485 4486function last(stack) { 4487 return stack[stack.length - 1]; 4488} 4489 4490var pp$6 = Parser.prototype; 4491 4492pp$6.addComment = function (comment) { 4493 if (this.filename) comment.loc.filename = this.filename; 4494 this.state.trailingComments.push(comment); 4495 this.state.leadingComments.push(comment); 4496}; 4497 4498pp$6.processComment = function (node) { 4499 if (node.type === "Program" && node.body.length > 0) return; 4500 4501 var stack = this.state.commentStack; 4502 4503 var firstChild = void 0, 4504 lastChild = void 0, 4505 trailingComments = void 0, 4506 i = void 0, 4507 j = void 0; 4508 4509 if (this.state.trailingComments.length > 0) { 4510 // If the first comment in trailingComments comes after the 4511 // current node, then we're good - all comments in the array will 4512 // come after the node and so it's safe to add them as official 4513 // trailingComments. 4514 if (this.state.trailingComments[0].start >= node.end) { 4515 trailingComments = this.state.trailingComments; 4516 this.state.trailingComments = []; 4517 } else { 4518 // Otherwise, if the first comment doesn't come after the 4519 // current node, that means we have a mix of leading and trailing 4520 // comments in the array and that leadingComments contains the 4521 // same items as trailingComments. Reset trailingComments to 4522 // zero items and we'll handle this by evaluating leadingComments 4523 // later. 4524 this.state.trailingComments.length = 0; 4525 } 4526 } else { 4527 var lastInStack = last(stack); 4528 if (stack.length > 0 && lastInStack.trailingComments && lastInStack.trailingComments[0].start >= node.end) { 4529 trailingComments = lastInStack.trailingComments; 4530 lastInStack.trailingComments = null; 4531 } 4532 } 4533 4534 // Eating the stack. 4535 if (stack.length > 0 && last(stack).start >= node.start) { 4536 firstChild = stack.pop(); 4537 } 4538 4539 while (stack.length > 0 && last(stack).start >= node.start) { 4540 lastChild = stack.pop(); 4541 } 4542 4543 if (!lastChild && firstChild) lastChild = firstChild; 4544 4545 // Attach comments that follow a trailing comma on the last 4546 // property in an object literal or a trailing comma in function arguments 4547 // as trailing comments 4548 if (firstChild && this.state.leadingComments.length > 0) { 4549 var lastComment = last(this.state.leadingComments); 4550 4551 if (firstChild.type === "ObjectProperty") { 4552 if (lastComment.start >= node.start) { 4553 if (this.state.commentPreviousNode) { 4554 for (j = 0; j < this.state.leadingComments.length; j++) { 4555 if (this.state.leadingComments[j].end < this.state.commentPreviousNode.end) { 4556 this.state.leadingComments.splice(j, 1); 4557 j--; 4558 } 4559 } 4560 4561 if (this.state.leadingComments.length > 0) { 4562 firstChild.trailingComments = this.state.leadingComments; 4563 this.state.leadingComments = []; 4564 } 4565 } 4566 } 4567 } else if (node.type === "CallExpression" && node.arguments && node.arguments.length) { 4568 var lastArg = last(node.arguments); 4569 4570 if (lastArg && lastComment.start >= lastArg.start && lastComment.end <= node.end) { 4571 if (this.state.commentPreviousNode) { 4572 if (this.state.leadingComments.length > 0) { 4573 lastArg.trailingComments = this.state.leadingComments; 4574 this.state.leadingComments = []; 4575 } 4576 } 4577 } 4578 } 4579 } 4580 4581 if (lastChild) { 4582 if (lastChild.leadingComments) { 4583 if (lastChild !== node && last(lastChild.leadingComments).end <= node.start) { 4584 node.leadingComments = lastChild.leadingComments; 4585 lastChild.leadingComments = null; 4586 } else { 4587 // A leading comment for an anonymous class had been stolen by its first ClassMethod, 4588 // so this takes back the leading comment. 4589 // See also: https://github.com/eslint/espree/issues/158 4590 for (i = lastChild.leadingComments.length - 2; i >= 0; --i) { 4591 if (lastChild.leadingComments[i].end <= node.start) { 4592 node.leadingComments = lastChild.leadingComments.splice(0, i + 1); 4593 break; 4594 } 4595 } 4596 } 4597 } 4598 } else if (this.state.leadingComments.length > 0) { 4599 if (last(this.state.leadingComments).end <= node.start) { 4600 if (this.state.commentPreviousNode) { 4601 for (j = 0; j < this.state.leadingComments.length; j++) { 4602 if (this.state.leadingComments[j].end < this.state.commentPreviousNode.end) { 4603 this.state.leadingComments.splice(j, 1); 4604 j--; 4605 } 4606 } 4607 } 4608 if (this.state.leadingComments.length > 0) { 4609 node.leadingComments = this.state.leadingComments; 4610 this.state.leadingComments = []; 4611 } 4612 } else { 4613 // https://github.com/eslint/espree/issues/2 4614 // 4615 // In special cases, such as return (without a value) and 4616 // debugger, all comments will end up as leadingComments and 4617 // will otherwise be eliminated. This step runs when the 4618 // commentStack is empty and there are comments left 4619 // in leadingComments. 4620 // 4621 // This loop figures out the stopping point between the actual 4622 // leading and trailing comments by finding the location of the 4623 // first comment that comes after the given node. 4624 for (i = 0; i < this.state.leadingComments.length; i++) { 4625 if (this.state.leadingComments[i].end > node.start) { 4626 break; 4627 } 4628 } 4629 4630 // Split the array based on the location of the first comment 4631 // that comes after the node. Keep in mind that this could 4632 // result in an empty array, and if so, the array must be 4633 // deleted. 4634 node.leadingComments = this.state.leadingComments.slice(0, i); 4635 if (node.leadingComments.length === 0) { 4636 node.leadingComments = null; 4637 } 4638 4639 // Similarly, trailing comments are attached later. The variable 4640 // must be reset to null if there are no trailing comments. 4641 trailingComments = this.state.leadingComments.slice(i); 4642 if (trailingComments.length === 0) { 4643 trailingComments = null; 4644 } 4645 } 4646 } 4647 4648 this.state.commentPreviousNode = node; 4649 4650 if (trailingComments) { 4651 if (trailingComments.length && trailingComments[0].start >= node.start && last(trailingComments).end <= node.end) { 4652 node.innerComments = trailingComments; 4653 } else { 4654 node.trailingComments = trailingComments; 4655 } 4656 } 4657 4658 stack.push(node); 4659}; 4660 4661var pp$7 = Parser.prototype; 4662 4663pp$7.estreeParseRegExpLiteral = function (_ref) { 4664 var pattern = _ref.pattern, 4665 flags = _ref.flags; 4666 4667 var regex = null; 4668 try { 4669 regex = new RegExp(pattern, flags); 4670 } catch (e) { 4671 // In environments that don't support these flags value will 4672 // be null as the regex can't be represented natively. 4673 } 4674 var node = this.estreeParseLiteral(regex); 4675 node.regex = { pattern: pattern, flags: flags }; 4676 4677 return node; 4678}; 4679 4680pp$7.estreeParseLiteral = function (value) { 4681 return this.parseLiteral(value, "Literal"); 4682}; 4683 4684pp$7.directiveToStmt = function (directive) { 4685 var directiveLiteral = directive.value; 4686 4687 var stmt = this.startNodeAt(directive.start, directive.loc.start); 4688 var expression = this.startNodeAt(directiveLiteral.start, directiveLiteral.loc.start); 4689 4690 expression.value = directiveLiteral.value; 4691 expression.raw = directiveLiteral.extra.raw; 4692 4693 stmt.expression = this.finishNodeAt(expression, "Literal", directiveLiteral.end, directiveLiteral.loc.end); 4694 stmt.directive = directiveLiteral.extra.raw.slice(1, -1); 4695 4696 return this.finishNodeAt(stmt, "ExpressionStatement", directive.end, directive.loc.end); 4697}; 4698 4699function isSimpleProperty(node) { 4700 return node && node.type === "Property" && node.kind === "init" && node.method === false; 4701} 4702 4703var estreePlugin = function (instance) { 4704 instance.extend("checkDeclaration", function (inner) { 4705 return function (node) { 4706 if (isSimpleProperty(node)) { 4707 this.checkDeclaration(node.value); 4708 } else { 4709 inner.call(this, node); 4710 } 4711 }; 4712 }); 4713 4714 instance.extend("checkGetterSetterParamCount", function () { 4715 return function (prop) { 4716 var paramCount = prop.kind === "get" ? 0 : 1; 4717 if (prop.value.params.length !== paramCount) { 4718 var start = prop.start; 4719 if (prop.kind === "get") { 4720 this.raise(start, "getter should have no params"); 4721 } else { 4722 this.raise(start, "setter should have exactly one param"); 4723 } 4724 } 4725 }; 4726 }); 4727 4728 instance.extend("checkLVal", function (inner) { 4729 return function (expr, isBinding, checkClashes) { 4730 var _this = this; 4731 4732 switch (expr.type) { 4733 case "ObjectPattern": 4734 expr.properties.forEach(function (prop) { 4735 _this.checkLVal(prop.type === "Property" ? prop.value : prop, isBinding, checkClashes, "object destructuring pattern"); 4736 }); 4737 break; 4738 default: 4739 for (var _len = arguments.length, args = Array(_len > 3 ? _len - 3 : 0), _key = 3; _key < _len; _key++) { 4740 args[_key - 3] = arguments[_key]; 4741 } 4742 4743 inner.call.apply(inner, [this, expr, isBinding, checkClashes].concat(args)); 4744 } 4745 }; 4746 }); 4747 4748 instance.extend("checkPropClash", function () { 4749 return function (prop, propHash) { 4750 if (prop.computed || !isSimpleProperty(prop)) return; 4751 4752 var key = prop.key; 4753 // It is either an Identifier or a String/NumericLiteral 4754 var name = key.type === "Identifier" ? key.name : String(key.value); 4755 4756 if (name === "__proto__") { 4757 if (propHash.proto) this.raise(key.start, "Redefinition of __proto__ property"); 4758 propHash.proto = true; 4759 } 4760 }; 4761 }); 4762 4763 instance.extend("isStrictBody", function () { 4764 return function (node, isExpression) { 4765 if (!isExpression && node.body.body.length > 0) { 4766 for (var _iterator = node.body.body, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { 4767 var _ref2; 4768 4769 if (_isArray) { 4770 if (_i >= _iterator.length) break; 4771 _ref2 = _iterator[_i++]; 4772 } else { 4773 _i = _iterator.next(); 4774 if (_i.done) break; 4775 _ref2 = _i.value; 4776 } 4777 4778 var directive = _ref2; 4779 4780 if (directive.type === "ExpressionStatement" && directive.expression.type === "Literal") { 4781 if (directive.expression.value === "use strict") return true; 4782 } else { 4783 // Break for the first non literal expression 4784 break; 4785 } 4786 } 4787 } 4788 4789 return false; 4790 }; 4791 }); 4792 4793 instance.extend("isValidDirective", function () { 4794 return function (stmt) { 4795 return stmt.type === "ExpressionStatement" && stmt.expression.type === "Literal" && typeof stmt.expression.value === "string" && (!stmt.expression.extra || !stmt.expression.extra.parenthesized); 4796 }; 4797 }); 4798 4799 instance.extend("stmtToDirective", function (inner) { 4800 return function (stmt) { 4801 var directive = inner.call(this, stmt); 4802 var value = stmt.expression.value; 4803 4804 // Reset value to the actual value as in estree mode we want 4805 // the stmt to have the real value and not the raw value 4806 directive.value.value = value; 4807 4808 return directive; 4809 }; 4810 }); 4811 4812 instance.extend("parseBlockBody", function (inner) { 4813 return function (node) { 4814 var _this2 = this; 4815 4816 for (var _len2 = arguments.length, args = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { 4817 args[_key2 - 1] = arguments[_key2]; 4818 } 4819 4820 inner.call.apply(inner, [this, node].concat(args)); 4821 4822 node.directives.reverse().forEach(function (directive) { 4823 node.body.unshift(_this2.directiveToStmt(directive)); 4824 }); 4825 delete node.directives; 4826 }; 4827 }); 4828 4829 instance.extend("parseClassMethod", function () { 4830 return function (classBody, method, isGenerator, isAsync) { 4831 this.parseMethod(method, isGenerator, isAsync); 4832 if (method.typeParameters) { 4833 method.value.typeParameters = method.typeParameters; 4834 delete method.typeParameters; 4835 } 4836 classBody.body.push(this.finishNode(method, "MethodDefinition")); 4837 }; 4838 }); 4839 4840 instance.extend("parseExprAtom", function (inner) { 4841 return function () { 4842 switch (this.state.type) { 4843 case types.regexp: 4844 return this.estreeParseRegExpLiteral(this.state.value); 4845 4846 case types.num: 4847 case types.string: 4848 return this.estreeParseLiteral(this.state.value); 4849 4850 case types._null: 4851 return this.estreeParseLiteral(null); 4852 4853 case types._true: 4854 return this.estreeParseLiteral(true); 4855 4856 case types._false: 4857 return this.estreeParseLiteral(false); 4858 4859 default: 4860 for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { 4861 args[_key3] = arguments[_key3]; 4862 } 4863 4864 return inner.call.apply(inner, [this].concat(args)); 4865 } 4866 }; 4867 }); 4868 4869 instance.extend("parseLiteral", function (inner) { 4870 return function () { 4871 for (var _len4 = arguments.length, args = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { 4872 args[_key4] = arguments[_key4]; 4873 } 4874 4875 var node = inner.call.apply(inner, [this].concat(args)); 4876 node.raw = node.extra.raw; 4877 delete node.extra; 4878 4879 return node; 4880 }; 4881 }); 4882 4883 instance.extend("parseMethod", function (inner) { 4884 return function (node) { 4885 var funcNode = this.startNode(); 4886 funcNode.kind = node.kind; // provide kind, so inner method correctly sets state 4887 4888 for (var _len5 = arguments.length, args = Array(_len5 > 1 ? _len5 - 1 : 0), _key5 = 1; _key5 < _len5; _key5++) { 4889 args[_key5 - 1] = arguments[_key5]; 4890 } 4891 4892 funcNode = inner.call.apply(inner, [this, funcNode].concat(args)); 4893 delete funcNode.kind; 4894 node.value = this.finishNode(funcNode, "FunctionExpression"); 4895 4896 return node; 4897 }; 4898 }); 4899 4900 instance.extend("parseObjectMethod", function (inner) { 4901 return function () { 4902 for (var _len6 = arguments.length, args = Array(_len6), _key6 = 0; _key6 < _len6; _key6++) { 4903 args[_key6] = arguments[_key6]; 4904 } 4905 4906 var node = inner.call.apply(inner, [this].concat(args)); 4907 4908 if (node) { 4909 if (node.kind === "method") node.kind = "init"; 4910 node.type = "Property"; 4911 } 4912 4913 return node; 4914 }; 4915 }); 4916 4917 instance.extend("parseObjectProperty", function (inner) { 4918 return function () { 4919 for (var _len7 = arguments.length, args = Array(_len7), _key7 = 0; _key7 < _len7; _key7++) { 4920 args[_key7] = arguments[_key7]; 4921 } 4922 4923 var node = inner.call.apply(inner, [this].concat(args)); 4924 4925 if (node) { 4926 node.kind = "init"; 4927 node.type = "Property"; 4928 } 4929 4930 return node; 4931 }; 4932 }); 4933 4934 instance.extend("toAssignable", function (inner) { 4935 return function (node, isBinding) { 4936 for (var _len8 = arguments.length, args = Array(_len8 > 2 ? _len8 - 2 : 0), _key8 = 2; _key8 < _len8; _key8++) { 4937 args[_key8 - 2] = arguments[_key8]; 4938 } 4939 4940 if (isSimpleProperty(node)) { 4941 this.toAssignable.apply(this, [node.value, isBinding].concat(args)); 4942 4943 return node; 4944 } else if (node.type === "ObjectExpression") { 4945 node.type = "ObjectPattern"; 4946 for (var _iterator2 = node.properties, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) { 4947 var _ref3; 4948 4949 if (_isArray2) { 4950 if (_i2 >= _iterator2.length) break; 4951 _ref3 = _iterator2[_i2++]; 4952 } else { 4953 _i2 = _iterator2.next(); 4954 if (_i2.done) break; 4955 _ref3 = _i2.value; 4956 } 4957 4958 var prop = _ref3; 4959 4960 if (prop.kind === "get" || prop.kind === "set") { 4961 this.raise(prop.key.start, "Object pattern can't contain getter or setter"); 4962 } else if (prop.method) { 4963 this.raise(prop.key.start, "Object pattern can't contain methods"); 4964 } else { 4965 this.toAssignable(prop, isBinding, "object destructuring pattern"); 4966 } 4967 } 4968 4969 return node; 4970 } 4971 4972 return inner.call.apply(inner, [this, node, isBinding].concat(args)); 4973 }; 4974 }); 4975}; 4976 4977/* eslint max-len: 0 */ 4978 4979var primitiveTypes = ["any", "mixed", "empty", "bool", "boolean", "number", "string", "void", "null"]; 4980 4981var pp$8 = Parser.prototype; 4982 4983pp$8.flowParseTypeInitialiser = function (tok) { 4984 var oldInType = this.state.inType; 4985 this.state.inType = true; 4986 this.expect(tok || types.colon); 4987 4988 var type = this.flowParseType(); 4989 this.state.inType = oldInType; 4990 return type; 4991}; 4992 4993pp$8.flowParsePredicate = function () { 4994 var node = this.startNode(); 4995 var moduloLoc = this.state.startLoc; 4996 var moduloPos = this.state.start; 4997 this.expect(types.modulo); 4998 var checksLoc = this.state.startLoc; 4999 this.expectContextual("checks"); 5000 // Force '%' and 'checks' to be adjacent 5001 if (moduloLoc.line !== checksLoc.line || moduloLoc.column !== checksLoc.column - 1) { 5002 this.raise(moduloPos, "Spaces between ´%´ and ´checks´ are not allowed here."); 5003 } 5004 if (this.eat(types.parenL)) { 5005 node.expression = this.parseExpression(); 5006 this.expect(types.parenR); 5007 return this.finishNode(node, "DeclaredPredicate"); 5008 } else { 5009 return this.finishNode(node, "InferredPredicate"); 5010 } 5011}; 5012 5013pp$8.flowParseTypeAndPredicateInitialiser = function () { 5014 var oldInType = this.state.inType; 5015 this.state.inType = true; 5016 this.expect(types.colon); 5017 var type = null; 5018 var predicate = null; 5019 if (this.match(types.modulo)) { 5020 this.state.inType = oldInType; 5021 predicate = this.flowParsePredicate(); 5022 } else { 5023 type = this.flowParseType(); 5024 this.state.inType = oldInType; 5025 if (this.match(types.modulo)) { 5026 predicate = this.flowParsePredicate(); 5027 } 5028 } 5029 return [type, predicate]; 5030}; 5031 5032pp$8.flowParseDeclareClass = function (node) { 5033 this.next(); 5034 this.flowParseInterfaceish(node, true); 5035 return this.finishNode(node, "DeclareClass"); 5036}; 5037 5038pp$8.flowParseDeclareFunction = function (node) { 5039 this.next(); 5040 5041 var id = node.id = this.parseIdentifier(); 5042 5043 var typeNode = this.startNode(); 5044 var typeContainer = this.startNode(); 5045 5046 if (this.isRelational("<")) { 5047 typeNode.typeParameters = this.flowParseTypeParameterDeclaration(); 5048 } else { 5049 typeNode.typeParameters = null; 5050 } 5051 5052 this.expect(types.parenL); 5053 var tmp = this.flowParseFunctionTypeParams(); 5054 typeNode.params = tmp.params; 5055 typeNode.rest = tmp.rest; 5056 this.expect(types.parenR); 5057 var predicate = null; 5058 5059 var _flowParseTypeAndPred = this.flowParseTypeAndPredicateInitialiser(); 5060 5061 typeNode.returnType = _flowParseTypeAndPred[0]; 5062 predicate = _flowParseTypeAndPred[1]; 5063 5064 typeContainer.typeAnnotation = this.finishNode(typeNode, "FunctionTypeAnnotation"); 5065 typeContainer.predicate = predicate; 5066 id.typeAnnotation = this.finishNode(typeContainer, "TypeAnnotation"); 5067 5068 this.finishNode(id, id.type); 5069 5070 this.semicolon(); 5071 5072 return this.finishNode(node, "DeclareFunction"); 5073}; 5074 5075pp$8.flowParseDeclare = function (node) { 5076 if (this.match(types._class)) { 5077 return this.flowParseDeclareClass(node); 5078 } else if (this.match(types._function)) { 5079 return this.flowParseDeclareFunction(node); 5080 } else if (this.match(types._var)) { 5081 return this.flowParseDeclareVariable(node); 5082 } else if (this.isContextual("module")) { 5083 if (this.lookahead().type === types.dot) { 5084 return this.flowParseDeclareModuleExports(node); 5085 } else { 5086 return this.flowParseDeclareModule(node); 5087 } 5088 } else if (this.isContextual("type")) { 5089 return this.flowParseDeclareTypeAlias(node); 5090 } else if (this.isContextual("opaque")) { 5091 return this.flowParseDeclareOpaqueType(node); 5092 } else if (this.isContextual("interface")) { 5093 return this.flowParseDeclareInterface(node); 5094 } else if (this.match(types._export)) { 5095 return this.flowParseDeclareExportDeclaration(node); 5096 } else { 5097 this.unexpected(); 5098 } 5099}; 5100 5101pp$8.flowParseDeclareExportDeclaration = function (node) { 5102 this.expect(types._export); 5103 if (this.isContextual("opaque") // declare export opaque ... 5104 ) { 5105 node.declaration = this.flowParseDeclare(this.startNode()); 5106 node.default = false; 5107 5108 return this.finishNode(node, "DeclareExportDeclaration"); 5109 } 5110 5111 throw this.unexpected(); 5112}; 5113 5114pp$8.flowParseDeclareVariable = function (node) { 5115 this.next(); 5116 node.id = this.flowParseTypeAnnotatableIdentifier(); 5117 this.semicolon(); 5118 return this.finishNode(node, "DeclareVariable"); 5119}; 5120 5121pp$8.flowParseDeclareModule = function (node) { 5122 this.next(); 5123 5124 if (this.match(types.string)) { 5125 node.id = this.parseExprAtom(); 5126 } else { 5127 node.id = this.parseIdentifier(); 5128 } 5129 5130 var bodyNode = node.body = this.startNode(); 5131 var body = bodyNode.body = []; 5132 this.expect(types.braceL); 5133 while (!this.match(types.braceR)) { 5134 var _bodyNode = this.startNode(); 5135 5136 if (this.match(types._import)) { 5137 var lookahead = this.lookahead(); 5138 if (lookahead.value !== "type" && lookahead.value !== "typeof") { 5139 this.unexpected(null, "Imports within a `declare module` body must always be `import type` or `import typeof`"); 5140 } 5141 5142 this.parseImport(_bodyNode); 5143 } else { 5144 this.expectContextual("declare", "Only declares and type imports are allowed inside declare module"); 5145 5146 _bodyNode = this.flowParseDeclare(_bodyNode, true); 5147 } 5148 5149 body.push(_bodyNode); 5150 } 5151 this.expect(types.braceR); 5152 5153 this.finishNode(bodyNode, "BlockStatement"); 5154 return this.finishNode(node, "DeclareModule"); 5155}; 5156 5157pp$8.flowParseDeclareModuleExports = function (node) { 5158 this.expectContextual("module"); 5159 this.expect(types.dot); 5160 this.expectContextual("exports"); 5161 node.typeAnnotation = this.flowParseTypeAnnotation(); 5162 this.semicolon(); 5163 5164 return this.finishNode(node, "DeclareModuleExports"); 5165}; 5166 5167pp$8.flowParseDeclareTypeAlias = function (node) { 5168 this.next(); 5169 this.flowParseTypeAlias(node); 5170 return this.finishNode(node, "DeclareTypeAlias"); 5171}; 5172 5173pp$8.flowParseDeclareOpaqueType = function (node) { 5174 this.next(); 5175 this.flowParseOpaqueType(node, true); 5176 return this.finishNode(node, "DeclareOpaqueType"); 5177}; 5178 5179pp$8.flowParseDeclareInterface = function (node) { 5180 this.next(); 5181 this.flowParseInterfaceish(node); 5182 return this.finishNode(node, "DeclareInterface"); 5183}; 5184 5185// Interfaces 5186 5187pp$8.flowParseInterfaceish = function (node) { 5188 node.id = this.parseIdentifier(); 5189 5190 if (this.isRelational("<")) { 5191 node.typeParameters = this.flowParseTypeParameterDeclaration(); 5192 } else { 5193 node.typeParameters = null; 5194 } 5195 5196 node.extends = []; 5197 node.mixins = []; 5198 5199 if (this.eat(types._extends)) { 5200 do { 5201 node.extends.push(this.flowParseInterfaceExtends()); 5202 } while (this.eat(types.comma)); 5203 } 5204 5205 if (this.isContextual("mixins")) { 5206 this.next(); 5207 do { 5208 node.mixins.push(this.flowParseInterfaceExtends()); 5209 } while (this.eat(types.comma)); 5210 } 5211 5212 node.body = this.flowParseObjectType(true, false, false); 5213}; 5214 5215pp$8.flowParseInterfaceExtends = function () { 5216 var node = this.startNode(); 5217 5218 node.id = this.flowParseQualifiedTypeIdentifier(); 5219 if (this.isRelational("<")) { 5220 node.typeParameters = this.flowParseTypeParameterInstantiation(); 5221 } else { 5222 node.typeParameters = null; 5223 } 5224 5225 return this.finishNode(node, "InterfaceExtends"); 5226}; 5227 5228pp$8.flowParseInterface = function (node) { 5229 this.flowParseInterfaceish(node, false); 5230 return this.finishNode(node, "InterfaceDeclaration"); 5231}; 5232 5233pp$8.flowParseRestrictedIdentifier = function (liberal) { 5234 if (primitiveTypes.indexOf(this.state.value) > -1) { 5235 this.raise(this.state.start, "Cannot overwrite primitive type " + this.state.value); 5236 } 5237 5238 return this.parseIdentifier(liberal); 5239}; 5240 5241// Type aliases 5242 5243pp$8.flowParseTypeAlias = function (node) { 5244 node.id = this.flowParseRestrictedIdentifier(); 5245 5246 if (this.isRelational("<")) { 5247 node.typeParameters = this.flowParseTypeParameterDeclaration(); 5248 } else { 5249 node.typeParameters = null; 5250 } 5251 5252 node.right = this.flowParseTypeInitialiser(types.eq); 5253 this.semicolon(); 5254 5255 return this.finishNode(node, "TypeAlias"); 5256}; 5257 5258// Opaque type aliases 5259 5260pp$8.flowParseOpaqueType = function (node, declare) { 5261 this.expectContextual("type"); 5262 node.id = this.flowParseRestrictedIdentifier(); 5263 5264 if (this.isRelational("<")) { 5265 node.typeParameters = this.flowParseTypeParameterDeclaration(); 5266 } else { 5267 node.typeParameters = null; 5268 } 5269 5270 // Parse the supertype 5271 node.supertype = null; 5272 if (this.match(types.colon)) { 5273 node.supertype = this.flowParseTypeInitialiser(types.colon); 5274 } 5275 5276 node.impltype = null; 5277 if (!declare) { 5278 node.impltype = this.flowParseTypeInitialiser(types.eq); 5279 } 5280 this.semicolon(); 5281 5282 return this.finishNode(node, "OpaqueType"); 5283}; 5284 5285// Type annotations 5286 5287pp$8.flowParseTypeParameter = function () { 5288 var node = this.startNode(); 5289 5290 var variance = this.flowParseVariance(); 5291 5292 var ident = this.flowParseTypeAnnotatableIdentifier(); 5293 node.name = ident.name; 5294 node.variance = variance; 5295 node.bound = ident.typeAnnotation; 5296 5297 if (this.match(types.eq)) { 5298 this.eat(types.eq); 5299 node.default = this.flowParseType(); 5300 } 5301 5302 return this.finishNode(node, "TypeParameter"); 5303}; 5304 5305pp$8.flowParseTypeParameterDeclaration = function () { 5306 var oldInType = this.state.inType; 5307 var node = this.startNode(); 5308 node.params = []; 5309 5310 this.state.inType = true; 5311 5312 // istanbul ignore else: this condition is already checked at all call sites 5313 if (this.isRelational("<") || this.match(types.jsxTagStart)) { 5314 this.next(); 5315 } else { 5316 this.unexpected(); 5317 } 5318 5319 do { 5320 node.params.push(this.flowParseTypeParameter()); 5321 if (!this.isRelational(">")) { 5322 this.expect(types.comma); 5323 } 5324 } while (!this.isRelational(">")); 5325 this.expectRelational(">"); 5326 5327 this.state.inType = oldInType; 5328 5329 return this.finishNode(node, "TypeParameterDeclaration"); 5330}; 5331 5332pp$8.flowParseTypeParameterInstantiation = function () { 5333 var node = this.startNode(); 5334 var oldInType = this.state.inType; 5335 node.params = []; 5336 5337 this.state.inType = true; 5338 5339 this.expectRelational("<"); 5340 while (!this.isRelational(">")) { 5341 node.params.push(this.flowParseType()); 5342 if (!this.isRelational(">")) { 5343 this.expect(types.comma); 5344 } 5345 } 5346 this.expectRelational(">"); 5347 5348 this.state.inType = oldInType; 5349 5350 return this.finishNode(node, "TypeParameterInstantiation"); 5351}; 5352 5353pp$8.flowParseObjectPropertyKey = function () { 5354 return this.match(types.num) || this.match(types.string) ? this.parseExprAtom() : this.parseIdentifier(true); 5355}; 5356 5357pp$8.flowParseObjectTypeIndexer = function (node, isStatic, variance) { 5358 node.static = isStatic; 5359 5360 this.expect(types.bracketL); 5361 if (this.lookahead().type === types.colon) { 5362 node.id = this.flowParseObjectPropertyKey(); 5363 node.key = this.flowParseTypeInitialiser(); 5364 } else { 5365 node.id = null; 5366 node.key = this.flowParseType(); 5367 } 5368 this.expect(types.bracketR); 5369 node.value = this.flowParseTypeInitialiser(); 5370 node.variance = variance; 5371 5372 this.flowObjectTypeSemicolon(); 5373 return this.finishNode(node, "ObjectTypeIndexer"); 5374}; 5375 5376pp$8.flowParseObjectTypeMethodish = function (node) { 5377 node.params = []; 5378 node.rest = null; 5379 node.typeParameters = null; 5380 5381 if (this.isRelational("<")) { 5382 node.typeParameters = this.flowParseTypeParameterDeclaration(); 5383 } 5384 5385 this.expect(types.parenL); 5386 while (!this.match(types.parenR) && !this.match(types.ellipsis)) { 5387 node.params.push(this.flowParseFunctionTypeParam()); 5388 if (!this.match(types.parenR)) { 5389 this.expect(types.comma); 5390 } 5391 } 5392 5393 if (this.eat(types.ellipsis)) { 5394 node.rest = this.flowParseFunctionTypeParam(); 5395 } 5396 this.expect(types.parenR); 5397 node.returnType = this.flowParseTypeInitialiser(); 5398 5399 return this.finishNode(node, "FunctionTypeAnnotation"); 5400}; 5401 5402pp$8.flowParseObjectTypeMethod = function (startPos, startLoc, isStatic, key) { 5403 var node = this.startNodeAt(startPos, startLoc); 5404 node.value = this.flowParseObjectTypeMethodish(this.startNodeAt(startPos, startLoc)); 5405 node.static = isStatic; 5406 node.key = key; 5407 node.optional = false; 5408 this.flowObjectTypeSemicolon(); 5409 return this.finishNode(node, "ObjectTypeProperty"); 5410}; 5411 5412pp$8.flowParseObjectTypeCallProperty = function (node, isStatic) { 5413 var valueNode = this.startNode(); 5414 node.static = isStatic; 5415 node.value = this.flowParseObjectTypeMethodish(valueNode); 5416 this.flowObjectTypeSemicolon(); 5417 return this.finishNode(node, "ObjectTypeCallProperty"); 5418}; 5419 5420pp$8.flowParseObjectType = function (allowStatic, allowExact, allowSpread) { 5421 var oldInType = this.state.inType; 5422 this.state.inType = true; 5423 5424 var nodeStart = this.startNode(); 5425 var node = void 0; 5426 var propertyKey = void 0; 5427 var isStatic = false; 5428 5429 nodeStart.callProperties = []; 5430 nodeStart.properties = []; 5431 nodeStart.indexers = []; 5432 5433 var endDelim = void 0; 5434 var exact = void 0; 5435 if (allowExact && this.match(types.braceBarL)) { 5436 this.expect(types.braceBarL); 5437 endDelim = types.braceBarR; 5438 exact = true; 5439 } else { 5440 this.expect(types.braceL); 5441 endDelim = types.braceR; 5442 exact = false; 5443 } 5444 5445 nodeStart.exact = exact; 5446 5447 while (!this.match(endDelim)) { 5448 var optional = false; 5449 var startPos = this.state.start; 5450 var startLoc = this.state.startLoc; 5451 node = this.startNode(); 5452 if (allowStatic && this.isContextual("static") && this.lookahead().type !== types.colon) { 5453 this.next(); 5454 isStatic = true; 5455 } 5456 5457 var variancePos = this.state.start; 5458 var variance = this.flowParseVariance(); 5459 5460 if (this.match(types.bracketL)) { 5461 nodeStart.indexers.push(this.flowParseObjectTypeIndexer(node, isStatic, variance)); 5462 } else if (this.match(types.parenL) || this.isRelational("<")) { 5463 if (variance) { 5464 this.unexpected(variancePos); 5465 } 5466 nodeStart.callProperties.push(this.flowParseObjectTypeCallProperty(node, isStatic)); 5467 } else { 5468 if (this.match(types.ellipsis)) { 5469 if (!allowSpread) { 5470 this.unexpected(null, "Spread operator cannot appear in class or interface definitions"); 5471 } 5472 if (variance) { 5473 this.unexpected(variance.start, "Spread properties cannot have variance"); 5474 } 5475 this.expect(types.ellipsis); 5476 node.argument = this.flowParseType(); 5477 this.flowObjectTypeSemicolon(); 5478 nodeStart.properties.push(this.finishNode(node, "ObjectTypeSpreadProperty")); 5479 } else { 5480 propertyKey = this.flowParseObjectPropertyKey(); 5481 if (this.isRelational("<") || this.match(types.parenL)) { 5482 // This is a method property 5483 if (variance) { 5484 this.unexpected(variance.start); 5485 } 5486 nodeStart.properties.push(this.flowParseObjectTypeMethod(startPos, startLoc, isStatic, propertyKey)); 5487 } else { 5488 if (this.eat(types.question)) { 5489 optional = true; 5490 } 5491 node.key = propertyKey; 5492 node.value = this.flowParseTypeInitialiser(); 5493 node.optional = optional; 5494 node.static = isStatic; 5495 node.variance = variance; 5496 this.flowObjectTypeSemicolon(); 5497 nodeStart.properties.push(this.finishNode(node, "ObjectTypeProperty")); 5498 } 5499 } 5500 } 5501 5502 isStatic = false; 5503 } 5504 5505 this.expect(endDelim); 5506 5507 var out = this.finishNode(nodeStart, "ObjectTypeAnnotation"); 5508 5509 this.state.inType = oldInType; 5510 5511 return out; 5512}; 5513 5514pp$8.flowObjectTypeSemicolon = function () { 5515 if (!this.eat(types.semi) && !this.eat(types.comma) && !this.match(types.braceR) && !this.match(types.braceBarR)) { 5516 this.unexpected(); 5517 } 5518}; 5519 5520pp$8.flowParseQualifiedTypeIdentifier = function (startPos, startLoc, id) { 5521 startPos = startPos || this.state.start; 5522 startLoc = startLoc || this.state.startLoc; 5523 var node = id || this.parseIdentifier(); 5524 5525 while (this.eat(types.dot)) { 5526 var node2 = this.startNodeAt(startPos, startLoc); 5527 node2.qualification = node; 5528 node2.id = this.parseIdentifier(); 5529 node = this.finishNode(node2, "QualifiedTypeIdentifier"); 5530 } 5531 5532 return node; 5533}; 5534 5535pp$8.flowParseGenericType = function (startPos, startLoc, id) { 5536 var node = this.startNodeAt(startPos, startLoc); 5537 5538 node.typeParameters = null; 5539 node.id = this.flowParseQualifiedTypeIdentifier(startPos, startLoc, id); 5540 5541 if (this.isRelational("<")) { 5542 node.typeParameters = this.flowParseTypeParameterInstantiation(); 5543 } 5544 5545 return this.finishNode(node, "GenericTypeAnnotation"); 5546}; 5547 5548pp$8.flowParseTypeofType = function () { 5549 var node = this.startNode(); 5550 this.expect(types._typeof); 5551 node.argument = this.flowParsePrimaryType(); 5552 return this.finishNode(node, "TypeofTypeAnnotation"); 5553}; 5554 5555pp$8.flowParseTupleType = function () { 5556 var node = this.startNode(); 5557 node.types = []; 5558 this.expect(types.bracketL); 5559 // We allow trailing commas 5560 while (this.state.pos < this.input.length && !this.match(types.bracketR)) { 5561 node.types.push(this.flowParseType()); 5562 if (this.match(types.bracketR)) break; 5563 this.expect(types.comma); 5564 } 5565 this.expect(types.bracketR); 5566 return this.finishNode(node, "TupleTypeAnnotation"); 5567}; 5568 5569pp$8.flowParseFunctionTypeParam = function () { 5570 var name = null; 5571 var optional = false; 5572 var typeAnnotation = null; 5573 var node = this.startNode(); 5574 var lh = this.lookahead(); 5575 if (lh.type === types.colon || lh.type === types.question) { 5576 name = this.parseIdentifier(); 5577 if (this.eat(types.question)) { 5578 optional = true; 5579 } 5580 typeAnnotation = this.flowParseTypeInitialiser(); 5581 } else { 5582 typeAnnotation = this.flowParseType(); 5583 } 5584 node.name = name; 5585 node.optional = optional; 5586 node.typeAnnotation = typeAnnotation; 5587 return this.finishNode(node, "FunctionTypeParam"); 5588}; 5589 5590pp$8.reinterpretTypeAsFunctionTypeParam = function (type) { 5591 var node = this.startNodeAt(type.start, type.loc.start); 5592 node.name = null; 5593 node.optional = false; 5594 node.typeAnnotation = type; 5595 return this.finishNode(node, "FunctionTypeParam"); 5596}; 5597 5598pp$8.flowParseFunctionTypeParams = function () { 5599 var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; 5600 5601 var ret = { params: params, rest: null }; 5602 while (!this.match(types.parenR) && !this.match(types.ellipsis)) { 5603 ret.params.push(this.flowParseFunctionTypeParam()); 5604 if (!this.match(types.parenR)) { 5605 this.expect(types.comma); 5606 } 5607 } 5608 if (this.eat(types.ellipsis)) { 5609 ret.rest = this.flowParseFunctionTypeParam(); 5610 } 5611 return ret; 5612}; 5613 5614pp$8.flowIdentToTypeAnnotation = function (startPos, startLoc, node, id) { 5615 switch (id.name) { 5616 case "any": 5617 return this.finishNode(node, "AnyTypeAnnotation"); 5618 5619 case "void": 5620 return this.finishNode(node, "VoidTypeAnnotation"); 5621 5622 case "bool": 5623 case "boolean": 5624 return this.finishNode(node, "BooleanTypeAnnotation"); 5625 5626 case "mixed": 5627 return this.finishNode(node, "MixedTypeAnnotation"); 5628 5629 case "empty": 5630 return this.finishNode(node, "EmptyTypeAnnotation"); 5631 5632 case "number": 5633 return this.finishNode(node, "NumberTypeAnnotation"); 5634 5635 case "string": 5636 return this.finishNode(node, "StringTypeAnnotation"); 5637 5638 default: 5639 return this.flowParseGenericType(startPos, startLoc, id); 5640 } 5641}; 5642 5643// The parsing of types roughly parallels the parsing of expressions, and 5644// primary types are kind of like primary expressions...they're the 5645// primitives with which other types are constructed. 5646pp$8.flowParsePrimaryType = function () { 5647 var startPos = this.state.start; 5648 var startLoc = this.state.startLoc; 5649 var node = this.startNode(); 5650 var tmp = void 0; 5651 var type = void 0; 5652 var isGroupedType = false; 5653 var oldNoAnonFunctionType = this.state.noAnonFunctionType; 5654 5655 switch (this.state.type) { 5656 case types.name: 5657 return this.flowIdentToTypeAnnotation(startPos, startLoc, node, this.parseIdentifier()); 5658 5659 case types.braceL: 5660 return this.flowParseObjectType(false, false, true); 5661 5662 case types.braceBarL: 5663 return this.flowParseObjectType(false, true, true); 5664 5665 case types.bracketL: 5666 return this.flowParseTupleType(); 5667 5668 case types.relational: 5669 if (this.state.value === "<") { 5670 node.typeParameters = this.flowParseTypeParameterDeclaration(); 5671 this.expect(types.parenL); 5672 tmp = this.flowParseFunctionTypeParams(); 5673 node.params = tmp.params; 5674 node.rest = tmp.rest; 5675 this.expect(types.parenR); 5676 5677 this.expect(types.arrow); 5678 5679 node.returnType = this.flowParseType(); 5680 5681 return this.finishNode(node, "FunctionTypeAnnotation"); 5682 } 5683 break; 5684 5685 case types.parenL: 5686 this.next(); 5687 5688 // Check to see if this is actually a grouped type 5689 if (!this.match(types.parenR) && !this.match(types.ellipsis)) { 5690 if (this.match(types.name)) { 5691 var token = this.lookahead().type; 5692 isGroupedType = token !== types.question && token !== types.colon; 5693 } else { 5694 isGroupedType = true; 5695 } 5696 } 5697 5698 if (isGroupedType) { 5699 this.state.noAnonFunctionType = false; 5700 type = this.flowParseType(); 5701 this.state.noAnonFunctionType = oldNoAnonFunctionType; 5702 5703 // A `,` or a `) =>` means this is an anonymous function type 5704 if (this.state.noAnonFunctionType || !(this.match(types.comma) || this.match(types.parenR) && this.lookahead().type === types.arrow)) { 5705 this.expect(types.parenR); 5706 return type; 5707 } else { 5708 // Eat a comma if there is one 5709 this.eat(types.comma); 5710 } 5711 } 5712 5713 if (type) { 5714 tmp = this.flowParseFunctionTypeParams([this.reinterpretTypeAsFunctionTypeParam(type)]); 5715 } else { 5716 tmp = this.flowParseFunctionTypeParams(); 5717 } 5718 5719 node.params = tmp.params; 5720 node.rest = tmp.rest; 5721 5722 this.expect(types.parenR); 5723 5724 this.expect(types.arrow); 5725 5726 node.returnType = this.flowParseType(); 5727 5728 node.typeParameters = null; 5729 5730 return this.finishNode(node, "FunctionTypeAnnotation"); 5731 5732 case types.string: 5733 return this.parseLiteral(this.state.value, "StringLiteralTypeAnnotation"); 5734 5735 case types._true:case types._false: 5736 node.value = this.match(types._true); 5737 this.next(); 5738 return this.finishNode(node, "BooleanLiteralTypeAnnotation"); 5739 5740 case types.plusMin: 5741 if (this.state.value === "-") { 5742 this.next(); 5743 if (!this.match(types.num)) this.unexpected(null, "Unexpected token, expected number"); 5744 5745 return this.parseLiteral(-this.state.value, "NumericLiteralTypeAnnotation", node.start, node.loc.start); 5746 } 5747 5748 this.unexpected(); 5749 case types.num: 5750 return this.parseLiteral(this.state.value, "NumericLiteralTypeAnnotation"); 5751 5752 case types._null: 5753 node.value = this.match(types._null); 5754 this.next(); 5755 return this.finishNode(node, "NullLiteralTypeAnnotation"); 5756 5757 case types._this: 5758 node.value = this.match(types._this); 5759 this.next(); 5760 return this.finishNode(node, "ThisTypeAnnotation"); 5761 5762 case types.star: 5763 this.next(); 5764 return this.finishNode(node, "ExistentialTypeParam"); 5765 5766 default: 5767 if (this.state.type.keyword === "typeof") { 5768 return this.flowParseTypeofType(); 5769 } 5770 } 5771 5772 this.unexpected(); 5773}; 5774 5775pp$8.flowParsePostfixType = function () { 5776 var startPos = this.state.start, 5777 startLoc = this.state.startLoc; 5778 var type = this.flowParsePrimaryType(); 5779 while (!this.canInsertSemicolon() && this.match(types.bracketL)) { 5780 var node = this.startNodeAt(startPos, startLoc); 5781 node.elementType = type; 5782 this.expect(types.bracketL); 5783 this.expect(types.bracketR); 5784 type = this.finishNode(node, "ArrayTypeAnnotation"); 5785 } 5786 return type; 5787}; 5788 5789pp$8.flowParsePrefixType = function () { 5790 var node = this.startNode(); 5791 if (this.eat(types.question)) { 5792 node.typeAnnotation = this.flowParsePrefixType(); 5793 return this.finishNode(node, "NullableTypeAnnotation"); 5794 } else { 5795 return this.flowParsePostfixType(); 5796 } 5797}; 5798 5799pp$8.flowParseAnonFunctionWithoutParens = function () { 5800 var param = this.flowParsePrefixType(); 5801 if (!this.state.noAnonFunctionType && this.eat(types.arrow)) { 5802 var node = this.startNodeAt(param.start, param.loc.start); 5803 node.params = [this.reinterpretTypeAsFunctionTypeParam(param)]; 5804 node.rest = null; 5805 node.returnType = this.flowParseType(); 5806 node.typeParameters = null; 5807 return this.finishNode(node, "FunctionTypeAnnotation"); 5808 } 5809 return param; 5810}; 5811 5812pp$8.flowParseIntersectionType = function () { 5813 var node = this.startNode(); 5814 this.eat(types.bitwiseAND); 5815 var type = this.flowParseAnonFunctionWithoutParens(); 5816 node.types = [type]; 5817 while (this.eat(types.bitwiseAND)) { 5818 node.types.push(this.flowParseAnonFunctionWithoutParens()); 5819 } 5820 return node.types.length === 1 ? type : this.finishNode(node, "IntersectionTypeAnnotation"); 5821}; 5822 5823pp$8.flowParseUnionType = function () { 5824 var node = this.startNode(); 5825 this.eat(types.bitwiseOR); 5826 var type = this.flowParseIntersectionType(); 5827 node.types = [type]; 5828 while (this.eat(types.bitwiseOR)) { 5829 node.types.push(this.flowParseIntersectionType()); 5830 } 5831 return node.types.length === 1 ? type : this.finishNode(node, "UnionTypeAnnotation"); 5832}; 5833 5834pp$8.flowParseType = function () { 5835 var oldInType = this.state.inType; 5836 this.state.inType = true; 5837 var type = this.flowParseUnionType(); 5838 this.state.inType = oldInType; 5839 return type; 5840}; 5841 5842pp$8.flowParseTypeAnnotation = function () { 5843 var node = this.startNode(); 5844 node.typeAnnotation = this.flowParseTypeInitialiser(); 5845 return this.finishNode(node, "TypeAnnotation"); 5846}; 5847 5848pp$8.flowParseTypeAndPredicateAnnotation = function () { 5849 var node = this.startNode(); 5850 5851 var _flowParseTypeAndPred2 = this.flowParseTypeAndPredicateInitialiser(); 5852 5853 node.typeAnnotation = _flowParseTypeAndPred2[0]; 5854 node.predicate = _flowParseTypeAndPred2[1]; 5855 5856 return this.finishNode(node, "TypeAnnotation"); 5857}; 5858 5859pp$8.flowParseTypeAnnotatableIdentifier = function () { 5860 var ident = this.flowParseRestrictedIdentifier(); 5861 if (this.match(types.colon)) { 5862 ident.typeAnnotation = this.flowParseTypeAnnotation(); 5863 this.finishNode(ident, ident.type); 5864 } 5865 return ident; 5866}; 5867 5868pp$8.typeCastToParameter = function (node) { 5869 node.expression.typeAnnotation = node.typeAnnotation; 5870 5871 return this.finishNodeAt(node.expression, node.expression.type, node.typeAnnotation.end, node.typeAnnotation.loc.end); 5872}; 5873 5874pp$8.flowParseVariance = function () { 5875 var variance = null; 5876 if (this.match(types.plusMin)) { 5877 if (this.state.value === "+") { 5878 variance = "plus"; 5879 } else if (this.state.value === "-") { 5880 variance = "minus"; 5881 } 5882 this.next(); 5883 } 5884 return variance; 5885}; 5886 5887var flowPlugin = function (instance) { 5888 // plain function return types: function name(): string {} 5889 instance.extend("parseFunctionBody", function (inner) { 5890 return function (node, allowExpression) { 5891 if (this.match(types.colon) && !allowExpression) { 5892 // if allowExpression is true then we're parsing an arrow function and if 5893 // there's a return type then it's been handled elsewhere 5894 node.returnType = this.flowParseTypeAndPredicateAnnotation(); 5895 } 5896 5897 return inner.call(this, node, allowExpression); 5898 }; 5899 }); 5900 5901 // interfaces 5902 instance.extend("parseStatement", function (inner) { 5903 return function (declaration, topLevel) { 5904 // strict mode handling of `interface` since it's a reserved word 5905 if (this.state.strict && this.match(types.name) && this.state.value === "interface") { 5906 var node = this.startNode(); 5907 this.next(); 5908 return this.flowParseInterface(node); 5909 } else { 5910 return inner.call(this, declaration, topLevel); 5911 } 5912 }; 5913 }); 5914 5915 // declares, interfaces and type aliases 5916 instance.extend("parseExpressionStatement", function (inner) { 5917 return function (node, expr) { 5918 if (expr.type === "Identifier") { 5919 if (expr.name === "declare") { 5920 if (this.match(types._class) || this.match(types.name) || this.match(types._function) || this.match(types._var) || this.match(types._export)) { 5921 return this.flowParseDeclare(node); 5922 } 5923 } else if (this.match(types.name)) { 5924 if (expr.name === "interface") { 5925 return this.flowParseInterface(node); 5926 } else if (expr.name === "type") { 5927 return this.flowParseTypeAlias(node); 5928 } else if (expr.name === "opaque") { 5929 return this.flowParseOpaqueType(node, false); 5930 } 5931 } 5932 } 5933 5934 return inner.call(this, node, expr); 5935 }; 5936 }); 5937 5938 // export type 5939 instance.extend("shouldParseExportDeclaration", function (inner) { 5940 return function () { 5941 return this.isContextual("type") || this.isContextual("interface") || this.isContextual("opaque") || inner.call(this); 5942 }; 5943 }); 5944 5945 instance.extend("isExportDefaultSpecifier", function (inner) { 5946 return function () { 5947 if (this.match(types.name) && (this.state.value === "type" || this.state.value === "interface" || this.state.value === "opaque")) { 5948 return false; 5949 } 5950 5951 return inner.call(this); 5952 }; 5953 }); 5954 5955 instance.extend("parseConditional", function (inner) { 5956 return function (expr, noIn, startPos, startLoc, refNeedsArrowPos) { 5957 // only do the expensive clone if there is a question mark 5958 // and if we come from inside parens 5959 if (refNeedsArrowPos && this.match(types.question)) { 5960 var state = this.state.clone(); 5961 try { 5962 return inner.call(this, expr, noIn, startPos, startLoc); 5963 } catch (err) { 5964 if (err instanceof SyntaxError) { 5965 this.state = state; 5966 refNeedsArrowPos.start = err.pos || this.state.start; 5967 return expr; 5968 } else { 5969 // istanbul ignore next: no such error is expected 5970 throw err; 5971 } 5972 } 5973 } 5974 5975 return inner.call(this, expr, noIn, startPos, startLoc); 5976 }; 5977 }); 5978 5979 instance.extend("parseParenItem", function (inner) { 5980 return function (node, startPos, startLoc) { 5981 node = inner.call(this, node, startPos, startLoc); 5982 if (this.eat(types.question)) { 5983 node.optional = true; 5984 } 5985 5986 if (this.match(types.colon)) { 5987 var typeCastNode = this.startNodeAt(startPos, startLoc); 5988 typeCastNode.expression = node; 5989 typeCastNode.typeAnnotation = this.flowParseTypeAnnotation(); 5990 5991 return this.finishNode(typeCastNode, "TypeCastExpression"); 5992 } 5993 5994 return node; 5995 }; 5996 }); 5997 5998 instance.extend("parseExport", function (inner) { 5999 return function (node) { 6000 node = inner.call(this, node); 6001 if (node.type === "ExportNamedDeclaration") { 6002 node.exportKind = node.exportKind || "value"; 6003 } 6004 return node; 6005 }; 6006 }); 6007 6008 instance.extend("parseExportDeclaration", function (inner) { 6009 return function (node) { 6010 if (this.isContextual("type")) { 6011 node.exportKind = "type"; 6012 6013 var declarationNode = this.startNode(); 6014 this.next(); 6015 6016 if (this.match(types.braceL)) { 6017 // export type { foo, bar }; 6018 node.specifiers = this.parseExportSpecifiers(); 6019 this.parseExportFrom(node); 6020 return null; 6021 } else { 6022 // export type Foo = Bar; 6023 return this.flowParseTypeAlias(declarationNode); 6024 } 6025 } else if (this.isContextual("opaque")) { 6026 node.exportKind = "type"; 6027 6028 var _declarationNode = this.startNode(); 6029 this.next(); 6030 // export opaque type Foo = Bar; 6031 return this.flowParseOpaqueType(_declarationNode, false); 6032 } else if (this.isContextual("interface")) { 6033 node.exportKind = "type"; 6034 var _declarationNode2 = this.startNode(); 6035 this.next(); 6036 return this.flowParseInterface(_declarationNode2); 6037 } else { 6038 return inner.call(this, node); 6039 } 6040 }; 6041 }); 6042 6043 instance.extend("parseClassId", function (inner) { 6044 return function (node) { 6045 inner.apply(this, arguments); 6046 if (this.isRelational("<")) { 6047 node.typeParameters = this.flowParseTypeParameterDeclaration(); 6048 } 6049 }; 6050 }); 6051 6052 // don't consider `void` to be a keyword as then it'll use the void token type 6053 // and set startExpr 6054 instance.extend("isKeyword", function (inner) { 6055 return function (name) { 6056 if (this.state.inType && name === "void") { 6057 return false; 6058 } else { 6059 return inner.call(this, name); 6060 } 6061 }; 6062 }); 6063 6064 // ensure that inside flow types, we bypass the jsx parser plugin 6065 instance.extend("readToken", function (inner) { 6066 return function (code) { 6067 if (this.state.inType && (code === 62 || code === 60)) { 6068 return this.finishOp(types.relational, 1); 6069 } else { 6070 return inner.call(this, code); 6071 } 6072 }; 6073 }); 6074 6075 // don't lex any token as a jsx one inside a flow type 6076 instance.extend("jsx_readToken", function (inner) { 6077 return function () { 6078 if (!this.state.inType) return inner.call(this); 6079 }; 6080 }); 6081 6082 instance.extend("toAssignable", function (inner) { 6083 return function (node, isBinding, contextDescription) { 6084 if (node.type === "TypeCastExpression") { 6085 return inner.call(this, this.typeCastToParameter(node), isBinding, contextDescription); 6086 } else { 6087 return inner.call(this, node, isBinding, contextDescription); 6088 } 6089 }; 6090 }); 6091 6092 // turn type casts that we found in function parameter head into type annotated params 6093 instance.extend("toAssignableList", function (inner) { 6094 return function (exprList, isBinding, contextDescription) { 6095 for (var i = 0; i < exprList.length; i++) { 6096 var expr = exprList[i]; 6097 if (expr && expr.type === "TypeCastExpression") { 6098 exprList[i] = this.typeCastToParameter(expr); 6099 } 6100 } 6101 return inner.call(this, exprList, isBinding, contextDescription); 6102 }; 6103 }); 6104 6105 // this is a list of nodes, from something like a call expression, we need to filter the 6106 // type casts that we've found that are illegal in this context 6107 instance.extend("toReferencedList", function () { 6108 return function (exprList) { 6109 for (var i = 0; i < exprList.length; i++) { 6110 var expr = exprList[i]; 6111 if (expr && expr._exprListItem && expr.type === "TypeCastExpression") { 6112 this.raise(expr.start, "Unexpected type cast"); 6113 } 6114 } 6115 6116 return exprList; 6117 }; 6118 }); 6119 6120 // parse an item inside a expression list eg. `(NODE, NODE)` where NODE represents 6121 // the position where this function is called 6122 instance.extend("parseExprListItem", function (inner) { 6123 return function () { 6124 var container = this.startNode(); 6125 6126 for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { 6127 args[_key] = arguments[_key]; 6128 } 6129 6130 var node = inner.call.apply(inner, [this].concat(args)); 6131 if (this.match(types.colon)) { 6132 container._exprListItem = true; 6133 container.expression = node; 6134 container.typeAnnotation = this.flowParseTypeAnnotation(); 6135 return this.finishNode(container, "TypeCastExpression"); 6136 } else { 6137 return node; 6138 } 6139 }; 6140 }); 6141 6142 instance.extend("checkLVal", function (inner) { 6143 return function (node) { 6144 if (node.type !== "TypeCastExpression") { 6145 return inner.apply(this, arguments); 6146 } 6147 }; 6148 }); 6149 6150 // parse class property type annotations 6151 instance.extend("parseClassProperty", function (inner) { 6152 return function (node) { 6153 delete node.variancePos; 6154 if (this.match(types.colon)) { 6155 node.typeAnnotation = this.flowParseTypeAnnotation(); 6156 } 6157 return inner.call(this, node); 6158 }; 6159 }); 6160 6161 // determine whether or not we're currently in the position where a class method would appear 6162 instance.extend("isClassMethod", function (inner) { 6163 return function () { 6164 return this.isRelational("<") || inner.call(this); 6165 }; 6166 }); 6167 6168 // determine whether or not we're currently in the position where a class property would appear 6169 instance.extend("isClassProperty", function (inner) { 6170 return function () { 6171 return this.match(types.colon) || inner.call(this); 6172 }; 6173 }); 6174 6175 instance.extend("isNonstaticConstructor", function (inner) { 6176 return function (method) { 6177 return !this.match(types.colon) && inner.call(this, method); 6178 }; 6179 }); 6180 6181 // parse type parameters for class methods 6182 instance.extend("parseClassMethod", function (inner) { 6183 return function (classBody, method) { 6184 if (method.variance) { 6185 this.unexpected(method.variancePos); 6186 } 6187 delete method.variance; 6188 delete method.variancePos; 6189 if (this.isRelational("<")) { 6190 method.typeParameters = this.flowParseTypeParameterDeclaration(); 6191 } 6192 6193 for (var _len2 = arguments.length, args = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) { 6194 args[_key2 - 2] = arguments[_key2]; 6195 } 6196 6197 inner.call.apply(inner, [this, classBody, method].concat(args)); 6198 }; 6199 }); 6200 6201 // parse a the super class type parameters and implements 6202 instance.extend("parseClassSuper", function (inner) { 6203 return function (node, isStatement) { 6204 inner.call(this, node, isStatement); 6205 if (node.superClass && this.isRelational("<")) { 6206 node.superTypeParameters = this.flowParseTypeParameterInstantiation(); 6207 } 6208 if (this.isContextual("implements")) { 6209 this.next(); 6210 var implemented = node.implements = []; 6211 do { 6212 var _node = this.startNode(); 6213 _node.id = this.parseIdentifier(); 6214 if (this.isRelational("<")) { 6215 _node.typeParameters = this.flowParseTypeParameterInstantiation(); 6216 } else { 6217 _node.typeParameters = null; 6218 } 6219 implemented.push(this.finishNode(_node, "ClassImplements")); 6220 } while (this.eat(types.comma)); 6221 } 6222 }; 6223 }); 6224 6225 instance.extend("parsePropertyName", function (inner) { 6226 return function (node) { 6227 var variancePos = this.state.start; 6228 var variance = this.flowParseVariance(); 6229 var key = inner.call(this, node); 6230 node.variance = variance; 6231 node.variancePos = variancePos; 6232 return key; 6233 }; 6234 }); 6235 6236 // parse type parameters for object method shorthand 6237 instance.extend("parseObjPropValue", function (inner) { 6238 return function (prop) { 6239 if (prop.variance) { 6240 this.unexpected(prop.variancePos); 6241 } 6242 delete prop.variance; 6243 delete prop.variancePos; 6244 6245 var typeParameters = void 0; 6246 6247 // method shorthand 6248 if (this.isRelational("<")) { 6249 typeParameters = this.flowParseTypeParameterDeclaration(); 6250 if (!this.match(types.parenL)) this.unexpected(); 6251 } 6252 6253 inner.apply(this, arguments); 6254 6255 // add typeParameters if we found them 6256 if (typeParameters) { 6257 (prop.value || prop).typeParameters = typeParameters; 6258 } 6259 }; 6260 }); 6261 6262 instance.extend("parseAssignableListItemTypes", function () { 6263 return function (param) { 6264 if (this.eat(types.question)) { 6265 param.optional = true; 6266 } 6267 if (this.match(types.colon)) { 6268 param.typeAnnotation = this.flowParseTypeAnnotation(); 6269 } 6270 this.finishNode(param, param.type); 6271 return param; 6272 }; 6273 }); 6274 6275 instance.extend("parseMaybeDefault", function (inner) { 6276 return function () { 6277 for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { 6278 args[_key3] = arguments[_key3]; 6279 } 6280 6281 var node = inner.apply(this, args); 6282 6283 if (node.type === "AssignmentPattern" && node.typeAnnotation && node.right.start < node.typeAnnotation.start) { 6284 this.raise(node.typeAnnotation.start, "Type annotations must come before default assignments, e.g. instead of `age = 25: number` use `age: number = 25`"); 6285 } 6286 6287 return node; 6288 }; 6289 }); 6290 6291 // parse typeof and type imports 6292 instance.extend("parseImportSpecifiers", function (inner) { 6293 return function (node) { 6294 node.importKind = "value"; 6295 6296 var kind = null; 6297 if (this.match(types._typeof)) { 6298 kind = "typeof"; 6299 } else if (this.isContextual("type")) { 6300 kind = "type"; 6301 } 6302 if (kind) { 6303 var lh = this.lookahead(); 6304 if (lh.type === types.name && lh.value !== "from" || lh.type === types.braceL || lh.type === types.star) { 6305 this.next(); 6306 node.importKind = kind; 6307 } 6308 } 6309 6310 inner.call(this, node); 6311 }; 6312 }); 6313 6314 // parse import-type/typeof shorthand 6315 instance.extend("parseImportSpecifier", function () { 6316 return function (node) { 6317 var specifier = this.startNode(); 6318 var firstIdentLoc = this.state.start; 6319 var firstIdent = this.parseIdentifier(true); 6320 6321 var specifierTypeKind = null; 6322 if (firstIdent.name === "type") { 6323 specifierTypeKind = "type"; 6324 } else if (firstIdent.name === "typeof") { 6325 specifierTypeKind = "typeof"; 6326 } 6327 6328 var isBinding = false; 6329 if (this.isContextual("as")) { 6330 var as_ident = this.parseIdentifier(true); 6331 if (specifierTypeKind !== null && !this.match(types.name) && !this.state.type.keyword) { 6332 // `import {type as ,` or `import {type as }` 6333 specifier.imported = as_ident; 6334 specifier.importKind = specifierTypeKind; 6335 specifier.local = as_ident.__clone(); 6336 } else { 6337 // `import {type as foo` 6338 specifier.imported = firstIdent; 6339 specifier.importKind = null; 6340 specifier.local = this.parseIdentifier(); 6341 } 6342 } else if (specifierTypeKind !== null && (this.match(types.name) || this.state.type.keyword)) { 6343 // `import {type foo` 6344 specifier.imported = this.parseIdentifier(true); 6345 specifier.importKind = specifierTypeKind; 6346 if (this.eatContextual("as")) { 6347 specifier.local = this.parseIdentifier(); 6348 } else { 6349 isBinding = true; 6350 specifier.local = specifier.imported.__clone(); 6351 } 6352 } else { 6353 isBinding = true; 6354 specifier.imported = firstIdent; 6355 specifier.importKind = null; 6356 specifier.local = specifier.imported.__clone(); 6357 } 6358 6359 if ((node.importKind === "type" || node.importKind === "typeof") && (specifier.importKind === "type" || specifier.importKind === "typeof")) { 6360 this.raise(firstIdentLoc, "`The `type` and `typeof` keywords on named imports can only be used on regular `import` statements. It cannot be used with `import type` or `import typeof` statements`"); 6361 } 6362 6363 if (isBinding) this.checkReservedWord(specifier.local.name, specifier.start, true, true); 6364 6365 this.checkLVal(specifier.local, true, undefined, "import specifier"); 6366 node.specifiers.push(this.finishNode(specifier, "ImportSpecifier")); 6367 }; 6368 }); 6369 6370 // parse function type parameters - function foo<T>() {} 6371 instance.extend("parseFunctionParams", function (inner) { 6372 return function (node) { 6373 if (this.isRelational("<")) { 6374 node.typeParameters = this.flowParseTypeParameterDeclaration(); 6375 } 6376 inner.call(this, node); 6377 }; 6378 }); 6379 6380 // parse flow type annotations on variable declarator heads - let foo: string = bar 6381 instance.extend("parseVarHead", function (inner) { 6382 return function (decl) { 6383 inner.call(this, decl); 6384 if (this.match(types.colon)) { 6385 decl.id.typeAnnotation = this.flowParseTypeAnnotation(); 6386 this.finishNode(decl.id, decl.id.type); 6387 } 6388 }; 6389 }); 6390 6391 // parse the return type of an async arrow function - let foo = (async (): number => {}); 6392 instance.extend("parseAsyncArrowFromCallExpression", function (inner) { 6393 return function (node, call) { 6394 if (this.match(types.colon)) { 6395 var oldNoAnonFunctionType = this.state.noAnonFunctionType; 6396 this.state.noAnonFunctionType = true; 6397 node.returnType = this.flowParseTypeAnnotation(); 6398 this.state.noAnonFunctionType = oldNoAnonFunctionType; 6399 } 6400 6401 return inner.call(this, node, call); 6402 }; 6403 }); 6404 6405 // todo description 6406 instance.extend("shouldParseAsyncArrow", function (inner) { 6407 return function () { 6408 return this.match(types.colon) || inner.call(this); 6409 }; 6410 }); 6411 6412 // We need to support type parameter declarations for arrow functions. This 6413 // is tricky. There are three situations we need to handle 6414 // 6415 // 1. This is either JSX or an arrow function. We'll try JSX first. If that 6416 // fails, we'll try an arrow function. If that fails, we'll throw the JSX 6417 // error. 6418 // 2. This is an arrow function. We'll parse the type parameter declaration, 6419 // parse the rest, make sure the rest is an arrow function, and go from 6420 // there 6421 // 3. This is neither. Just call the inner function 6422 instance.extend("parseMaybeAssign", function (inner) { 6423 return function () { 6424 var jsxError = null; 6425 6426 for (var _len4 = arguments.length, args = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { 6427 args[_key4] = arguments[_key4]; 6428 } 6429 6430 if (types.jsxTagStart && this.match(types.jsxTagStart)) { 6431 var state = this.state.clone(); 6432 try { 6433 return inner.apply(this, args); 6434 } catch (err) { 6435 if (err instanceof SyntaxError) { 6436 this.state = state; 6437 6438 // Remove `tc.j_expr` and `tc.j_oTag` from context added 6439 // by parsing `jsxTagStart` to stop the JSX plugin from 6440 // messing with the tokens 6441 this.state.context.length -= 2; 6442 6443 jsxError = err; 6444 } else { 6445 // istanbul ignore next: no such error is expected 6446 throw err; 6447 } 6448 } 6449 } 6450 6451 if (jsxError != null || this.isRelational("<")) { 6452 var arrowExpression = void 0; 6453 var typeParameters = void 0; 6454 try { 6455 typeParameters = this.flowParseTypeParameterDeclaration(); 6456 6457 arrowExpression = inner.apply(this, args); 6458 arrowExpression.typeParameters = typeParameters; 6459 arrowExpression.start = typeParameters.start; 6460 arrowExpression.loc.start = typeParameters.loc.start; 6461 } catch (err) { 6462 throw jsxError || err; 6463 } 6464 6465 if (arrowExpression.type === "ArrowFunctionExpression") { 6466 return arrowExpression; 6467 } else if (jsxError != null) { 6468 throw jsxError; 6469 } else { 6470 this.raise(typeParameters.start, "Expected an arrow function after this type parameter declaration"); 6471 } 6472 } 6473 6474 return inner.apply(this, args); 6475 }; 6476 }); 6477 6478 // handle return types for arrow functions 6479 instance.extend("parseArrow", function (inner) { 6480 return function (node) { 6481 if (this.match(types.colon)) { 6482 var state = this.state.clone(); 6483 try { 6484 var oldNoAnonFunctionType = this.state.noAnonFunctionType; 6485 this.state.noAnonFunctionType = true; 6486 var returnType = this.flowParseTypeAndPredicateAnnotation(); 6487 this.state.noAnonFunctionType = oldNoAnonFunctionType; 6488 6489 if (this.canInsertSemicolon()) this.unexpected(); 6490 if (!this.match(types.arrow)) this.unexpected(); 6491 // assign after it is clear it is an arrow 6492 node.returnType = returnType; 6493 } catch (err) { 6494 if (err instanceof SyntaxError) { 6495 this.state = state; 6496 } else { 6497 // istanbul ignore next: no such error is expected 6498 throw err; 6499 } 6500 } 6501 } 6502 6503 return inner.call(this, node); 6504 }; 6505 }); 6506 6507 instance.extend("shouldParseArrow", function (inner) { 6508 return function () { 6509 return this.match(types.colon) || inner.call(this); 6510 }; 6511 }); 6512}; 6513 6514// Adapted from String.fromcodepoint to export the function without modifying String 6515/*! https://mths.be/fromcodepoint v0.2.1 by @mathias */ 6516 6517// The MIT License (MIT) 6518// Copyright (c) Mathias Bynens 6519// 6520// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6521// associated documentation files (the "Software"), to deal in the Software without restriction, 6522// including without limitation the rights to use, copy, modify, merge, publish, distribute, 6523// sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 6524// furnished to do so, subject to the following conditions: 6525// 6526// The above copyright notice and this permission notice shall be included in all copies or 6527// substantial portions of the Software. 6528// 6529// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 6530// NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 6531// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 6532// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 6533// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 6534 6535var fromCodePoint = String.fromCodePoint; 6536 6537if (!fromCodePoint) { 6538 var stringFromCharCode = String.fromCharCode; 6539 var floor = Math.floor; 6540 fromCodePoint = function fromCodePoint() { 6541 var MAX_SIZE = 0x4000; 6542 var codeUnits = []; 6543 var highSurrogate = void 0; 6544 var lowSurrogate = void 0; 6545 var index = -1; 6546 var length = arguments.length; 6547 if (!length) { 6548 return ""; 6549 } 6550 var result = ""; 6551 while (++index < length) { 6552 var codePoint = Number(arguments[index]); 6553 if (!isFinite(codePoint) || // `NaN`, `+Infinity`, or `-Infinity` 6554 codePoint < 0 || // not a valid Unicode code point 6555 codePoint > 0x10FFFF || // not a valid Unicode code point 6556 floor(codePoint) != codePoint // not an integer 6557 ) { 6558 throw RangeError("Invalid code point: " + codePoint); 6559 } 6560 if (codePoint <= 0xFFFF) { 6561 // BMP code point 6562 codeUnits.push(codePoint); 6563 } else { 6564 // Astral code point; split in surrogate halves 6565 // https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae 6566 codePoint -= 0x10000; 6567 highSurrogate = (codePoint >> 10) + 0xD800; 6568 lowSurrogate = codePoint % 0x400 + 0xDC00; 6569 codeUnits.push(highSurrogate, lowSurrogate); 6570 } 6571 if (index + 1 == length || codeUnits.length > MAX_SIZE) { 6572 result += stringFromCharCode.apply(null, codeUnits); 6573 codeUnits.length = 0; 6574 } 6575 } 6576 return result; 6577 }; 6578} 6579 6580var fromCodePoint$1 = fromCodePoint; 6581 6582var XHTMLEntities = { 6583 quot: "\"", 6584 amp: "&", 6585 apos: "'", 6586 lt: "<", 6587 gt: ">", 6588 nbsp: "\xA0", 6589 iexcl: "\xA1", 6590 cent: "\xA2", 6591 pound: "\xA3", 6592 curren: "\xA4", 6593 yen: "\xA5", 6594 brvbar: "\xA6", 6595 sect: "\xA7", 6596 uml: "\xA8", 6597 copy: "\xA9", 6598 ordf: "\xAA", 6599 laquo: "\xAB", 6600 not: "\xAC", 6601 shy: "\xAD", 6602 reg: "\xAE", 6603 macr: "\xAF", 6604 deg: "\xB0", 6605 plusmn: "\xB1", 6606 sup2: "\xB2", 6607 sup3: "\xB3", 6608 acute: "\xB4", 6609 micro: "\xB5", 6610 para: "\xB6", 6611 middot: "\xB7", 6612 cedil: "\xB8", 6613 sup1: "\xB9", 6614 ordm: "\xBA", 6615 raquo: "\xBB", 6616 frac14: "\xBC", 6617 frac12: "\xBD", 6618 frac34: "\xBE", 6619 iquest: "\xBF", 6620 Agrave: "\xC0", 6621 Aacute: "\xC1", 6622 Acirc: "\xC2", 6623 Atilde: "\xC3", 6624 Auml: "\xC4", 6625 Aring: "\xC5", 6626 AElig: "\xC6", 6627 Ccedil: "\xC7", 6628 Egrave: "\xC8", 6629 Eacute: "\xC9", 6630 Ecirc: "\xCA", 6631 Euml: "\xCB", 6632 Igrave: "\xCC", 6633 Iacute: "\xCD", 6634 Icirc: "\xCE", 6635 Iuml: "\xCF", 6636 ETH: "\xD0", 6637 Ntilde: "\xD1", 6638 Ograve: "\xD2", 6639 Oacute: "\xD3", 6640 Ocirc: "\xD4", 6641 Otilde: "\xD5", 6642 Ouml: "\xD6", 6643 times: "\xD7", 6644 Oslash: "\xD8", 6645 Ugrave: "\xD9", 6646 Uacute: "\xDA", 6647 Ucirc: "\xDB", 6648 Uuml: "\xDC", 6649 Yacute: "\xDD", 6650 THORN: "\xDE", 6651 szlig: "\xDF", 6652 agrave: "\xE0", 6653 aacute: "\xE1", 6654 acirc: "\xE2", 6655 atilde: "\xE3", 6656 auml: "\xE4", 6657 aring: "\xE5", 6658 aelig: "\xE6", 6659 ccedil: "\xE7", 6660 egrave: "\xE8", 6661 eacute: "\xE9", 6662 ecirc: "\xEA", 6663 euml: "\xEB", 6664 igrave: "\xEC", 6665 iacute: "\xED", 6666 icirc: "\xEE", 6667 iuml: "\xEF", 6668 eth: "\xF0", 6669 ntilde: "\xF1", 6670 ograve: "\xF2", 6671 oacute: "\xF3", 6672 ocirc: "\xF4", 6673 otilde: "\xF5", 6674 ouml: "\xF6", 6675 divide: "\xF7", 6676 oslash: "\xF8", 6677 ugrave: "\xF9", 6678 uacute: "\xFA", 6679 ucirc: "\xFB", 6680 uuml: "\xFC", 6681 yacute: "\xFD", 6682 thorn: "\xFE", 6683 yuml: "\xFF", 6684 OElig: "\u0152", 6685 oelig: "\u0153", 6686 Scaron: "\u0160", 6687 scaron: "\u0161", 6688 Yuml: "\u0178", 6689 fnof: "\u0192", 6690 circ: "\u02C6", 6691 tilde: "\u02DC", 6692 Alpha: "\u0391", 6693 Beta: "\u0392", 6694 Gamma: "\u0393", 6695 Delta: "\u0394", 6696 Epsilon: "\u0395", 6697 Zeta: "\u0396", 6698 Eta: "\u0397", 6699 Theta: "\u0398", 6700 Iota: "\u0399", 6701 Kappa: "\u039A", 6702 Lambda: "\u039B", 6703 Mu: "\u039C", 6704 Nu: "\u039D", 6705 Xi: "\u039E", 6706 Omicron: "\u039F", 6707 Pi: "\u03A0", 6708 Rho: "\u03A1", 6709 Sigma: "\u03A3", 6710 Tau: "\u03A4", 6711 Upsilon: "\u03A5", 6712 Phi: "\u03A6", 6713 Chi: "\u03A7", 6714 Psi: "\u03A8", 6715 Omega: "\u03A9", 6716 alpha: "\u03B1", 6717 beta: "\u03B2", 6718 gamma: "\u03B3", 6719 delta: "\u03B4", 6720 epsilon: "\u03B5", 6721 zeta: "\u03B6", 6722 eta: "\u03B7", 6723 theta: "\u03B8", 6724 iota: "\u03B9", 6725 kappa: "\u03BA", 6726 lambda: "\u03BB", 6727 mu: "\u03BC", 6728 nu: "\u03BD", 6729 xi: "\u03BE", 6730 omicron: "\u03BF", 6731 pi: "\u03C0", 6732 rho: "\u03C1", 6733 sigmaf: "\u03C2", 6734 sigma: "\u03C3", 6735 tau: "\u03C4", 6736 upsilon: "\u03C5", 6737 phi: "\u03C6", 6738 chi: "\u03C7", 6739 psi: "\u03C8", 6740 omega: "\u03C9", 6741 thetasym: "\u03D1", 6742 upsih: "\u03D2", 6743 piv: "\u03D6", 6744 ensp: "\u2002", 6745 emsp: "\u2003", 6746 thinsp: "\u2009", 6747 zwnj: "\u200C", 6748 zwj: "\u200D", 6749 lrm: "\u200E", 6750 rlm: "\u200F", 6751 ndash: "\u2013", 6752 mdash: "\u2014", 6753 lsquo: "\u2018", 6754 rsquo: "\u2019", 6755 sbquo: "\u201A", 6756 ldquo: "\u201C", 6757 rdquo: "\u201D", 6758 bdquo: "\u201E", 6759 dagger: "\u2020", 6760 Dagger: "\u2021", 6761 bull: "\u2022", 6762 hellip: "\u2026", 6763 permil: "\u2030", 6764 prime: "\u2032", 6765 Prime: "\u2033", 6766 lsaquo: "\u2039", 6767 rsaquo: "\u203A", 6768 oline: "\u203E", 6769 frasl: "\u2044", 6770 euro: "\u20AC", 6771 image: "\u2111", 6772 weierp: "\u2118", 6773 real: "\u211C", 6774 trade: "\u2122", 6775 alefsym: "\u2135", 6776 larr: "\u2190", 6777 uarr: "\u2191", 6778 rarr: "\u2192", 6779 darr: "\u2193", 6780 harr: "\u2194", 6781 crarr: "\u21B5", 6782 lArr: "\u21D0", 6783 uArr: "\u21D1", 6784 rArr: "\u21D2", 6785 dArr: "\u21D3", 6786 hArr: "\u21D4", 6787 forall: "\u2200", 6788 part: "\u2202", 6789 exist: "\u2203", 6790 empty: "\u2205", 6791 nabla: "\u2207", 6792 isin: "\u2208", 6793 notin: "\u2209", 6794 ni: "\u220B", 6795 prod: "\u220F", 6796 sum: "\u2211", 6797 minus: "\u2212", 6798 lowast: "\u2217", 6799 radic: "\u221A", 6800 prop: "\u221D", 6801 infin: "\u221E", 6802 ang: "\u2220", 6803 and: "\u2227", 6804 or: "\u2228", 6805 cap: "\u2229", 6806 cup: "\u222A", 6807 "int": "\u222B", 6808 there4: "\u2234", 6809 sim: "\u223C", 6810 cong: "\u2245", 6811 asymp: "\u2248", 6812 ne: "\u2260", 6813 equiv: "\u2261", 6814 le: "\u2264", 6815 ge: "\u2265", 6816 sub: "\u2282", 6817 sup: "\u2283", 6818 nsub: "\u2284", 6819 sube: "\u2286", 6820 supe: "\u2287", 6821 oplus: "\u2295", 6822 otimes: "\u2297", 6823 perp: "\u22A5", 6824 sdot: "\u22C5", 6825 lceil: "\u2308", 6826 rceil: "\u2309", 6827 lfloor: "\u230A", 6828 rfloor: "\u230B", 6829 lang: "\u2329", 6830 rang: "\u232A", 6831 loz: "\u25CA", 6832 spades: "\u2660", 6833 clubs: "\u2663", 6834 hearts: "\u2665", 6835 diams: "\u2666" 6836}; 6837 6838var HEX_NUMBER = /^[\da-fA-F]+$/; 6839var DECIMAL_NUMBER = /^\d+$/; 6840 6841types$1.j_oTag = new TokContext("<tag", false); 6842types$1.j_cTag = new TokContext("</tag", false); 6843types$1.j_expr = new TokContext("<tag>...</tag>", true, true); 6844 6845types.jsxName = new TokenType("jsxName"); 6846types.jsxText = new TokenType("jsxText", { beforeExpr: true }); 6847types.jsxTagStart = new TokenType("jsxTagStart", { startsExpr: true }); 6848types.jsxTagEnd = new TokenType("jsxTagEnd"); 6849 6850types.jsxTagStart.updateContext = function () { 6851 this.state.context.push(types$1.j_expr); // treat as beginning of JSX expression 6852 this.state.context.push(types$1.j_oTag); // start opening tag context 6853 this.state.exprAllowed = false; 6854}; 6855 6856types.jsxTagEnd.updateContext = function (prevType) { 6857 var out = this.state.context.pop(); 6858 if (out === types$1.j_oTag && prevType === types.slash || out === types$1.j_cTag) { 6859 this.state.context.pop(); 6860 this.state.exprAllowed = this.curContext() === types$1.j_expr; 6861 } else { 6862 this.state.exprAllowed = true; 6863 } 6864}; 6865 6866var pp$9 = Parser.prototype; 6867 6868// Reads inline JSX contents token. 6869 6870pp$9.jsxReadToken = function () { 6871 var out = ""; 6872 var chunkStart = this.state.pos; 6873 for (;;) { 6874 if (this.state.pos >= this.input.length) { 6875 this.raise(this.state.start, "Unterminated JSX contents"); 6876 } 6877 6878 var ch = this.input.charCodeAt(this.state.pos); 6879 6880 switch (ch) { 6881 case 60: // "<" 6882 case 123: 6883 // "{" 6884 if (this.state.pos === this.state.start) { 6885 if (ch === 60 && this.state.exprAllowed) { 6886 ++this.state.pos; 6887 return this.finishToken(types.jsxTagStart); 6888 } 6889 return this.getTokenFromCode(ch); 6890 } 6891 out += this.input.slice(chunkStart, this.state.pos); 6892 return this.finishToken(types.jsxText, out); 6893 6894 case 38: 6895 // "&" 6896 out += this.input.slice(chunkStart, this.state.pos); 6897 out += this.jsxReadEntity(); 6898 chunkStart = this.state.pos; 6899 break; 6900 6901 default: 6902 if (isNewLine(ch)) { 6903 out += this.input.slice(chunkStart, this.state.pos); 6904 out += this.jsxReadNewLine(true); 6905 chunkStart = this.state.pos; 6906 } else { 6907 ++this.state.pos; 6908 } 6909 } 6910 } 6911}; 6912 6913pp$9.jsxReadNewLine = function (normalizeCRLF) { 6914 var ch = this.input.charCodeAt(this.state.pos); 6915 var out = void 0; 6916 ++this.state.pos; 6917 if (ch === 13 && this.input.charCodeAt(this.state.pos) === 10) { 6918 ++this.state.pos; 6919 out = normalizeCRLF ? "\n" : "\r\n"; 6920 } else { 6921 out = String.fromCharCode(ch); 6922 } 6923 ++this.state.curLine; 6924 this.state.lineStart = this.state.pos; 6925 6926 return out; 6927}; 6928 6929pp$9.jsxReadString = function (quote) { 6930 var out = ""; 6931 var chunkStart = ++this.state.pos; 6932 for (;;) { 6933 if (this.state.pos >= this.input.length) { 6934 this.raise(this.state.start, "Unterminated string constant"); 6935 } 6936 6937 var ch = this.input.charCodeAt(this.state.pos); 6938 if (ch === quote) break; 6939 if (ch === 38) { 6940 // "&" 6941 out += this.input.slice(chunkStart, this.state.pos); 6942 out += this.jsxReadEntity(); 6943 chunkStart = this.state.pos; 6944 } else if (isNewLine(ch)) { 6945 out += this.input.slice(chunkStart, this.state.pos); 6946 out += this.jsxReadNewLine(false); 6947 chunkStart = this.state.pos; 6948 } else { 6949 ++this.state.pos; 6950 } 6951 } 6952 out += this.input.slice(chunkStart, this.state.pos++); 6953 return this.finishToken(types.string, out); 6954}; 6955 6956pp$9.jsxReadEntity = function () { 6957 var str = ""; 6958 var count = 0; 6959 var entity = void 0; 6960 var ch = this.input[this.state.pos]; 6961 6962 var startPos = ++this.state.pos; 6963 while (this.state.pos < this.input.length && count++ < 10) { 6964 ch = this.input[this.state.pos++]; 6965 if (ch === ";") { 6966 if (str[0] === "#") { 6967 if (str[1] === "x") { 6968 str = str.substr(2); 6969 if (HEX_NUMBER.test(str)) entity = fromCodePoint$1(parseInt(str, 16)); 6970 } else { 6971 str = str.substr(1); 6972 if (DECIMAL_NUMBER.test(str)) entity = fromCodePoint$1(parseInt(str, 10)); 6973 } 6974 } else { 6975 entity = XHTMLEntities[str]; 6976 } 6977 break; 6978 } 6979 str += ch; 6980 } 6981 if (!entity) { 6982 this.state.pos = startPos; 6983 return "&"; 6984 } 6985 return entity; 6986}; 6987 6988// Read a JSX identifier (valid tag or attribute name). 6989// 6990// Optimized version since JSX identifiers can"t contain 6991// escape characters and so can be read as single slice. 6992// Also assumes that first character was already checked 6993// by isIdentifierStart in readToken. 6994 6995pp$9.jsxReadWord = function () { 6996 var ch = void 0; 6997 var start = this.state.pos; 6998 do { 6999 ch = this.input.charCodeAt(++this.state.pos); 7000 } while (isIdentifierChar(ch) || ch === 45); // "-" 7001 return this.finishToken(types.jsxName, this.input.slice(start, this.state.pos)); 7002}; 7003 7004// Transforms JSX element name to string. 7005 7006function getQualifiedJSXName(object) { 7007 if (object.type === "JSXIdentifier") { 7008 return object.name; 7009 } 7010 7011 if (object.type === "JSXNamespacedName") { 7012 return object.namespace.name + ":" + object.name.name; 7013 } 7014 7015 if (object.type === "JSXMemberExpression") { 7016 return getQualifiedJSXName(object.object) + "." + getQualifiedJSXName(object.property); 7017 } 7018} 7019 7020// Parse next token as JSX identifier 7021 7022pp$9.jsxParseIdentifier = function () { 7023 var node = this.startNode(); 7024 if (this.match(types.jsxName)) { 7025 node.name = this.state.value; 7026 } else if (this.state.type.keyword) { 7027 node.name = this.state.type.keyword; 7028 } else { 7029 this.unexpected(); 7030 } 7031 this.next(); 7032 return this.finishNode(node, "JSXIdentifier"); 7033}; 7034 7035// Parse namespaced identifier. 7036 7037pp$9.jsxParseNamespacedName = function () { 7038 var startPos = this.state.start; 7039 var startLoc = this.state.startLoc; 7040 var name = this.jsxParseIdentifier(); 7041 if (!this.eat(types.colon)) return name; 7042 7043 var node = this.startNodeAt(startPos, startLoc); 7044 node.namespace = name; 7045 node.name = this.jsxParseIdentifier(); 7046 return this.finishNode(node, "JSXNamespacedName"); 7047}; 7048 7049// Parses element name in any form - namespaced, member 7050// or single identifier. 7051 7052pp$9.jsxParseElementName = function () { 7053 var startPos = this.state.start; 7054 var startLoc = this.state.startLoc; 7055 var node = this.jsxParseNamespacedName(); 7056 while (this.eat(types.dot)) { 7057 var newNode = this.startNodeAt(startPos, startLoc); 7058 newNode.object = node; 7059 newNode.property = this.jsxParseIdentifier(); 7060 node = this.finishNode(newNode, "JSXMemberExpression"); 7061 } 7062 return node; 7063}; 7064 7065// Parses any type of JSX attribute value. 7066 7067pp$9.jsxParseAttributeValue = function () { 7068 var node = void 0; 7069 switch (this.state.type) { 7070 case types.braceL: 7071 node = this.jsxParseExpressionContainer(); 7072 if (node.expression.type === "JSXEmptyExpression") { 7073 this.raise(node.start, "JSX attributes must only be assigned a non-empty expression"); 7074 } else { 7075 return node; 7076 } 7077 7078 case types.jsxTagStart: 7079 case types.string: 7080 node = this.parseExprAtom(); 7081 node.extra = null; 7082 return node; 7083 7084 default: 7085 this.raise(this.state.start, "JSX value should be either an expression or a quoted JSX text"); 7086 } 7087}; 7088 7089// JSXEmptyExpression is unique type since it doesn't actually parse anything, 7090// and so it should start at the end of last read token (left brace) and finish 7091// at the beginning of the next one (right brace). 7092 7093pp$9.jsxParseEmptyExpression = function () { 7094 var node = this.startNodeAt(this.state.lastTokEnd, this.state.lastTokEndLoc); 7095 return this.finishNodeAt(node, "JSXEmptyExpression", this.state.start, this.state.startLoc); 7096}; 7097 7098// Parse JSX spread child 7099 7100pp$9.jsxParseSpreadChild = function () { 7101 var node = this.startNode(); 7102 this.expect(types.braceL); 7103 this.expect(types.ellipsis); 7104 node.expression = this.parseExpression(); 7105 this.expect(types.braceR); 7106 7107 return this.finishNode(node, "JSXSpreadChild"); 7108}; 7109 7110// Parses JSX expression enclosed into curly brackets. 7111 7112 7113pp$9.jsxParseExpressionContainer = function () { 7114 var node = this.startNode(); 7115 this.next(); 7116 if (this.match(types.braceR)) { 7117 node.expression = this.jsxParseEmptyExpression(); 7118 } else { 7119 node.expression = this.parseExpression(); 7120 } 7121 this.expect(types.braceR); 7122 return this.finishNode(node, "JSXExpressionContainer"); 7123}; 7124 7125// Parses following JSX attribute name-value pair. 7126 7127pp$9.jsxParseAttribute = function () { 7128 var node = this.startNode(); 7129 if (this.eat(types.braceL)) { 7130 this.expect(types.ellipsis); 7131 node.argument = this.parseMaybeAssign(); 7132 this.expect(types.braceR); 7133 return this.finishNode(node, "JSXSpreadAttribute"); 7134 } 7135 node.name = this.jsxParseNamespacedName(); 7136 node.value = this.eat(types.eq) ? this.jsxParseAttributeValue() : null; 7137 return this.finishNode(node, "JSXAttribute"); 7138}; 7139 7140// Parses JSX opening tag starting after "<". 7141 7142pp$9.jsxParseOpeningElementAt = function (startPos, startLoc) { 7143 var node = this.startNodeAt(startPos, startLoc); 7144 node.attributes = []; 7145 node.name = this.jsxParseElementName(); 7146 while (!this.match(types.slash) && !this.match(types.jsxTagEnd)) { 7147 node.attributes.push(this.jsxParseAttribute()); 7148 } 7149 node.selfClosing = this.eat(types.slash); 7150 this.expect(types.jsxTagEnd); 7151 return this.finishNode(node, "JSXOpeningElement"); 7152}; 7153 7154// Parses JSX closing tag starting after "</". 7155 7156pp$9.jsxParseClosingElementAt = function (startPos, startLoc) { 7157 var node = this.startNodeAt(startPos, startLoc); 7158 node.name = this.jsxParseElementName(); 7159 this.expect(types.jsxTagEnd); 7160 return this.finishNode(node, "JSXClosingElement"); 7161}; 7162 7163// Parses entire JSX element, including it"s opening tag 7164// (starting after "<"), attributes, contents and closing tag. 7165 7166pp$9.jsxParseElementAt = function (startPos, startLoc) { 7167 var node = this.startNodeAt(startPos, startLoc); 7168 var children = []; 7169 var openingElement = this.jsxParseOpeningElementAt(startPos, startLoc); 7170 var closingElement = null; 7171 7172 if (!openingElement.selfClosing) { 7173 contents: for (;;) { 7174 switch (this.state.type) { 7175 case types.jsxTagStart: 7176 startPos = this.state.start;startLoc = this.state.startLoc; 7177 this.next(); 7178 if (this.eat(types.slash)) { 7179 closingElement = this.jsxParseClosingElementAt(startPos, startLoc); 7180 break contents; 7181 } 7182 children.push(this.jsxParseElementAt(startPos, startLoc)); 7183 break; 7184 7185 case types.jsxText: 7186 children.push(this.parseExprAtom()); 7187 break; 7188 7189 case types.braceL: 7190 if (this.lookahead().type === types.ellipsis) { 7191 children.push(this.jsxParseSpreadChild()); 7192 } else { 7193 children.push(this.jsxParseExpressionContainer()); 7194 } 7195 7196 break; 7197 7198 // istanbul ignore next - should never happen 7199 default: 7200 this.unexpected(); 7201 } 7202 } 7203 7204 if (getQualifiedJSXName(closingElement.name) !== getQualifiedJSXName(openingElement.name)) { 7205 this.raise(closingElement.start, "Expected corresponding JSX closing tag for <" + getQualifiedJSXName(openingElement.name) + ">"); 7206 } 7207 } 7208 7209 node.openingElement = openingElement; 7210 node.closingElement = closingElement; 7211 node.children = children; 7212 if (this.match(types.relational) && this.state.value === "<") { 7213 this.raise(this.state.start, "Adjacent JSX elements must be wrapped in an enclosing tag"); 7214 } 7215 return this.finishNode(node, "JSXElement"); 7216}; 7217 7218// Parses entire JSX element from current position. 7219 7220pp$9.jsxParseElement = function () { 7221 var startPos = this.state.start; 7222 var startLoc = this.state.startLoc; 7223 this.next(); 7224 return this.jsxParseElementAt(startPos, startLoc); 7225}; 7226 7227var jsxPlugin = function (instance) { 7228 instance.extend("parseExprAtom", function (inner) { 7229 return function (refShortHandDefaultPos) { 7230 if (this.match(types.jsxText)) { 7231 var node = this.parseLiteral(this.state.value, "JSXText"); 7232 // https://github.com/babel/babel/issues/2078 7233 node.extra = null; 7234 return node; 7235 } else if (this.match(types.jsxTagStart)) { 7236 return this.jsxParseElement(); 7237 } else { 7238 return inner.call(this, refShortHandDefaultPos); 7239 } 7240 }; 7241 }); 7242 7243 instance.extend("readToken", function (inner) { 7244 return function (code) { 7245 if (this.state.inPropertyName) return inner.call(this, code); 7246 7247 var context = this.curContext(); 7248 7249 if (context === types$1.j_expr) { 7250 return this.jsxReadToken(); 7251 } 7252 7253 if (context === types$1.j_oTag || context === types$1.j_cTag) { 7254 if (isIdentifierStart(code)) { 7255 return this.jsxReadWord(); 7256 } 7257 7258 if (code === 62) { 7259 ++this.state.pos; 7260 return this.finishToken(types.jsxTagEnd); 7261 } 7262 7263 if ((code === 34 || code === 39) && context === types$1.j_oTag) { 7264 return this.jsxReadString(code); 7265 } 7266 } 7267 7268 if (code === 60 && this.state.exprAllowed) { 7269 ++this.state.pos; 7270 return this.finishToken(types.jsxTagStart); 7271 } 7272 7273 return inner.call(this, code); 7274 }; 7275 }); 7276 7277 instance.extend("updateContext", function (inner) { 7278 return function (prevType) { 7279 if (this.match(types.braceL)) { 7280 var curContext = this.curContext(); 7281 if (curContext === types$1.j_oTag) { 7282 this.state.context.push(types$1.braceExpression); 7283 } else if (curContext === types$1.j_expr) { 7284 this.state.context.push(types$1.templateQuasi); 7285 } else { 7286 inner.call(this, prevType); 7287 } 7288 this.state.exprAllowed = true; 7289 } else if (this.match(types.slash) && prevType === types.jsxTagStart) { 7290 this.state.context.length -= 2; // do not consider JSX expr -> JSX open tag -> ... anymore 7291 this.state.context.push(types$1.j_cTag); // reconsider as closing tag context 7292 this.state.exprAllowed = false; 7293 } else { 7294 return inner.call(this, prevType); 7295 } 7296 }; 7297 }); 7298}; 7299 7300plugins.estree = estreePlugin; 7301plugins.flow = flowPlugin; 7302plugins.jsx = jsxPlugin; 7303 7304function parse(input, options) { 7305 return new Parser(options, input).parse(); 7306} 7307 7308function parseExpression(input, options) { 7309 var parser = new Parser(options, input); 7310 if (parser.options.strictMode) { 7311 parser.state.strict = true; 7312 } 7313 return parser.getExpression(); 7314} 7315 7316exports.parse = parse; 7317exports.parseExpression = parseExpression; 7318exports.tokTypes = types; 7319