UNPKG

orionsoft-react-scripts

Version:

Orionsoft Configuration and scripts for Create React App.

1,322 lines (1,082 loc) 204 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); /* eslint max-len: 0 */ // This is a trick taken from Esprima. It turns out that, on // non-Chrome browsers, to check whether a string is in a set, a // predicate containing a big ugly `switch` statement is faster than // a regular expression, and on Chrome the two are about on par. // This function uses `eval` (non-lexical) to produce such a // predicate from a space-separated string of words. // // It starts by sorting the words by length. function makePredicate(words) { words = words.split(" "); return function (str) { return words.indexOf(str) >= 0; }; } // Reserved word lists for various dialects of the language var reservedWords = { 6: makePredicate("enum await"), strict: makePredicate("implements interface let package private protected public static yield"), strictBind: makePredicate("eval arguments") }; // And the keywords var isKeyword$1 = 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"); // ## Character categories // Big ugly regular expressions that match characters in the // whitespace, identifier, and identifier-start categories. These // are only applied when a character is found to actually have a // code point above 128. // Generated by `bin/generate-identifier-regex.js`. var nonASCIIidentifierStartChars = "\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B4\u08B6-\u08BD\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309B-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FD5\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC"; var nonASCIIidentifierChars = "\u200C\u200D\xB7\u0300-\u036F\u0387\u0483-\u0487\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u0610-\u061A\u064B-\u0669\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED\u06F0-\u06F9\u0711\u0730-\u074A\u07A6-\u07B0\u07C0-\u07C9\u07EB-\u07F3\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08D4-\u08E1\u08E3-\u0903\u093A-\u093C\u093E-\u094F\u0951-\u0957\u0962\u0963\u0966-\u096F\u0981-\u0983\u09BC\u09BE-\u09C4\u09C7\u09C8\u09CB-\u09CD\u09D7\u09E2\u09E3\u09E6-\u09EF\u0A01-\u0A03\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A66-\u0A71\u0A75\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AE2\u0AE3\u0AE6-\u0AEF\u0B01-\u0B03\u0B3C\u0B3E-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B62\u0B63\u0B66-\u0B6F\u0B82\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0CBC\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CE2\u0CE3\u0CE6-\u0CEF\u0D01-\u0D03\u0D3E-\u0D44\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D62\u0D63\u0D66-\u0D6F\u0D82\u0D83\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0E50-\u0E59\u0EB1\u0EB4-\u0EB9\u0EBB\u0EBC\u0EC8-\u0ECD\u0ED0-\u0ED9\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F84\u0F86\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u102B-\u103E\u1040-\u1049\u1056-\u1059\u105E-\u1060\u1062-\u1064\u1067-\u106D\u1071-\u1074\u1082-\u108D\u108F-\u109D\u135D-\u135F\u1369-\u1371\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17B4-\u17D3\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u18A9\u1920-\u192B\u1930-\u193B\u1946-\u194F\u19D0-\u19DA\u1A17-\u1A1B\u1A55-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AB0-\u1ABD\u1B00-\u1B04\u1B34-\u1B44\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1B82\u1BA1-\u1BAD\u1BB0-\u1BB9\u1BE6-\u1BF3\u1C24-\u1C37\u1C40-\u1C49\u1C50-\u1C59\u1CD0-\u1CD2\u1CD4-\u1CE8\u1CED\u1CF2-\u1CF4\u1CF8\u1CF9\u1DC0-\u1DF5\u1DFB-\u1DFF\u203F\u2040\u2054\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302F\u3099\u309A\uA620-\uA629\uA66F\uA674-\uA67D\uA69E\uA69F\uA6F0\uA6F1\uA802\uA806\uA80B\uA823-\uA827\uA880\uA881\uA8B4-\uA8C5\uA8D0-\uA8D9\uA8E0-\uA8F1\uA900-\uA909\uA926-\uA92D\uA947-\uA953\uA980-\uA983\uA9B3-\uA9C0\uA9D0-\uA9D9\uA9E5\uA9F0-\uA9F9\uAA29-\uAA36\uAA43\uAA4C\uAA4D\uAA50-\uAA59\uAA7B-\uAA7D\uAAB0\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uAAEB-\uAAEF\uAAF5\uAAF6\uABE3-\uABEA\uABEC\uABED\uABF0-\uABF9\uFB1E\uFE00-\uFE0F\uFE20-\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFF10-\uFF19\uFF3F"; var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]"); var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]"); nonASCIIidentifierStartChars = nonASCIIidentifierChars = null; // These are a run-length and offset encoded representation of the // >0xffff code points that are a valid part of identifiers. The // offset starts at 0x10000, and each pair of numbers represents an // offset to the next range, and then a size of the range. They were // generated by `bin/generate-identifier-regex.js`. var astralIdentifierStartCodes = [0, 11, 2, 25, 2, 18, 2, 1, 2, 14, 3, 13, 35, 122, 70, 52, 268, 28, 4, 48, 48, 31, 17, 26, 6, 37, 11, 29, 3, 35, 5, 7, 2, 4, 43, 157, 19, 35, 5, 35, 5, 39, 9, 51, 157, 310, 10, 21, 11, 7, 153, 5, 3, 0, 2, 43, 2, 1, 4, 0, 3, 22, 11, 22, 10, 30, 66, 18, 2, 1, 11, 21, 11, 25, 71, 55, 7, 1, 65, 0, 16, 3, 2, 2, 2, 26, 45, 28, 4, 28, 36, 7, 2, 27, 28, 53, 11, 21, 11, 18, 14, 17, 111, 72, 56, 50, 14, 50, 785, 52, 76, 44, 33, 24, 27, 35, 42, 34, 4, 0, 13, 47, 15, 3, 22, 0, 2, 0, 36, 17, 2, 24, 85, 6, 2, 0, 2, 3, 2, 14, 2, 9, 8, 46, 39, 7, 3, 1, 3, 21, 2, 6, 2, 1, 2, 4, 4, 0, 19, 0, 13, 4, 159, 52, 19, 3, 54, 47, 21, 1, 2, 0, 185, 46, 42, 3, 37, 47, 21, 0, 60, 42, 86, 25, 391, 63, 32, 0, 449, 56, 264, 8, 2, 36, 18, 0, 50, 29, 881, 921, 103, 110, 18, 195, 2749, 1070, 4050, 582, 8634, 568, 8, 30, 114, 29, 19, 47, 17, 3, 32, 20, 6, 18, 881, 68, 12, 0, 67, 12, 65, 0, 32, 6124, 20, 754, 9486, 1, 3071, 106, 6, 12, 4, 8, 8, 9, 5991, 84, 2, 70, 2, 1, 3, 0, 3, 1, 3, 3, 2, 11, 2, 0, 2, 6, 2, 64, 2, 3, 3, 7, 2, 6, 2, 27, 2, 3, 2, 4, 2, 0, 4, 6, 2, 339, 3, 24, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 7, 4149, 196, 60, 67, 1213, 3, 2, 26, 2, 1, 2, 0, 3, 0, 2, 9, 2, 3, 2, 0, 2, 0, 7, 0, 5, 0, 2, 0, 2, 0, 2, 2, 2, 1, 2, 0, 3, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 3, 3, 2, 6, 2, 3, 2, 3, 2, 0, 2, 9, 2, 16, 6, 2, 2, 4, 2, 16, 4421, 42710, 42, 4148, 12, 221, 3, 5761, 10591, 541]; var astralIdentifierCodes = [509, 0, 227, 0, 150, 4, 294, 9, 1368, 2, 2, 1, 6, 3, 41, 2, 5, 0, 166, 1, 1306, 2, 54, 14, 32, 9, 16, 3, 46, 10, 54, 9, 7, 2, 37, 13, 2, 9, 52, 0, 13, 2, 49, 13, 10, 2, 4, 9, 83, 11, 7, 0, 161, 11, 6, 9, 7, 3, 57, 0, 2, 6, 3, 1, 3, 2, 10, 0, 11, 1, 3, 6, 4, 4, 193, 17, 10, 9, 87, 19, 13, 9, 214, 6, 3, 8, 28, 1, 83, 16, 16, 9, 82, 12, 9, 9, 84, 14, 5, 9, 423, 9, 838, 7, 2, 7, 17, 9, 57, 21, 2, 13, 19882, 9, 135, 4, 60, 6, 26, 9, 1016, 45, 17, 3, 19723, 1, 5319, 4, 4, 5, 9, 7, 3, 6, 31, 3, 149, 2, 1418, 49, 513, 54, 5, 49, 9, 0, 15, 0, 23, 4, 2, 14, 1361, 6, 2, 16, 3, 6, 2, 1, 2, 4, 2214, 6, 110, 6, 6, 9, 792487, 239]; // This has a complexity linear to the value of the code. The // assumption is that looking up astral identifier characters is // rare. function isInAstralSet(code, set) { var pos = 0x10000; for (var i = 0; i < set.length; i += 2) { pos += set[i]; if (pos > code) return false; pos += set[i + 1]; if (pos >= code) return true; } } // Test whether a given character code starts an identifier. function isIdentifierStart(code) { if (code < 65) return code === 36; if (code < 91) return true; if (code < 97) return code === 95; if (code < 123) return true; if (code <= 0xffff) return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)); return isInAstralSet(code, astralIdentifierStartCodes); } // Test whether a given character is part of an identifier. function isIdentifierChar(code) { if (code < 48) return code === 36; if (code < 58) return true; if (code < 65) return false; if (code < 91) return true; if (code < 97) return code === 95; if (code < 123) return true; if (code <= 0xffff) return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)); return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes); } // A second optional argument can be given to further configure var defaultOptions = { // Source type ("script" or "module") for different semantics sourceType: "script", // Source filename. sourceFilename: undefined, // When enabled, a return at the top level is not considered an // error. allowReturnOutsideFunction: false, // When enabled, import/export statements are not constrained to // appearing at the top of the program. allowImportExportEverywhere: false, // TODO allowSuperOutsideMethod: false, // An array of plugins to enable plugins: [], // TODO strictMode: null }; // Interpret and default an options object function getOptions(opts) { var options = {}; for (var key in defaultOptions) { options[key] = opts && key in opts ? opts[key] : defaultOptions[key]; } return options; } function _classCallCheck$2(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } // ## Token types // The assignment of fine-grained, information-carrying type objects // allows the tokenizer to store the information it has about a // token in a way that is very cheap for the parser to look up. // All token type variables start with an underscore, to make them // easy to recognize. // The `beforeExpr` property is used to disambiguate between regular // expressions and divisions. It is set on all token types that can // be followed by an expression (thus, a slash after them would be a // regular expression). // // `isLoop` marks a keyword as starting a loop, which is important // to know when parsing a label, in order to allow or disallow // continue jumps to that label. var TokenType = function TokenType(label) { var conf = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; _classCallCheck$2(this, TokenType); this.label = label; this.keyword = conf.keyword; this.beforeExpr = !!conf.beforeExpr; this.startsExpr = !!conf.startsExpr; this.rightAssociative = !!conf.rightAssociative; this.isLoop = !!conf.isLoop; this.isAssign = !!conf.isAssign; this.prefix = !!conf.prefix; this.postfix = !!conf.postfix; this.binop = conf.binop || null; this.updateContext = null; }; function binop(name, prec) { return new TokenType(name, { beforeExpr: true, binop: prec }); } var beforeExpr = { beforeExpr: true }; var startsExpr = { startsExpr: true }; var types = { num: new TokenType("num", startsExpr), regexp: new TokenType("regexp", startsExpr), string: new TokenType("string", startsExpr), name: new TokenType("name", startsExpr), eof: new TokenType("eof"), // Punctuation token types. bracketL: new TokenType("[", { beforeExpr: true, startsExpr: true }), bracketR: new TokenType("]"), braceL: new TokenType("{", { beforeExpr: true, startsExpr: true }), braceBarL: new TokenType("{|", { beforeExpr: true, startsExpr: true }), braceR: new TokenType("}"), braceBarR: new TokenType("|}"), parenL: new TokenType("(", { beforeExpr: true, startsExpr: true }), parenR: new TokenType(")"), comma: new TokenType(",", beforeExpr), semi: new TokenType(";", beforeExpr), colon: new TokenType(":", beforeExpr), doubleColon: new TokenType("::", beforeExpr), dot: new TokenType("."), question: new TokenType("?", beforeExpr), arrow: new TokenType("=>", beforeExpr), template: new TokenType("template"), ellipsis: new TokenType("...", beforeExpr), backQuote: new TokenType("`", startsExpr), dollarBraceL: new TokenType("${", { beforeExpr: true, startsExpr: true }), at: new TokenType("@"), // Operators. These carry several kinds of properties to help the // parser use them properly (the presence of these properties is // what categorizes them as operators). // // `binop`, when present, specifies that this operator is a binary // operator, and will refer to its precedence. // // `prefix` and `postfix` mark the operator as a prefix or postfix // unary operator. // // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as // binary operators with a very low precedence, that should result // in AssignmentExpression nodes. eq: new TokenType("=", { beforeExpr: true, isAssign: true }), assign: new TokenType("_=", { beforeExpr: true, isAssign: true }), incDec: new TokenType("++/--", { prefix: true, postfix: true, startsExpr: true }), prefix: new TokenType("prefix", { beforeExpr: true, prefix: true, startsExpr: true }), logicalOR: binop("||", 1), logicalAND: binop("&&", 2), bitwiseOR: binop("|", 3), bitwiseXOR: binop("^", 4), bitwiseAND: binop("&", 5), equality: binop("==/!=", 6), relational: binop("</>", 7), bitShift: binop("<</>>", 8), plusMin: new TokenType("+/-", { beforeExpr: true, binop: 9, prefix: true, startsExpr: true }), modulo: binop("%", 10), star: binop("*", 10), slash: binop("/", 10), exponent: new TokenType("**", { beforeExpr: true, binop: 11, rightAssociative: true }) }; // Map keyword names to token types. var keywords = {}; // Succinct definitions of keyword token types function kw(name) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; options.keyword = name; keywords[name] = types["_" + name] = new TokenType(name, options); } kw("break"); kw("case", beforeExpr); kw("catch"); kw("continue"); kw("debugger"); kw("default", beforeExpr); kw("do", { isLoop: true, beforeExpr: true }); kw("else", beforeExpr); kw("finally"); kw("for", { isLoop: true }); kw("function", startsExpr); kw("if"); kw("return", beforeExpr); kw("switch"); kw("throw", beforeExpr); kw("try"); kw("var"); kw("let"); kw("const"); kw("while", { isLoop: true }); kw("with"); kw("new", { beforeExpr: true, startsExpr: true }); kw("this", startsExpr); kw("super", startsExpr); kw("class"); kw("extends", beforeExpr); kw("export"); kw("import"); kw("yield", { beforeExpr: true, startsExpr: true }); kw("null", startsExpr); kw("true", startsExpr); kw("false", startsExpr); kw("in", { beforeExpr: true, binop: 7 }); kw("instanceof", { beforeExpr: true, binop: 7 }); kw("typeof", { beforeExpr: true, prefix: true, startsExpr: true }); kw("void", { beforeExpr: true, prefix: true, startsExpr: true }); kw("delete", { beforeExpr: true, prefix: true, startsExpr: true }); // Matches a whole line break (where CRLF is considered a single // line break). Used to count lines. var lineBreak = /\r\n?|\n|\u2028|\u2029/; var lineBreakG = new RegExp(lineBreak.source, "g"); function isNewLine(code) { return code === 10 || code === 13 || code === 0x2028 || code === 0x2029; } var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/; function _classCallCheck$3(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } // The algorithm used to determine whether a regexp can appear at a // given point in the program is loosely based on sweet.js' approach. // See https://github.com/mozilla/sweet.js/wiki/design var TokContext = function TokContext(token, isExpr, preserveSpace, override) { _classCallCheck$3(this, TokContext); this.token = token; this.isExpr = !!isExpr; this.preserveSpace = !!preserveSpace; this.override = override; }; var types$1 = { braceStatement: new TokContext("{", false), braceExpression: new TokContext("{", true), templateQuasi: new TokContext("${", true), parenStatement: new TokContext("(", false), parenExpression: new TokContext("(", true), template: new TokContext("`", true, true, function (p) { return p.readTmplToken(); }), functionExpression: new TokContext("function", true) }; // Token-specific context update code types.parenR.updateContext = types.braceR.updateContext = function () { if (this.state.context.length === 1) { this.state.exprAllowed = true; return; } var out = this.state.context.pop(); if (out === types$1.braceStatement && this.curContext() === types$1.functionExpression) { this.state.context.pop(); this.state.exprAllowed = false; } else if (out === types$1.templateQuasi) { this.state.exprAllowed = true; } else { this.state.exprAllowed = !out.isExpr; } }; types.name.updateContext = function (prevType) { this.state.exprAllowed = false; if (prevType === types._let || prevType === types._const || prevType === types._var) { if (lineBreak.test(this.input.slice(this.state.end))) { this.state.exprAllowed = true; } } }; types.braceL.updateContext = function (prevType) { this.state.context.push(this.braceIsBlock(prevType) ? types$1.braceStatement : types$1.braceExpression); this.state.exprAllowed = true; }; types.dollarBraceL.updateContext = function () { this.state.context.push(types$1.templateQuasi); this.state.exprAllowed = true; }; types.parenL.updateContext = function (prevType) { var statementParens = prevType === types._if || prevType === types._for || prevType === types._with || prevType === types._while; this.state.context.push(statementParens ? types$1.parenStatement : types$1.parenExpression); this.state.exprAllowed = true; }; types.incDec.updateContext = function () { // tokExprAllowed stays unchanged }; types._function.updateContext = function () { if (this.curContext() !== types$1.braceStatement) { this.state.context.push(types$1.functionExpression); } this.state.exprAllowed = false; }; types.backQuote.updateContext = function () { if (this.curContext() === types$1.template) { this.state.context.pop(); } else { this.state.context.push(types$1.template); } this.state.exprAllowed = false; }; function _classCallCheck$4(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } // These are used when `options.locations` is on, for the // `startLoc` and `endLoc` properties. var Position = function Position(line, col) { _classCallCheck$4(this, Position); this.line = line; this.column = col; }; var SourceLocation = function SourceLocation(start, end) { _classCallCheck$4(this, SourceLocation); this.start = start; this.end = end; }; // The `getLineInfo` function is mostly useful when the // `locations` option is off (for performance reasons) and you // want to find the line/column position for a given character // offset. `input` should be the code string that the offset refers // into. function getLineInfo(input, offset) { for (var line = 1, cur = 0;;) { lineBreakG.lastIndex = cur; var match = lineBreakG.exec(input); if (match && match.index < offset) { ++line; cur = match.index + match[0].length; } else { return new Position(line, offset - cur); } } } function _classCallCheck$5(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var State = function () { function State() { _classCallCheck$5(this, State); } State.prototype.init = function init(options, input) { this.strict = options.strictMode === false ? false : options.sourceType === "module"; this.input = input; this.potentialArrowAt = -1; this.inMethod = this.inFunction = this.inGenerator = this.inAsync = this.inType = false; this.labels = []; this.decorators = []; this.tokens = []; this.comments = []; this.trailingComments = []; this.leadingComments = []; this.commentStack = []; this.pos = this.lineStart = 0; this.curLine = 1; this.type = types.eof; this.value = null; this.start = this.end = this.pos; this.startLoc = this.endLoc = this.curPosition(); this.lastTokEndLoc = this.lastTokStartLoc = null; this.lastTokStart = this.lastTokEnd = this.pos; this.context = [types$1.braceStatement]; this.exprAllowed = true; this.containsEsc = this.containsOctal = false; this.octalPosition = null; this.exportedIdentifiers = []; return this; }; // TODO // TODO // Used to signify the start of a potential arrow function // Flags to track whether we are in a function, a generator. // Labels in scope. // Leading decorators. // Token store. // Comment store. // Comment attachment store // The current position of the tokenizer in the input. // Properties of the current token: // Its type // For tokens that include more information than their type, the value // Its start and end offset // And, if locations are used, the {line, column} object // corresponding to those offsets // Position information for the previous token // The context stack is used to superficially track syntactic // context to predict whether a regular expression is allowed in a // given position. // Used to signal to callers of `readWord1` whether the word // contained any escape sequences. This is needed because words with // escape sequences must not be interpreted as keywords. // TODO // Names of exports store. `default` is stored as a name for both // `export default foo;` and `export { foo as default };`. State.prototype.curPosition = function curPosition() { return new Position(this.curLine, this.pos - this.lineStart); }; State.prototype.clone = function clone(skipArrays) { var state = new State(); for (var key in this) { var val = this[key]; if ((!skipArrays || key === "context") && Array.isArray(val)) { val = val.slice(); } state[key] = val; } return state; }; return State; }(); function _classCallCheck$1(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /* eslint indent: 0 */ // Object type used to represent tokens. Note that normally, tokens // simply exist as properties on the parser object. This is only // used for the onToken callback and the external tokenizer. var Token = function Token(state) { _classCallCheck$1(this, Token); this.type = state.type; this.value = state.value; this.start = state.start; this.end = state.end; this.loc = new SourceLocation(state.startLoc, state.endLoc); }; // ## Tokenizer function codePointToString(code) { // UTF-16 Decoding if (code <= 0xFFFF) { return String.fromCharCode(code); } else { return String.fromCharCode((code - 0x10000 >> 10) + 0xD800, (code - 0x10000 & 1023) + 0xDC00); } } var Tokenizer = function () { function Tokenizer(options, input) { _classCallCheck$1(this, Tokenizer); this.state = new State(); this.state.init(options, input); } // Move to the next token Tokenizer.prototype.next = function next() { if (!this.isLookahead) { this.state.tokens.push(new Token(this.state)); } this.state.lastTokEnd = this.state.end; this.state.lastTokStart = this.state.start; this.state.lastTokEndLoc = this.state.endLoc; this.state.lastTokStartLoc = this.state.startLoc; this.nextToken(); }; // TODO Tokenizer.prototype.eat = function eat(type) { if (this.match(type)) { this.next(); return true; } else { return false; } }; // TODO Tokenizer.prototype.match = function match(type) { return this.state.type === type; }; // TODO Tokenizer.prototype.isKeyword = function isKeyword(word) { return isKeyword$1(word); }; // TODO Tokenizer.prototype.lookahead = function lookahead() { var old = this.state; this.state = old.clone(true); this.isLookahead = true; this.next(); this.isLookahead = false; var curr = this.state.clone(true); this.state = old; return curr; }; // Toggle strict mode. Re-reads the next number or string to please // pedantic tests (`"use strict"; 010;` should fail). Tokenizer.prototype.setStrict = function setStrict(strict) { this.state.strict = strict; if (!this.match(types.num) && !this.match(types.string)) return; this.state.pos = this.state.start; while (this.state.pos < this.state.lineStart) { this.state.lineStart = this.input.lastIndexOf("\n", this.state.lineStart - 2) + 1; --this.state.curLine; } this.nextToken(); }; Tokenizer.prototype.curContext = function curContext() { return this.state.context[this.state.context.length - 1]; }; // Read a single token, updating the parser object's token-related // properties. Tokenizer.prototype.nextToken = function nextToken() { var curContext = this.curContext(); if (!curContext || !curContext.preserveSpace) this.skipSpace(); this.state.containsOctal = false; this.state.octalPosition = null; this.state.start = this.state.pos; this.state.startLoc = this.state.curPosition(); if (this.state.pos >= this.input.length) return this.finishToken(types.eof); if (curContext.override) { return curContext.override(this); } else { return this.readToken(this.fullCharCodeAtPos()); } }; Tokenizer.prototype.readToken = function readToken(code) { // Identifier or keyword. '\uXXXX' sequences are allowed in // identifiers, so '\' also dispatches to that. if (isIdentifierStart(code) || code === 92 /* '\' */) { return this.readWord(); } else { return this.getTokenFromCode(code); } }; Tokenizer.prototype.fullCharCodeAtPos = function fullCharCodeAtPos() { var code = this.input.charCodeAt(this.state.pos); if (code <= 0xd7ff || code >= 0xe000) return code; var next = this.input.charCodeAt(this.state.pos + 1); return (code << 10) + next - 0x35fdc00; }; Tokenizer.prototype.pushComment = function pushComment(block, text, start, end, startLoc, endLoc) { var comment = { type: block ? "CommentBlock" : "CommentLine", value: text, start: start, end: end, loc: new SourceLocation(startLoc, endLoc) }; if (!this.isLookahead) { this.state.tokens.push(comment); this.state.comments.push(comment); this.addComment(comment); } }; Tokenizer.prototype.skipBlockComment = function skipBlockComment() { var startLoc = this.state.curPosition(); var start = this.state.pos, end = this.input.indexOf("*/", this.state.pos += 2); if (end === -1) this.raise(this.state.pos - 2, "Unterminated comment"); this.state.pos = end + 2; lineBreakG.lastIndex = start; var match = void 0; while ((match = lineBreakG.exec(this.input)) && match.index < this.state.pos) { ++this.state.curLine; this.state.lineStart = match.index + match[0].length; } this.pushComment(true, this.input.slice(start + 2, end), start, this.state.pos, startLoc, this.state.curPosition()); }; Tokenizer.prototype.skipLineComment = function skipLineComment(startSkip) { var start = this.state.pos; var startLoc = this.state.curPosition(); var ch = this.input.charCodeAt(this.state.pos += startSkip); while (this.state.pos < this.input.length && ch !== 10 && ch !== 13 && ch !== 8232 && ch !== 8233) { ++this.state.pos; ch = this.input.charCodeAt(this.state.pos); } this.pushComment(false, this.input.slice(start + startSkip, this.state.pos), start, this.state.pos, startLoc, this.state.curPosition()); }; // Called at the start of the parse and after every token. Skips // whitespace and comments, and. Tokenizer.prototype.skipSpace = function skipSpace() { loop: while (this.state.pos < this.input.length) { var ch = this.input.charCodeAt(this.state.pos); switch (ch) { case 32:case 160: // ' ' ++this.state.pos; break; case 13: if (this.input.charCodeAt(this.state.pos + 1) === 10) { ++this.state.pos; } case 10:case 8232:case 8233: ++this.state.pos; ++this.state.curLine; this.state.lineStart = this.state.pos; break; case 47: // '/' switch (this.input.charCodeAt(this.state.pos + 1)) { case 42: // '*' this.skipBlockComment(); break; case 47: this.skipLineComment(2); break; default: break loop; } break; default: if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) { ++this.state.pos; } else { break loop; } } } }; // Called at the end of every token. Sets `end`, `val`, and // maintains `context` and `exprAllowed`, and skips the space after // the token, so that the next one's `start` will point at the // right position. Tokenizer.prototype.finishToken = function finishToken(type, val) { this.state.end = this.state.pos; this.state.endLoc = this.state.curPosition(); var prevType = this.state.type; this.state.type = type; this.state.value = val; this.updateContext(prevType); }; // ### Token reading // This is the function that is called to fetch the next token. It // is somewhat obscure, because it works in character codes rather // than characters, and because operator parsing has been inlined // into it. // // All in the name of speed. // Tokenizer.prototype.readToken_dot = function readToken_dot() { var next = this.input.charCodeAt(this.state.pos + 1); if (next >= 48 && next <= 57) { return this.readNumber(true); } var next2 = this.input.charCodeAt(this.state.pos + 2); if (next === 46 && next2 === 46) { // 46 = dot '.' this.state.pos += 3; return this.finishToken(types.ellipsis); } else { ++this.state.pos; return this.finishToken(types.dot); } }; Tokenizer.prototype.readToken_slash = function readToken_slash() { // '/' if (this.state.exprAllowed) { ++this.state.pos; return this.readRegexp(); } var next = this.input.charCodeAt(this.state.pos + 1); if (next === 61) { return this.finishOp(types.assign, 2); } else { return this.finishOp(types.slash, 1); } }; Tokenizer.prototype.readToken_mult_modulo = function readToken_mult_modulo(code) { // '%*' var type = code === 42 ? types.star : types.modulo; var width = 1; var next = this.input.charCodeAt(this.state.pos + 1); if (next === 42) { // '*' width++; next = this.input.charCodeAt(this.state.pos + 2); type = types.exponent; } if (next === 61) { width++; type = types.assign; } return this.finishOp(type, width); }; Tokenizer.prototype.readToken_pipe_amp = function readToken_pipe_amp(code) { // '|&' var next = this.input.charCodeAt(this.state.pos + 1); if (next === code) return this.finishOp(code === 124 ? types.logicalOR : types.logicalAND, 2); if (next === 61) return this.finishOp(types.assign, 2); if (code === 124 && next === 125 && this.hasPlugin("flow")) return this.finishOp(types.braceBarR, 2); return this.finishOp(code === 124 ? types.bitwiseOR : types.bitwiseAND, 1); }; Tokenizer.prototype.readToken_caret = function readToken_caret() { // '^' var next = this.input.charCodeAt(this.state.pos + 1); if (next === 61) { return this.finishOp(types.assign, 2); } else { return this.finishOp(types.bitwiseXOR, 1); } }; Tokenizer.prototype.readToken_plus_min = function readToken_plus_min(code) { // '+-' var next = this.input.charCodeAt(this.state.pos + 1); if (next === code) { if (next === 45 && this.input.charCodeAt(this.state.pos + 2) === 62 && lineBreak.test(this.input.slice(this.state.lastTokEnd, this.state.pos))) { // A `-->` line comment this.skipLineComment(3); this.skipSpace(); return this.nextToken(); } return this.finishOp(types.incDec, 2); } if (next === 61) { return this.finishOp(types.assign, 2); } else { return this.finishOp(types.plusMin, 1); } }; Tokenizer.prototype.readToken_lt_gt = function readToken_lt_gt(code) { // '<>' var next = this.input.charCodeAt(this.state.pos + 1); var size = 1; if (next === code) { size = code === 62 && this.input.charCodeAt(this.state.pos + 2) === 62 ? 3 : 2; if (this.input.charCodeAt(this.state.pos + size) === 61) return this.finishOp(types.assign, size + 1); return this.finishOp(types.bitShift, size); } if (next === 33 && code === 60 && this.input.charCodeAt(this.state.pos + 2) === 45 && this.input.charCodeAt(this.state.pos + 3) === 45) { if (this.inModule) this.unexpected(); // `<!--`, an XML-style comment that should be interpreted as a line comment this.skipLineComment(4); this.skipSpace(); return this.nextToken(); } if (next === 61) { // <= | >= size = 2; } return this.finishOp(types.relational, size); }; Tokenizer.prototype.readToken_eq_excl = function readToken_eq_excl(code) { // '=!' var next = this.input.charCodeAt(this.state.pos + 1); if (next === 61) return this.finishOp(types.equality, this.input.charCodeAt(this.state.pos + 2) === 61 ? 3 : 2); if (code === 61 && next === 62) { // '=>' this.state.pos += 2; return this.finishToken(types.arrow); } return this.finishOp(code === 61 ? types.eq : types.prefix, 1); }; Tokenizer.prototype.getTokenFromCode = function getTokenFromCode(code) { switch (code) { // The interpretation of a dot depends on whether it is followed // by a digit or another two dots. case 46: // '.' return this.readToken_dot(); // Punctuation tokens. case 40: ++this.state.pos;return this.finishToken(types.parenL); case 41: ++this.state.pos;return this.finishToken(types.parenR); case 59: ++this.state.pos;return this.finishToken(types.semi); case 44: ++this.state.pos;return this.finishToken(types.comma); case 91: ++this.state.pos;return this.finishToken(types.bracketL); case 93: ++this.state.pos;return this.finishToken(types.bracketR); case 123: if (this.hasPlugin("flow") && this.input.charCodeAt(this.state.pos + 1) === 124) { return this.finishOp(types.braceBarL, 2); } else { ++this.state.pos; return this.finishToken(types.braceL); } case 125: ++this.state.pos;return this.finishToken(types.braceR); case 58: if (this.hasPlugin("functionBind") && this.input.charCodeAt(this.state.pos + 1) === 58) { return this.finishOp(types.doubleColon, 2); } else { ++this.state.pos; return this.finishToken(types.colon); } case 63: ++this.state.pos;return this.finishToken(types.question); case 64: ++this.state.pos;return this.finishToken(types.at); case 96: // '`' ++this.state.pos; return this.finishToken(types.backQuote); case 48: // '0' var next = this.input.charCodeAt(this.state.pos + 1); if (next === 120 || next === 88) return this.readRadixNumber(16); // '0x', '0X' - hex number if (next === 111 || next === 79) return this.readRadixNumber(8); // '0o', '0O' - octal number if (next === 98 || next === 66) return this.readRadixNumber(2); // '0b', '0B' - binary number // Anything else beginning with a digit is an integer, octal // number, or float. case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57: // 1-9 return this.readNumber(false); // Quotes produce strings. case 34:case 39: // '"', "'" return this.readString(code); // Operators are parsed inline in tiny state machines. '=' (61) is // often referred to. `finishOp` simply skips the amount of // characters it is given as second argument, and returns a token // of the type given by its first argument. case 47: // '/' return this.readToken_slash(); case 37:case 42: // '%*' return this.readToken_mult_modulo(code); case 124:case 38: // '|&' return this.readToken_pipe_amp(code); case 94: // '^' return this.readToken_caret(); case 43:case 45: // '+-' return this.readToken_plus_min(code); case 60:case 62: // '<>' return this.readToken_lt_gt(code); case 61:case 33: // '=!' return this.readToken_eq_excl(code); case 126: // '~' return this.finishOp(types.prefix, 1); } this.raise(this.state.pos, "Unexpected character '" + codePointToString(code) + "'"); }; Tokenizer.prototype.finishOp = function finishOp(type, size) { var str = this.input.slice(this.state.pos, this.state.pos + size); this.state.pos += size; return this.finishToken(type, str); }; Tokenizer.prototype.readRegexp = function readRegexp() { var escaped = void 0, inClass = void 0, start = this.state.pos; for (;;) { if (this.state.pos >= this.input.length) this.raise(start, "Unterminated regular expression"); var ch = this.input.charAt(this.state.pos); if (lineBreak.test(ch)) { this.raise(start, "Unterminated regular expression"); } if (escaped) { escaped = false; } else { if (ch === "[") { inClass = true; } else if (ch === "]" && inClass) { inClass = false; } else if (ch === "/" && !inClass) { break; } escaped = ch === "\\"; } ++this.state.pos; } var content = this.input.slice(start, this.state.pos); ++this.state.pos; // Need to use `readWord1` because '\uXXXX' sequences are allowed // here (don't ask). var mods = this.readWord1(); if (mods) { var validFlags = /^[gmsiyu]*$/; if (!validFlags.test(mods)) this.raise(start, "Invalid regular expression flag"); } return this.finishToken(types.regexp, { pattern: content, flags: mods }); }; // Read an integer in the given radix. Return null if zero digits // were read, the integer value otherwise. When `len` is given, this // will return `null` unless the integer has exactly `len` digits. Tokenizer.prototype.readInt = function readInt(radix, len) { var start = this.state.pos, total = 0; for (var i = 0, e = len == null ? Infinity : len; i < e; ++i) { var code = this.input.charCodeAt(this.state.pos), val = void 0; if (code >= 97) { val = code - 97 + 10; // a } else if (code >= 65) { val = code - 65 + 10; // A } else if (code >= 48 && code <= 57) { val = code - 48; // 0-9 } else { val = Infinity; } if (val >= radix) break; ++this.state.pos; total = total * radix + val; } if (this.state.pos === start || len != null && this.state.pos - start !== len) return null; return total; }; Tokenizer.prototype.readRadixNumber = function readRadixNumber(radix) { this.state.pos += 2; // 0x var val = this.readInt(radix); if (val == null) this.raise(this.state.start + 2, "Expected number in radix " + radix); if (isIdentifierStart(this.fullCharCodeAtPos())) this.raise(this.state.pos, "Identifier directly after number"); return this.finishToken(types.num, val); }; // Read an integer, octal integer, or floating-point number. Tokenizer.prototype.readNumber = function readNumber(startsWithDot) { var start = this.state.pos, isFloat = false, octal = this.input.charCodeAt(this.state.pos) === 48; if (!startsWithDot && this.readInt(10) === null) this.raise(start, "Invalid number"); var next = this.input.charCodeAt(this.state.pos); if (next === 46) { // '.' ++this.state.pos; this.readInt(10); isFloat = true; next = this.input.charCodeAt(this.state.pos); } if (next === 69 || next === 101) { // 'eE' next = this.input.charCodeAt(++this.state.pos); if (next === 43 || next === 45) ++this.state.pos; // '+-' if (this.readInt(10) === null) this.raise(start, "Invalid number"); isFloat = true; } if (isIdentifierStart(this.fullCharCodeAtPos())) this.raise(this.state.pos, "Identifier directly after number"); var str = this.input.slice(start, this.state.pos), val = void 0; if (isFloat) { val = parseFloat(str); } else if (!octal || str.length === 1) { val = parseInt(str, 10); } else if (/[89]/.test(str) || this.state.strict) { this.raise(start, "Invalid number"); } else { val = parseInt(str, 8); } return this.finishToken(types.num, val); }; // Read a string value, interpreting backslash-escapes. Tokenizer.prototype.readCodePoint = function readCodePoint() { var ch = this.input.charCodeAt(this.state.pos), code = void 0; if (ch === 123) { var codePos = ++this.state.pos; code = this.readHexChar(this.input.indexOf("}", this.state.pos) - this.state.pos); ++this.state.pos; if (code > 0x10FFFF) this.raise(codePos, "Code point out of bounds"); } else { code = this.readHexChar(4); } return code; }; Tokenizer.prototype.readString = function readString(quote) { var out = "", chunkStart = ++this.state.pos; for (;;) { if (this.state.pos >= this.input.length) this.raise(this.state.start, "Unterminated string constant"); var ch = this.input.charCodeAt(this.state.pos); if (ch === quote) break; if (ch === 92) { // '\' out += this.input.slice(chunkStart, this.state.pos); out += this.readEscapedChar(false); chunkStart = this.state.pos; } else { if (isNewLine(ch)) this.raise(this.state.start, "Unterminated string constant"); ++this.state.pos; } } out += this.input.slice(chunkStart, this.state.pos++); return this.finishToken(types.string, out); }; // Reads template string tokens. Tokenizer.prototype.readTmplToken = function readTmplToken() { var out = "", chunkStart = this.state.pos; for (;;) { if (this.state.pos >= this.input.length) this.raise(this.state.start, "Unterminated template"); var ch = this.input.charCodeAt(this.state.pos); if (ch === 96 || ch === 36 && this.input.charCodeAt(this.state.pos + 1) === 123) { // '`', '${' if (this.state.pos === this.state.start && this.match(types.template)) { if (ch === 36) { this.state.pos += 2; return this.finishToken(types.dollarBraceL); } else { ++this.state.pos; return this.finishToken(types.backQuote); } } out += this.input.slice(chunkStart, this.state.pos); return this.finishToken(types.template, out); } if (ch === 92) { // '\' out += this.input.slice(chunkStart, this.state.pos); out += this.readEscapedChar(true); chunkStart = this.state.pos; } else if (isNewLine(ch)) { out += this.input.slice(chunkStart, this.state.pos); ++this.state.pos; switch (ch) { case 13: if (this.input.charCodeAt(this.state.pos) === 10) ++this.state.pos; case 10: out += "\n"; break; default: out += String.fromCharCode(ch); break; } ++this.state.curLine; this.state.lineStart = this.state.pos; chunkStart = this.state.pos; } else { ++this.state.pos; } } }; // Used to read escaped characters Tokenizer.prototype.readEscapedChar = function readEscapedChar(inTemplate) { var ch = this.input.charCodeAt(++this.state.pos); ++this.state.pos; switch (ch) { case 110: return "\n"; // 'n' -> '\n' case 114: return "\r"; // 'r' -> '\r' case 120: return String.fromCharCode(this.readHexChar(2)); // 'x' case 117: return codePointToString(this.readCodePoint()); // 'u' case 116: return "\t"; // 't' -> '\t' case 98: return "\b"; // 'b' -> '\b' case 118: return "\x0B"; // 'v' -> '\u000b' case 102: return "\f"; // 'f' -> '\f' case 13: if (this.input.charCodeAt(this.state.pos) === 10) ++this.state.pos; // '\r\n' case 10: // ' \n' this.state.lineStart = this.state.pos; ++this.state.curLine; return ""; default: if (ch >= 48 && ch <= 55) { var octalStr = this.input.substr(this.state.pos - 1, 3).match(/^[0-7]+/)[0]; var octal = parseInt(octalStr, 8); if (octal > 255) { octalStr = octalStr.slice(0, -1); octal = parseInt(octalStr, 8); } if (octal > 0) { if (!this.state.containsOctal) { this.state.containsOctal = true; this.state.octalPosition = this.state.pos - 2; } if (this.state.strict || inTemplate) { this.raise(this.state.pos - 2, "Octal literal in strict mode"); } } this.state.pos += octalStr.length - 1; return String.fromCharCode(octal);